21.3. Extending a Sensor Installer

21.3.1. Package Configuration for SensorInstaller code

After writing the installer.def.xml file for your new sensor, the next step is to implement a subclass of the SensorInstaller abstract class with your sensor-specific installation functionality. This subclass should be located in the "installer" directory. Our FooSensor SensorInstaller subclass would thus be called "FooSensorInstaller" with the following path:

C:\hackydev-svn\hackySensor_FooSensor\src\org\hackystat\sensor\foosensor\installer\FooSensorInstaller.java

21.3.2. Abstract Methods

The SensorInstaller superclass contains several abstract methods that must be provided with a sensor specific implementation in your subclass. These abstract methods are listed in Table 21.1, “SensorInstaller Abstract Methods”.

Table 21.1. SensorInstaller Abstract Methods

Abstract MethodDescription
installThe method that is called to install a sensor. See Section 21.3.3.1, “Overriding the Install Method” for an example.
updateThe method that is called to update a sensor. See Section 21.3.3.2, “Overriding the Update Method” for an example.
removeRemoves a sensor from the user's system. See Section 21.3.3.3, “Overriding the Remove Method” for an example.
isInstalledThe method that checks if a sensor is installed. See Section 21.3.3.4, “Overriding the isInstalled Method” for an example.
isEnabledReturns if a sensor is turned on. See Section 21.3.3.5, “Overriding the isEnabled Method” for an example.

21.3.3. Example Code

Provided below is example code of the AntSensorInstaller. This SensorInstaller was picked because it is characteristics of a large number of sensor installers in Hackystat. For examples of alternative ways to write a SensorInstaller, please take a look at the EclipseSensorInstaller or the VisualStudioSensorInstaller.

21.3.3.1. Overriding the Install Method

Example 21.3, “The AntSensorInstaller Install Method” is a typical install code example.

Example 21.3. The AntSensorInstaller Install Method

  public void install () throws InstallerException, ModelException {
    try {
      // make sure paths correct before installing sensor to the directory
      this.validateAllSensorPaths();  1
      Path path = this.pathManager.getPath("ANT_HOME"); 2
      
      // check and install sensorshell.jar if needed
      this.updateSensorshell(path.getLocation() + "/lib"); 3

      // download sensor and get the new version number 4
      this.downloadToTempDir(); 
      this.removeOldSensor(path.getLocation() + "/lib");
      this.moveSensorFile(this.getSensorJarfileName(), path.getLocation() + "/lib");
      this.sensor.setVersion(Version.getServerVersion());

      ConfigPersistor.getInstance().write(); // Write new information to hackyinstaller.xml.
    }
    catch (MalformedURLException e) {
      throw new InstallerException("Url to sensor is invalid.", e);
    }
    catch (DownloadException e) {
      throw new InstallerException(e.getMessage(), e);
    }
    catch (IOException e) {
      throw new InstallerException("Error contacting server for sensor files.", e);
    }
    catch (SAXException e) {
      throw new InstallerException("Could not retrieve version of sensor downloaded.", e);
    }
    catch (Exception e) {
      throw new InstallerException(e.getMessage(), e);
    }
    finally {
      Directory.deleteDir(this.sensorTempDir); // cleans up temporary directory
    }
  }

1

Validates all of the paths associated with a sensor. This method should be used to ensure that a sensor is installed to a path that is valid.

2

Retrieves the path(s) associated with this sensor. The name of the path string is specified in the <moduleName>.<installerName>.installer.def.xml file.

3

If the sensor requires the sensorshell.jar file, this call ensures that the most current version of sensorshell is installed. If an older version exists, the new version is downloaded.

4

Downloads the sensor to a temporary directory until the download is completed. When the download is finished, the old sensor is removed and the new sensor is moved to the path specified by the user. The current version number is then saved to the hackyinstaller.xml properties file.

21.3.3.2. Overriding the Update Method

Example 21.4, “The AntSensorInstaller Update Method” is a typical update code example. For the Ant sensor installer, the update method calls the install method because it is easier to download a new copy of the sensor jar file, which is very small in size, than to update the current jar file. If the sensor you are installing requires a different update procedure, the update method is where it should be done.

Example 21.4. The AntSensorInstaller Update Method

  public void update () throws ModelException, InstallerException {
    if (!this.hasLatestVersion()) {
      this.install();
    }
  }

21.3.3.3. Overriding the Remove Method

Example 21.5, “The AntSensorInstaller remove Method” is a typical remove code example. The AntSensorInstaller removes the sensor by finding the location of the sensor.ant.jar file and deletes it. The information associated with the sensor, such as the version number, is then cleared.

Example 21.5. The AntSensorInstaller remove Method

  public void remove () throws ModelException, InstallerException {
    try {
      Path path = this.pathManager.getPath("ANT_HOME");
      File buildSensor = new File(path.getLocation() + this.relativeToolPath);
      // Check if sensor exists
      if (buildSensor.exists()) {
        boolean removed = buildSensor.delete();

        if (!removed) {
          throw new SensorRemoveException("Error removing build sensor.  File may be in use.");
        }
        else { // clears information about the sensor
          // Set version of sensor blank
          this.sensor.setVersion("");

          // Write new information to hackyinstaller.xml.
          ConfigPersistor configHandler = ConfigPersistor.getInstance();
          configHandler.write();
        }
      }
      else {
        throw new SensorRemoveException("Build sensor does not appear to be installed.");
      }
    }
    catch (SensorRemoveException e) {
      throw new InstallerException(e.getMessage(), e);
    }
  }

21.3.3.4. Overriding the isInstalled Method

Example 21.6, “The AntSensorInstaller isInstalled Method” is a typical isInstalled code example. For the Ant sensor installer, the isInstalled method verifys if the sensor.ant.jar file exists in the directory specified by the user. If it does not exist, false is returned.

Example 21.6. The AntSensorInstaller isInstalled Method

  public boolean isInstalled () throws ModelException {
    boolean isInstalled = false;
    Path path = this.pathManager.getPath("ANT_HOME");

    File buildSensor = new File(path.getLocation() + this.relativeToolPath);
    if (buildSensor.exists()) {
      isInstalled = true;
    }
    return isInstalled;
  }

21.3.3.5. Overriding the isEnabled Method

Example 21.7, “The AntSensorInstaller isEnabled Method” is a typical isEnabled code example. To check if a sensor is enabled, a simple check of the 'ENABLE_ANT_SENSOR' property is implemented. All hackystat sensors are associated with an 'ENABLE.SENSOR_NAME.SENSOR' property that is found in the user.home/.hackystat/sensor.properties file. The PropertyManager is the object that contains a list of all the properties that are associated with a sensor.

Example 21.7. The AntSensorInstaller isEnabled Method

  public boolean isEnabled () {
    PropertyManager properties = this.sensor.getPropertyManager();
    Property property = properties.getProperty("ENABLE_ANT_SENSOR");

    return Boolean.valueOf(property.getValue()).booleanValue();
  }