public void endElement(String namespaceURI, String localName, String qName)
     throws SAXException {
   //
   //   if </target> then
   //       create TargetHistory object and add to hashtable
   //           if corresponding output file exists and
   //           has the same timestamp
   //
   if (qName.equals("target")) {
     if (config != null && output != null) {
       File existingFile = new File(baseDir, output);
       //
       //   if the corresponding files doesn't exist or has a
       // different
       //      modification time, then discard this record
       if (existingFile.exists()) {
         //
         //   would have expected exact time stamps
         //      but have observed slight differences
         //      in return value for multiple evaluations of
         //      lastModified(). Check if times are within
         //      a second
         long existingLastModified = existingFile.lastModified();
         if (!CUtil.isSignificantlyBefore(existingLastModified, outputLastModified)
             && !CUtil.isSignificantlyAfter(existingLastModified, outputLastModified)) {
           SourceHistory[] sourcesArray = new SourceHistory[sources.size()];
           sources.copyInto(sourcesArray);
           TargetHistory targetHistory =
               new TargetHistory(config, output, outputLastModified, sourcesArray);
           history.put(output, targetHistory);
         }
       }
     }
     output = null;
     sources.setSize(0);
   } else {
     //
     //   reset config so targets not within a processor element
     //      don't pick up a previous processors signature
     //
     if (qName.equals("processor")) {
       config = null;
     }
   }
 }
 // FREEHEP added synchronized
 private synchronized void update(String configId, String outputName, String[] sources) {
   File outputFile = new File(outputDir, outputName);
   //
   //   if output file doesn't exist or predates the start of the
   //        compile step (most likely a compilation error) then
   //        do not write add a history entry
   //
   if (outputFile.exists()) {
     dirty = true;
     history.remove(outputName);
     SourceHistory[] sourceHistories = new SourceHistory[sources.length];
     for (int i = 0; i < sources.length; i++) {
       File sourceFile = new File(sources[i]);
       long lastModified = sourceFile.lastModified();
       String relativePath = CUtil.getRelativePath(outputDirPath, sourceFile);
       sourceHistories[i] = new SourceHistory(relativePath, lastModified);
     }
     TargetHistory newHistory =
         new TargetHistory(configId, outputName, outputFile.lastModified(), sourceHistories);
     history.put(outputName, newHistory);
   }
 }
 // FREEHEP added synchronized
 public synchronized void update(TargetInfo linkTarget) {
   File outputFile = linkTarget.getOutput();
   String outputName = outputFile.getName();
   //
   //   if output file doesn't exist or predates the start of the
   //        compile or link step (most likely a compilation error) then
   //        do not write add a history entry
   //
   if (outputFile.exists()
       && !CUtil.isSignificantlyBefore(outputFile.lastModified(), historyFile.lastModified())) {
     dirty = true;
     history.remove(outputName);
     SourceHistory[] sourceHistories = linkTarget.getSourceHistories(outputDirPath);
     TargetHistory newHistory =
         new TargetHistory(
             linkTarget.getConfiguration().getIdentifier(),
             outputName,
             outputFile.lastModified(),
             sourceHistories);
     history.put(outputName, newHistory);
   }
 }
 /**
  * Returns true if the if and unless conditions (if any) are satisfied.
  *
  * @return true if this object is active.
  */
 public boolean isActive() {
   return CUtil.isActive(getProject(), ifCond, unlessCond);
 }
 public void commit() throws IOException {
   //
   //   if not dirty, no need to update file
   //
   if (dirty) {
     //
     //   build (small) hashtable of config id's in history
     //
     Hashtable configs = new Hashtable(20);
     Enumeration elements = history.elements();
     while (elements.hasMoreElements()) {
       TargetHistory targetHistory = (TargetHistory) elements.nextElement();
       String configId = targetHistory.getProcessorConfiguration();
       if (configs.get(configId) == null) {
         configs.put(configId, configId);
       }
     }
     FileOutputStream outStream = new FileOutputStream(historyFile);
     OutputStreamWriter outWriter;
     //
     //   early VM's don't support UTF-8 encoding
     //       try and fallback to the default encoding
     //           otherwise
     String encodingName = "UTF-8";
     try {
       outWriter = new OutputStreamWriter(outStream, "UTF-8");
     } catch (UnsupportedEncodingException ex) {
       outWriter = new OutputStreamWriter(outStream);
       encodingName = outWriter.getEncoding();
     }
     BufferedWriter writer = new BufferedWriter(outWriter);
     writer.write("<?xml version='1.0' encoding='");
     writer.write(encodingName);
     writer.write("'?>\n");
     writer.write("<history>\n");
     StringBuffer buf = new StringBuffer(200);
     Enumeration configEnum = configs.elements();
     while (configEnum.hasMoreElements()) {
       String configId = (String) configEnum.nextElement();
       buf.setLength(0);
       buf.append("   <processor signature=\"");
       buf.append(CUtil.xmlAttribEncode(configId));
       buf.append("\">\n");
       writer.write(buf.toString());
       elements = history.elements();
       while (elements.hasMoreElements()) {
         TargetHistory targetHistory = (TargetHistory) elements.nextElement();
         if (targetHistory.getProcessorConfiguration().equals(configId)) {
           buf.setLength(0);
           buf.append("      <target file=\"");
           buf.append(CUtil.xmlAttribEncode(targetHistory.getOutput()));
           buf.append("\" lastModified=\"");
           buf.append(Long.toHexString(targetHistory.getOutputLastModified()));
           buf.append("\">\n");
           writer.write(buf.toString());
           SourceHistory[] sourceHistories = targetHistory.getSources();
           for (int i = 0; i < sourceHistories.length; i++) {
             buf.setLength(0);
             buf.append("         <source file=\"");
             buf.append(CUtil.xmlAttribEncode(sourceHistories[i].getRelativePath()));
             buf.append("\" lastModified=\"");
             buf.append(Long.toHexString(sourceHistories[i].getLastModified()));
             buf.append("\"/>\n");
             writer.write(buf.toString());
           }
           writer.write("      </target>\n");
         }
       }
       writer.write("   </processor>\n");
     }
     writer.write("</history>\n");
     writer.close();
     dirty = false;
   }
 }