001    package org.hackystat.telemetry.service.prefetch;
002    
003    import java.io.File;
004    import java.io.FileInputStream;
005    import java.io.InputStream;
006    import java.util.ArrayList;
007    import java.util.List;
008    import java.util.logging.Logger;
009    
010    import javax.xml.bind.JAXBContext;
011    import javax.xml.bind.Unmarshaller;
012    
013    import org.hackystat.telemetry.analyzer.configuration.ExtensionFileFilter;
014    import org.hackystat.telemetry.service.prefetch.jaxb.TelemetryPrefetch;
015    import org.hackystat.telemetry.service.server.Server;
016    import org.hackystat.telemetry.service.server.ServerProperties;
017    import org.hackystat.utilities.stacktrace.StackTrace;
018    
019    /**
020     * Reads in the XML files (if any) containing prefetch information, and sets up a timer task to 
021     * prefetch (i.e. run) these chart analyses once a day.  If RunOnStartup is true, then the prefetch
022     * tasks are run immediately.  
023     * @author Philip Johnson 
024     */
025    public class PrefetchManager {
026      /** This telemetry server. */
027      Server server;
028      /** The logger for this telemetry server. */
029      Logger logger;
030      /** The list of TelemetryPrefetch JAXB instances. */
031      List<TelemetryPrefetch> telemetryPrefetchList = new ArrayList<TelemetryPrefetch>();
032      /** The list of DailyTimer instances, one per TelemetryPrefetch file. */
033      List<DailyTimer> timers = new ArrayList<DailyTimer>();
034      
035      /**
036       * Constructs a PrefetchManager, which reads in the Telemetry prefetch XML files and sets up 
037       * a DailyTimer task for each XML file found.
038       * @param server This Telemetry analysis server.
039       */
040      public PrefetchManager(Server server) {
041        this.server = server;
042        this.logger = server.getLogger();
043        this.telemetryPrefetchList = getTelemetryPrefetchList();
044        setupTimers();
045      }
046      
047      /**
048       * Find any Prefetch XML files and constructs the Java instances for them, returning them
049       * as a List of TelemetryPrefetch instances. 
050       * @return The list of TelemetryPrefetch instances, or an empty list if none found.
051       */
052      private List<TelemetryPrefetch> getTelemetryPrefetchList() {
053        List<TelemetryPrefetch> telemetryPrefetchList = new ArrayList<TelemetryPrefetch>();
054        String defDirString = server.getServerProperties().get(ServerProperties.PREFETCH_DIR_KEY);
055        if (defDirString == null || !((new File(defDirString)).exists())) {
056          server.getLogger().info("Telemetry prefetch directory not available: " + defDirString);
057        }
058        else {
059          // Read in the any prefetch definitions from the prefetch directory.
060          File defDir = new File(defDirString);
061          File[] xmlFiles = defDir.listFiles(new ExtensionFileFilter(".xml"));
062          FileInputStream fileStream = null;
063          for (int i = 0; i < xmlFiles.length; i++) {
064            try {
065              // Get the TelemetryPrefetch instance from the file.
066              this.logger.info("Reading telemetry prefetch data from: " + xmlFiles[i].getName());
067              fileStream = new FileInputStream(xmlFiles[i]);
068              telemetryPrefetchList.add(getDefinitions(fileStream));
069              fileStream.close();
070            }
071            catch (Exception e) {
072              this.logger.info("Error reading definitions from: " + xmlFiles[i] + " " + e);
073              try {
074                fileStream.close();
075              }
076              catch (Exception f) { 
077                this.logger.info("Failed to close: " + fileStream.toString() + " " + e);
078              }
079            }
080          }
081        }
082        return telemetryPrefetchList;
083      }
084    
085      /**
086       * Initializes the list of DailyTimer instances. 
087       */
088      private void setupTimers() {
089        for (TelemetryPrefetch prefetch : telemetryPrefetchList) {
090          PrefetchTask task = new PrefetchTask(prefetch, this.logger, this.server.getHostName());
091          DailyTimer timer = new DailyTimer(prefetch.getMinutesAfterMidnight(), task); 
092          this.logger.info("Prefetch '" + prefetch.getName() + "' scheduled for: " + 
093              timer.getTriggerTime());
094          this.timers.add(timer);
095          if ("True".equalsIgnoreCase(prefetch.getRunOnStartup())) {
096            this.logger.info("Run on startup is true, so invoking: " + prefetch.getName());
097            task.run();
098          }
099        }
100      }
101      
102      /**
103       * Returns a TelemetryPrefetch object constructed from defStream, or null if unsuccessful.
104       * @param defStream The input stream containing a TelemetryPrefetch object in XML format.
105       * @return The TelemetryPrefetch object.
106       */
107      private TelemetryPrefetch getDefinitions (InputStream defStream) {
108        // Read in the definitions file.
109        try {
110          JAXBContext jaxbContext = JAXBContext
111          .newInstance(org.hackystat.telemetry.service.prefetch.jaxb.ObjectFactory.class);
112          Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
113          return (TelemetryPrefetch) unmarshaller.unmarshal(defStream);
114        } 
115        catch (Exception e) {
116          this.logger.severe("Failed to get TelemetryPrefetch from stream" + StackTrace.toString(e));
117        }
118        return null;
119      }
120    
121    }