VYPR
Critical severity9.8NVD Advisory· Published Jun 15, 2026

CVE-2026-48114

CVE-2026-48114

Description

Unauthenticated SQL injection in Metacat 2.x harvesterRegistration endpoint allows full database compromise; fixed in 3.0.0.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Unauthenticated SQL injection in Metacat 2.x harvesterRegistration endpoint allows full database compromise; fixed in 3.0.0.

Vulnerability

Metacat versions 2.0.0 through 2.19.1 contain an unauthenticated SQL injection in the /harvesterRegistration endpoint. The HarvesterRegistration.dbInsert() method builds an INSERT statement against HARVEST_SITE_SCHEDULE via string concatenation, using a quoteString() helper that performs raw single-quote wrapping without escaping. Three request parameters reach the sink: unit, contactEmail, and documentListURL. The servlet does not verify LDAP identity, allowing the vulnerable insert to proceed. [1]

Exploitation

An attacker can send a crafted HTTP request to the /harvesterRegistration endpoint with malicious payloads in any of the three parameters. Because the PostgreSQL backend permits stacked queries via Statement.executeUpdate(), the attacker can execute arbitrary SQL statements. Additionally, a second-order SQL injection exists: an attacker-controlled documentListURL is fetched by the scheduled harvester, and the parsed `` element flows unsanitized. [1]

Impact

Successful exploitation allows full read/write/execute access in the Metacat database context, including credentials, session material, and the xml_documents corpus. This can lead to complete compromise of the Metacat instance and its data. [1]

Mitigation

The vulnerability was remediated in Metacat 3.0.0 (commit 820d595) via removal of the harvesterClient package. [2] The 2.x branch remains vulnerable and will not be backported. Users should upgrade to Metacat 3.0.0 or later (preferably the current release >= 3.4.0). As a workaround, restrict access to the old 1.x API endpoints. [1]

AI Insight generated on Jun 15, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected products

2
  • Nceas/Metacatreferences2 versions
    (expand)+ 1 more
    • (no CPE)
    • (no CPE)range: >=2.0.0, <3.0.0

Patches

1
820d595309b3

Removed the harvester client for LTER.

https://github.com/nceas/metacatJing TaoSep 15, 2023via nvd-ref
16 files changed · +0 6471
  • src/edu/ucsb/nceas/metacat/harvesterClient/HarvestDetailLog.java+0 125 removed
    @@ -1,125 +0,0 @@
    -/**
    - *  '$RCSfile$'
    - *  Copyright: 2004 University of New Mexico and the 
    - *                  Regents of the University of California
    - *
    - *   '$Author$'
    - *     '$Date$'
    - * '$Revision$'
    - *
    - * This program is free software; you can redistribute it and/or modify
    - * it under the terms of the GNU General Public License as published by
    - * the Free Software Foundation; either version 2 of the License, or
    - * (at your option) any later version.
    - *
    - * This program is distributed in the hope that it will be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write to the Free Software
    - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    - */
    -
    -package edu.ucsb.nceas.metacat.harvesterClient;
    -
    -import java.io.PrintStream;
    -import java.sql.Connection;
    -import java.sql.SQLException;
    -import java.sql.Statement;
    -
    -/**
    - * HarvestDetailLog manages data and operations corresponding to the
    - * HARVEST_DETAIL_LOG table. It records errors encountered while attempting
    - * to harvest a particular EML document.
    - * 
    - * @author  costa
    - */
    -public class HarvestDetailLog {
    -
    -  private Connection conn;    
    -  private Harvester harvester;              // The parent Harvester object
    -  private int detailLogID;
    -  private int harvestLogID;
    -  private HarvestDocument harvestDocument;  // The associated HarvestDocument
    -  private String errorMessage;
    -    
    -
    -  /** 
    -   * Creates a new instance of HarvestDetailLog and inserts the data into
    -   * the HARVEST_DETAIL_LOG table.
    -   *
    -   * @param  harvester       the Harvester parent object
    -   * @param  conn            the database connection
    -   * @param  detailLogID     primary key in the HARVEST_LOG table
    -   * @param  harvestLogID    foreign key value matching the HARVEST_LOG table
    -   * @param  harvestDocument HarvestDocument object that generated an error
    -   * @param  errorMessage    text of the error message
    -   */
    -  public HarvestDetailLog(Harvester       harvester,
    -                          Connection      conn,
    -                          int             detailLogID,
    -                          int             harvestLogID,
    -                          HarvestDocument harvestDocument,
    -                          String          errorMessage
    -                         ) {
    -    this.harvester = harvester;
    -    this.conn = conn;
    -    this.detailLogID = detailLogID;
    -    this.harvestLogID = harvestLogID;
    -    this.harvestDocument = harvestDocument;
    -    this.errorMessage = errorMessage;
    -  }
    -    
    -
    -  /**
    -   * Inserts a new entry into the HARVEST_DETAIL_LOG table, based on the 
    -   * contents of this HarvestDetailLog object.
    -   */
    -  void dbInsertHarvestDetailLogEntry() {
    -    String dequotedMessage;
    -    String insertString;
    -		Statement stmt;
    -    
    -    dequotedMessage = harvester.dequoteText(errorMessage);
    -
    -    // Set the value of the HARVEST_LOG_ID to the current time in UTC seconds
    -    insertString = "INSERT INTO HARVEST_DETAIL_LOG " +
    -                   "(DETAIL_LOG_ID, HARVEST_LOG_ID, SCOPE," + 
    -                   " IDENTIFIER, REVISION," +
    -                   " DOCUMENT_URL, ERROR_MESSAGE, DOCUMENT_TYPE) " +
    -                   "values(" +
    -                   detailLogID + ", " +
    -                   harvestLogID + ", " +
    -                   "'" + harvestDocument.scope + "', " +
    -                   harvestDocument.identifier + ", " +
    -                   harvestDocument.revision + ", " +
    -                   "'" + harvestDocument.documentURL + "', " +
    -                   "'" + dequotedMessage + "'," +
    -                   "'" + harvestDocument.documentType + "'" +
    -                   ")";
    -                   
    -		try {
    -			stmt = conn.createStatement();
    -			stmt.executeUpdate(insertString);
    -			stmt.close();
    -		}
    -    catch(SQLException e) {
    -			System.out.println("SQLException: " + e.getMessage());
    -		}
    -  }
    -
    -
    -  /**
    -   * Prints the contents of this HarvestLog object. Used in generating reports.
    -   * 
    -   * @param out   the PrintStream to write to
    -   */
    -  public void printOutput(PrintStream out) {
    -    out.println("* detailLogID:          " + detailLogID);
    -    out.println("* errorMessage:         " + errorMessage);
    -    harvestDocument.printOutput(out);
    -  }
    -
    -}
    
  • src/edu/ucsb/nceas/metacat/harvesterClient/HarvestDocument.java+0 402 removed
    @@ -1,402 +0,0 @@
    -/**
    - *  '$RCSfile$'
    - *  Copyright: 2004 University of New Mexico and the 
    - *                  Regents of the University of California
    - *
    - *   '$Author$'
    - *     '$Date$'
    - * '$Revision$'
    - *
    - * This program is free software; you can redistribute it and/or modify
    - * it under the terms of the GNU General Public License as published by
    - * the Free Software Foundation; either version 2 of the License, or
    - * (at your option) any later version.
    - *
    - * This program is distributed in the hope that it will be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write to the Free Software
    - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    - */
    -
    -package edu.ucsb.nceas.metacat.harvesterClient;
    -
    -import java.io.InputStream;
    -import java.io.InputStreamReader;
    -import java.io.IOException;
    -import java.io.PrintStream;
    -import java.io.StringReader;
    -import java.net.MalformedURLException;
    -import java.net.URL;
    -import java.sql.Connection;
    -import java.sql.ResultSet;
    -import java.sql.SQLException;
    -import java.sql.Statement;
    -
    -import edu.ucsb.nceas.metacat.client.InsufficientKarmaException;
    -import edu.ucsb.nceas.metacat.client.Metacat;
    -import edu.ucsb.nceas.metacat.client.MetacatException;
    -import edu.ucsb.nceas.metacat.client.MetacatInaccessibleException;
    -import edu.ucsb.nceas.utilities.IOUtil;
    -
    -
    -/**
    - * HarvestDocument manages operations and data for a single document to be
    - * harvested.
    - * 
    - * @author  costa
    - */
    -public class HarvestDocument {
    -
    -   
    -  private String docid;                      // scope + identifier
    -  private String docidFull;                  // scope + identifier + revision
    -  String documentType;
    -  String documentURL;
    -  private Harvester harvester;
    -  private HarvestSiteSchedule harvestSiteSchedule;
    -  int identifier;
    -  int revision;
    -  String scope;
    -
    -  /* These booleans keep track of status information. They are used when
    -   * generating email reports.
    -   */
    -  boolean accessError = false;
    -  boolean inserted = false;
    -  boolean metacatHasIt = false;
    -  boolean updated = false;
    -  boolean uploadError = false;
    -    
    -
    -  /**
    -   * Creates a new instance of HarvestDocument. Initialized with the data
    -   * that was read from a single <document> element in site document list.
    -   * 
    -   * @param harvester            the parent Harvester object
    -   * @param harvestSiteSchedule  the parent HarvestSiteSchedule object
    -   * @param scope                the value of the <scope> element
    -   * @param identifier           the value of the <identifier> element
    -   * @param revision             the value of the <revision> element
    -   * @param documentType         the value of the <documentType> element
    -   * @param documentURL          the value of the <documentURL> element
    -   */
    -  public HarvestDocument (
    -                          Harvester harvester,
    -                          HarvestSiteSchedule harvestSiteSchedule,
    -                          String scope,
    -                          int identifier,
    -                          int revision,
    -                          String documentType,
    -                          String documentURL
    -                        ) {
    -    this.harvester = harvester;
    -    this.harvestSiteSchedule = harvestSiteSchedule;
    -    this.documentType = documentType;
    -    this.documentURL = documentURL;
    -    this.scope = scope;
    -    this.identifier = identifier;
    -    this.revision = revision;
    -    
    -    this.docid = scope + "." + identifier;
    -    this.docidFull = this.docid + "." + revision;
    -  }
    -
    -
    -  /**
    -   * Retrieve the document from the site using its <documentURL> value.
    -   * 
    -   * @return   A StringReader containing the document string.
    -   */
    -  public StringReader getSiteDocument() {
    -    String documentString;
    -    InputStream inputStream;
    -    InputStreamReader inputStreamReader;
    -    StringReader stringReader = null;
    -    URL url;
    -    
    -    try {
    -      url = new URL(documentURL);
    -      inputStream = url.openStream();
    -      inputStreamReader = new InputStreamReader(inputStream);
    -      documentString = IOUtil.getAsString(inputStreamReader, true);
    -      stringReader = new StringReader(documentString);
    -      harvester.addLogEntry(0,
    -                            "Retrieved: " + documentURL, 
    -                            "harvester.GetDocSuccess", 
    -                            harvestSiteSchedule.siteScheduleID, 
    -                            null, 
    -                            "");
    -    }
    -    catch (MalformedURLException e) {
    -      accessError = true;
    -      harvester.addLogEntry(1, "MalformedURLException", "harvester.GetDocError", 
    -                            harvestSiteSchedule.siteScheduleID, this, 
    -                            "MalformedURLException: " + e.getMessage());
    -    }
    -    catch (IOException e) {
    -      accessError = true;
    -      harvester.addLogEntry(1, "IOException", "harvester.GetDocError", 
    -                            harvestSiteSchedule.siteScheduleID, this, 
    -                            "IOException: " + e.getMessage());
    -    }
    -    
    -    return stringReader;
    -  }
    -    
    -
    -  /**
    -   * Harvest the document from the site. Unless Metacat already has the
    -   * document, retrieve the document from the site and put (insert or
    -   * update) it to Metacat. If Metacat already has the document, determine
    -   * the highest revision stored in Metacat so that this can be reported
    -   * back to the user.
    -   */
    -  public void harvestDocument() {
    -    int highestRevision;
    -    boolean insert = false;
    -    String metacatReturnString;
    -    StringReader stringReader;
    -    boolean update = false;
    -
    -    /* If metacat already has this document, determine the highest revision in
    -     * metacat and report it to the user; else, insert or delete the document 
    -     * into metacat.
    -     */
    -    highestRevision = metacatHighestRevision();
    -
    -    if (highestRevision == -1) {
    -      insert = true;
    -    }
    -    else if (revision > highestRevision) {
    -      update = true;
    -    }
    -    else {
    -      metacatHasIt = true;
    -      harvester.addLogEntry(0, 
    -                            "Attempting to update " + docid + " to revision " + 
    -                            revision + ". Metacat has document revision " +
    -                            highestRevision + ".", 
    -                            "harvester.MetacatHasDoc", 
    -                            harvestSiteSchedule.siteScheduleID, 
    -                            null, 
    -                            "");
    -    }
    -    
    -    if (insert || update) {
    -      stringReader = getSiteDocument();
    -      if (stringReader != null) {
    -        if (validateDocument()) {
    -          putMetacatDocument(insert, update, stringReader);
    -        }
    -      }
    -    }
    -  }
    -  
    -
    -  /**
    -   * Boolean to determine whether the string returned by the Metacat client for
    -   * an insert or update operation indicates that the operation succeeded.
    -   * 
    -   * @param metacatReturnString     The string returned by the Metacat client.
    -   * @return true if the return string indicates success, else false
    -   */
    -  private boolean isMetacatSuccessString(String metacatReturnString) {
    -    boolean isMetacatSuccessString = false;
    -    
    -    if ((metacatReturnString != null) &&
    -        (metacatReturnString.contains("<success>"))
    -       ) {
    -      isMetacatSuccessString = true;
    -    }
    -    
    -    return isMetacatSuccessString;
    -  }
    - 
    - 
    -  /**
    -   * Logs a metacat document error to the harvest detail log. 
    -   *
    -   * @param insert               true if insert operation, false is update
    -   * @param metacatReturnString  string returned from the insert or update
    -   * @param exceptionName        name of the exception class
    -   * @param e                    the exception object
    -   */
    -  private void logMetacatError (boolean insert, 
    -                                String metacatReturnString,
    -                                String exceptionName,
    -                                Exception e
    -                               ) {
    -    uploadError = true;
    -
    -    if (insert) {
    -      harvester.addLogEntry(1, 
    -                            metacatReturnString,
    -                            "harvester.InsertDocError",
    -                            harvestSiteSchedule.siteScheduleID,
    -                            this,
    -                            exceptionName + ": " + e.getMessage());
    -    }
    -    else {
    -      harvester.addLogEntry(1, 
    -                            metacatReturnString,
    -                            "harvester.UpdateDocError",
    -                            harvestSiteSchedule.siteScheduleID,
    -                            this,
    -                            exceptionName + ": " + e.getMessage());
    -    }
    -  }
    -  
    -
    -  /**
    -   * Determines the highest revision that Metacat has for this document.
    -   * 
    -   * @return  int representing the highest revision for this document in
    -   *          Metacat. Returns -1 if Metacat does not currently hold the
    -   *          document.
    -   */
    -  public int metacatHighestRevision() {
    -    Connection conn = harvester.getConnection();
    -    int         highestRevision = -1;
    -		String query = "SELECT REV FROM XML_DOCUMENTS WHERE DOCID = " +
    -                   "'" + docid + "'";
    -		Statement stmt;
    -    
    -		try {
    -			stmt = conn.createStatement();							
    -			ResultSet rs = stmt.executeQuery(query);
    -	
    -			while (rs.next()) {
    -				highestRevision = rs.getInt("REV");
    -			}
    -	
    -			stmt.close();	
    -		}
    -    catch(SQLException e) {
    -			System.out.println("SQLException: " + e.getMessage());
    -    }
    -
    -    return highestRevision;
    -  }
    -  
    -  
    -  /**
    -   * Print the data fields and values in this HarvestDocument object.
    -   * 
    -   * @param out   the PrintStream to write to
    -   */
    -  public void printOutput(PrintStream out) {
    -    out.println("* scope:                " + scope);
    -    out.println("* identifier:           " + identifier);
    -    out.println("* revision:             " + revision);
    -    out.println("* documentType:         " + documentType);
    -    out.println("* documentURL:          " + documentURL);
    -  }
    - 
    - 
    -  /**
    -   * Print the document URL following by its scope.identifier.revision.
    -   * Used for report generation.
    -   * 
    -   * @param out   the PrintStream to write to
    -   */
    -  public void prettyPrint(PrintStream out) {
    -    out.println("*   " + docidFull + "  (" + documentURL + ")");
    -  }
    - 
    - 
    -  /**
    -   * Insert or update this document to Metacat. If revision equals 1, do an
    -   * insert; otherwise, do an update.
    -   * 
    -   * @param insert       true if this is an insert operation
    -   * @param update       true if this is an update operation
    -   * @param stringReader the StringReader object holding the document text
    -   */
    -  private void putMetacatDocument(boolean insert,
    -                                  boolean update, 
    -                                  StringReader stringReader) {
    -    Metacat metacat = harvester.metacat;
    -    String metacatReturnString = "";
    -    
    -    if (harvester.connectToMetacat()) {
    -      try {
    -        String harvestOperationCode = "";
    -        
    -        if (insert) {
    -          harvestOperationCode = "harvester.InsertDocSuccess";
    -          metacatReturnString = metacat.insert(docidFull, stringReader, null);
    -          this.inserted = true;
    -        }
    -        else if (update) {
    -          harvestOperationCode = "harvester.UpdateDocSuccess";
    -          metacatReturnString = metacat.update(docidFull, stringReader, null);
    -          this.updated = true;
    -        }
    -        
    -        if (isMetacatSuccessString(metacatReturnString)) {
    -          String message = docidFull + " : " + metacatReturnString;
    -          harvester.addLogEntry(0, message, harvestOperationCode, 
    -                                harvestSiteSchedule.siteScheduleID, null, "");
    -        }
    -        else {
    -          this.inserted = false;
    -          this.updated = false;
    -          final String exceptionName = "UnreportedMetacatException";
    -          final String exceptionMessage = 
    -                    "Metacat insert/update failed without reporting an exception";
    -          Exception e = new Exception(exceptionMessage);
    -          logMetacatError(insert, metacatReturnString, exceptionName, e);
    -        }
    -      }
    -      catch (MetacatInaccessibleException e) {
    -        logMetacatError(insert, metacatReturnString, 
    -                        "MetacatInaccessibleException", e);
    -      }
    -      catch (InsufficientKarmaException e) {
    -        logMetacatError(insert, metacatReturnString, 
    -                        "InsufficientKarmaException", e);
    -      }
    -      catch (MetacatException e) {
    -        logMetacatError(insert, metacatReturnString, "MetacatException", e);
    -      }
    -      catch (IOException e) {
    -        logMetacatError(insert, metacatReturnString, "IOException", e);
    -      }
    -      catch (Exception e) {
    -        logMetacatError(insert, metacatReturnString, "Exception", e);
    -      }
    -    }
    -  }
    -  
    -  
    -  /**
    -   * Validate the document to determine whether it is valid EML prior to 
    -   * inserting or updating it to Metacat. This is QA/QC measure. 
    -   * Not yet implemented.
    -   * 
    -   * @return  true if the document is valid EML, otherwise false
    -   */
    -  private boolean validateDocument () {
    -    boolean success = true;
    -    
    -    /*if (success) {
    -      harvester.addLogEntry(0, 
    -                            "Validated: " + documentURL, 
    -                            "harvester.ValidateDocSuccess", 
    -                            harvestSiteSchedule.siteScheduleID, 
    -                            null, 
    -                            "");
    -    }
    -    else {
    -      harvester.addLogEntry(1, "Error validating document", "harvester.ValidateDocError", 
    -                            harvestSiteSchedule.siteScheduleID, this, "");
    -    }*/
    -    
    -    return success;
    -  }
    -  
    -}
    
  • src/edu/ucsb/nceas/metacat/harvesterClient/Harvester.java+0 1042 removed
    @@ -1,1042 +0,0 @@
    -/**
    - *  '$RCSfile$'
    - *  Copyright: 2004 University of New Mexico and the 
    - *                  Regents of the University of California
    - *
    - *   '$Author$'
    - *     '$Date$'
    - * '$Revision$'
    - *
    - * This program is free software; you can redistribute it and/or modify
    - * it under the terms of the GNU General Public License as published by
    - * the Free Software Foundation; either version 2 of the License, or
    - * (at your option) any later version.
    - *
    - * This program is distributed in the hope that it will be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write to the Free Software
    - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    - */
    -
    -package edu.ucsb.nceas.metacat.harvesterClient;
    -
    -import com.oreilly.servlet.MailMessage;
    -import java.io.IOException;
    -import java.io.PrintStream;
    -import java.sql.Connection;
    -import java.sql.DriverManager;
    -import java.sql.ResultSet;
    -import java.sql.SQLException;
    -import java.sql.SQLWarning;
    -import java.sql.Statement;
    -import java.util.ArrayList;
    -import java.text.SimpleDateFormat;
    -import java.util.Date;
    -
    -import edu.ucsb.nceas.metacat.client.Metacat;
    -import edu.ucsb.nceas.metacat.client.MetacatFactory;
    -import edu.ucsb.nceas.metacat.client.MetacatInaccessibleException;
    -import edu.ucsb.nceas.metacat.properties.PropertyService;
    -import edu.ucsb.nceas.metacat.util.SystemUtil;
    -import edu.ucsb.nceas.utilities.PropertyNotFoundException;
    -
    -/**
    - * Harvester is the main class for the Harvester application. The main
    - * method creates a single Harvester object which drives the application.
    - * 
    - * @author    costa
    - * 
    - */
    -public class Harvester {
    -
    -  /*
    -   * Class fields
    -   */
    -
    -  public static final String filler = "*";
    -  private static boolean keepRunning = true;
    -  public static final String marker =
    -"*****************************************************************************";
    -//  public static PropertyService propertyService = null;
    -  private static String schemaLocation = null;
    -   
    -
    -  /* 
    -   * Class methods
    -   */
    -   
    -
    -  /**
    -   * Constructor. Creates a new instance of Harvester.
    -   */
    -  public Harvester() {
    -  }
    -    
    -
    -  /**
    -   * Loads Harvester options from a configuration file.
    -   */
    -  public static void loadProperties(String metacatContextDir) {
    -
    -    try {
    -    	PropertyService.getInstance(metacatContextDir + "/WEB-INF");
    -    } 
    -    catch (Exception e) {
    -      System.out.println("Error in loading properties: " + e.getMessage());
    -      System.exit(1);
    -    }
    -  }
    -  
    -  
    -    /**
    -	 * Harvester main method.
    -	 * 
    -	 * @param args               the command line arguments
    -	 * 
    -	 *   args[0] if "false", then this is not command-line mode,
    -	 *           Command-line mode is true by default.
    -	 *           
    -	 *   args[1] if present, represents the path to the harvest list schema file.
    -	 *           Specifying it overrides the default path to the schema file.
    -	 *   
    -	 * @throws SAXException
    -	 * @throws IOException
    -	 * @throws ParserConfigurationException
    -	 */
    -	public static void main(String[] args) {
    -
    -	    Integer delayDefault = new Integer(0); // Default number of hours delay
    -		int delay = delayDefault.intValue(); // Delay in hours before first
    -												// harvest
    -		Integer d; // Used for determining delay
    -		long delta; // endTime - startTime
    -		long endTime; // time that a harvest completes
    -		Harvester harvester; // object for a single harvest run
    -		Integer maxHarvestsDefault = new Integer(0); // Default max harvests
    -		int maxHarvests = maxHarvestsDefault.intValue(); // Max number of
    -															// harvests
    -		Integer mh; // used in determining max harvests
    -		int nHarvests = 0; // counts the number of harvest runs
    -		final long oneHour = (60 * 60 * 1000); // milliseconds in one hour
    -		Integer periodDefault = new Integer(24); // Default hours between
    -													// harvests
    -		int period = periodDefault.intValue(); // Hours between harvests
    -		Integer p; // Used in determining the period
    -		long startTime; // time that a harvest run starts
    -		
    -		String metacatContextDir = null;
    -
    -		if ((args.length > 0) && (args[0] != null)) {
    -			metacatContextDir = args[0];
    -		}
    -
    -		/*
    -		 * If there is a second argument, it is the schemaLocation value
    -		 */
    -		if (args.length > 1) {
    -			schemaLocation = args[1];
    -			System.err.println("schemaLocation: " + schemaLocation);
    -
    -			try {
    -				Thread.sleep(10000);
    -			} catch (InterruptedException e) {
    -				e.printStackTrace();
    -			}
    -		}
    -
    -		System.out.println(marker);
    -		System.out.println("Starting Harvester");
    -		Harvester.loadProperties(metacatContextDir);
    -
    -		// Parse the delay property. Use default if necessary.
    -		try {
    -			d = Integer.valueOf(PropertyService.getProperty("harvester.delay"));
    -			delay = d.intValue();
    -		} catch (NumberFormatException e) {
    -			System.out.println("NumberFormatException: Error parsing delay: "
    -					+ e.getMessage());
    -			System.out.println("Defaulting to delay=" + delayDefault);
    -			delay = delayDefault.intValue();
    -		} catch (PropertyNotFoundException pnfe) {
    -			System.out.println("PropertyNotFoundException: Error finding delay: "
    -					+ pnfe.getMessage());
    -			System.out.println("Defaulting to delay=" + delayDefault);
    -			delay = delayDefault.intValue();
    -		}
    -
    -		// Parse the maxHarvests property. Use default if necessary.
    -		try {
    -			mh = Integer.valueOf(PropertyService.getProperty("harvester.maxHarvests"));
    -			maxHarvests = mh.intValue();
    -		} catch (NumberFormatException e) {
    -			System.out.println("NumberFormatException: Error parsing maxHarvests: "
    -					+ e.getMessage());
    -			System.out.println("Defaulting to maxHarvests=" + maxHarvestsDefault);
    -			maxHarvests = maxHarvestsDefault.intValue();
    -		} catch (PropertyNotFoundException pnfe) {
    -			System.out.println("PropertyNotFoundException: Error finding maxHarvests: "
    -					+ pnfe.getMessage());
    -			System.out.println("Defaulting to maxHarvests=" + maxHarvestsDefault);
    -			maxHarvests = maxHarvestsDefault.intValue();
    -		}
    -
    -		// Parse the period property. Use default if necessary.
    -		try {
    -			p = Integer.valueOf(PropertyService.getProperty("harvester.period"));
    -			period = p.intValue();
    -		} catch (NumberFormatException e) {
    -			System.out.println("NumberFormatException: Error parsing period: "
    -					+ e.getMessage());
    -			System.out.println("Defaulting to period=" + periodDefault);
    -			period = periodDefault.intValue();
    -		} catch (PropertyNotFoundException pnfe) {
    -			System.out.println("PropertyNotFoundException: Error finding period: "
    -					+ pnfe.getMessage());
    -			System.out.println("Defaulting to period=" + periodDefault);
    -			period = periodDefault.intValue();
    -		}
    -
    -		// Sleep for delay number of hours prior to starting first harvest
    -		if (delay > 0) {
    -			try {
    -				System.out.print("First harvest will begin in " + delay);
    -				if (delay == 1) {
    -					System.out.println(" hour.");
    -				} else {
    -					System.out.println(" hours.");
    -				}
    -				Thread.sleep(delay * oneHour);
    -			} catch (InterruptedException e) {
    -				System.err.println("InterruptedException: " + e.getMessage());
    -				System.exit(1);
    -			}
    -		}
    -
    -    // Repeat a new harvest once every period number of hours, until we reach
    -    // the maximum number of harvests, or indefinitely if maxHarvests <= 0.
    -    // Subtract delta from the time period so
    -    // that each harvest will start at a fixed interval.
    -    //
    -    while (keepRunning && ((nHarvests < maxHarvests) || (maxHarvests <= 0))) {
    -      nHarvests++;
    -      startTime = System.currentTimeMillis();
    -      harvester = new Harvester();                // New object for this
    -													// harvest
    -      harvester.startup(nHarvests, maxHarvests);  // Start up Harvester
    -      harvester.readHarvestSiteSchedule();        // Read the database table
    -      harvester.harvest();                        // Harvest the documents
    -      harvester.shutdown();                       // Shut down Harvester
    -      endTime = System.currentTimeMillis();
    -      delta = endTime - startTime;
    -
    -      if ((nHarvests < maxHarvests) || (maxHarvests <= 0)) {
    -        try {
    -          System.out.println("Next harvest will begin in " + 
    -                             period + " hours.");
    -          Thread.sleep((period * oneHour) - delta);
    -        }
    -        catch (InterruptedException e) {
    -          System.err.println("InterruptedException: " + e.getMessage());
    -          System.exit(1);
    -        }
    -      }
    -    }
    -  }
    -  
    -  
    -  /**
    -   * Set the keepRunning flag. If set to false, the main program will end
    -   * the while loop that keeps harvester running every period number of hours.
    -   * The static method is intended to be called from the HarvesterServlet class
    -   * which creates a thread to run Harvester. When the thread is destroyed, the
    -   * thread's destroy() method calls Harvester.setKeepRunning(false).
    -   * 
    -   * @param keepRunning
    -   */
    -  static void setKeepRunning(boolean keepRunning) {
    -    Harvester.keepRunning = keepRunning;
    -  }
    -
    -  
    -  /*
    -   * Object fields
    -   */
    -
    -  /** Database connection */
    -  private Connection conn = null;
    -  
    -  /** Used during development to determine whether to connect to metacat 
    -   *  Sometimes it's useful to test parts of the code without actually
    -   *  connecting to Metacat.
    -   */
    -  private boolean connectToMetacat;
    -
    -  /** Highest DETAIL_LOG_ID primary key in the HARVEST_DETAIL_LOG table */
    -  private int detailLogID;
    -  
    -  /** Email address of the Harvester Administrator */
    -  String harvesterAdministrator;
    -  
    -  /** Highest HARVEST_LOG_ID primary key in the HARVEST_LOG table */
    -  private int harvestLogID;
    -  
    -  /** End time of this harvest session */
    -  private Date harvestEndTime;
    -  
    -  /** List of HarvestLog objects. Stores log entries for report generation. */
    -  private ArrayList harvestLogList = new ArrayList();
    -  
    -  /** List of HarvestSiteSchedule objects */
    -  private ArrayList harvestSiteScheduleList = new ArrayList();
    -  
    -  /** Start time of this harvest session */
    -  private Date harvestStartTime;
    -  
    -  /** Number of days to save log records. Any that are older are purged. */
    -  int logPeriod;
    -  
    -  /** Metacat client object */
    -  Metacat metacat;
    -  
    -  /** SMTP server for sending mail messages */
    -  String smtpServer;
    -  
    -  /** The timestamp for this harvest run. Used for output only. */
    -  String timestamp;
    -  
    -
    -  /*
    -   * Object methods
    -   */
    -   
    -  /**
    -   * Creates a new HarvestLog object and adds it to the harvestLogList.
    -   * 
    -   * @param  status          the status of the harvest operation
    -   * @param  message         the message text of the harvest operation
    -   * @param  harvestOperationCode  the harvest operation code
    -   * @param  siteScheduleID  the siteScheduleID for which this operation was
    -   *                         performed. 0 indicates that the operation did not
    -   *                         involve a particular harvest site.
    -   * @param  harvestDocument the associated HarvestDocument object. May be null.
    -   * @param  errorMessage    additional error message pertaining to document
    -   *                         error.
    -   */
    -  void addLogEntry(int    status,
    -                   String message,
    -                   String harvestOperationCode,
    -                   int    siteScheduleID,
    -                   HarvestDocument harvestDocument,
    -                   String errorMessage
    -                  ) {
    -    HarvestLog harvestLog;
    -    int harvestLogID = getHarvestLogID();
    -    int detailLogID;
    -
    -    /* If there is no associated harvest document, call the basic constructor;
    -     * else call the extended constructor.
    -     */
    -    if (harvestDocument == null) {    
    -      harvestLog = new HarvestLog(this, conn, harvestLogID, harvestStartTime, 
    -                                  status, message, harvestOperationCode, 
    -                                  siteScheduleID);
    -    }
    -    else {
    -      detailLogID = getDetailLogID();
    -      harvestLog = new HarvestLog(this, conn, harvestLogID, detailLogID, 
    -                                  harvestStartTime, status, message,
    -                                  harvestOperationCode, siteScheduleID,
    -                                  harvestDocument, errorMessage);
    -    }
    -    
    -    harvestLogList.add(harvestLog);
    -  }
    -  
    -  
    -  public void closeConnection() {
    -    try {
    -      // Close the database connection
    -      System.out.println("Closing the database connection.");
    -      conn.close();
    -    }
    -    catch (SQLException e) {
    -      System.out.println("Database access failed " + e);
    -    }    
    -  }
    -
    -
    -  /**
    -   * Determines whether Harvester should attempt to connect to Metacat.
    -   * Used during development and testing.
    -   * 
    -   * @return     true if Harvester should connect, otherwise false
    -   */
    -  boolean connectToMetacat () {
    -    return connectToMetacat;
    -  }
    -  
    -
    -  /**
    -   * Normalizes text prior to insertion into the HARVEST_LOG or
    -   * HARVEST_DETAIL_LOG tables. In particular, replaces the single quote
    -   * character with the double quote character. This prevents SQL errors
    -   * involving words that contain single quotes. Also removes \n and \r
    -   * characters from the text.
    -   * 
    -   * @param text  the original string
    -   * @return      a string containing the normalized text
    -   */
    -  public String dequoteText(String text) {
    -    char c;
    -    StringBuffer stringBuffer = new StringBuffer();
    -    
    -    for (int i = 0; i < text.length(); i++) {
    -      c = text.charAt(i);
    -      switch (c) {
    -        case '\'':
    -          stringBuffer.append('\"');
    -          break;
    -        case '\r':
    -        case '\n':
    -          break;
    -        default:
    -          stringBuffer.append(c);
    -          break;
    -      }
    -    }
    -    
    -    return stringBuffer.toString();
    -  }
    -  
    -  /**
    -   * Returns a connection to the database. Opens the connection if a connection
    -   * has not already been made previously.
    -   * 
    -   * @return  conn  the database Connection object
    -   */
    -  public Connection getConnection() {
    -    String dbDriver = "";
    -    String defaultDB = null;
    -    String password = null;
    -    String user = null;
    -    SQLWarning warn;
    -    
    -    if (conn == null) {
    -    	try {
    -			dbDriver = PropertyService.getProperty("database.driver");
    -			defaultDB = PropertyService.getProperty("database.connectionURI");
    -			password = PropertyService.getProperty("database.password");
    -			user = PropertyService.getProperty("database.user");
    -		} catch (PropertyNotFoundException pnfe) {
    -			System.out.println("Can't find property " + pnfe);
    -	        System.exit(1);
    -		}
    -
    -      // Load the jdbc driver
    -      try {
    -        Class.forName(dbDriver);
    -      }
    -      catch (ClassNotFoundException e) {
    -        System.out.println("Can't load driver " + e);
    -        System.exit(1);
    -      } 
    -
    -      // Make the database connection
    -      try {
    -        System.out.println("Getting connection to Harvester tables");
    -        conn = DriverManager.getConnection(defaultDB, user, password);
    -
    -        // If a SQLWarning object is available, print its warning(s).
    -        // There may be multiple warnings chained.
    -        warn = conn.getWarnings();
    -      
    -        if (warn != null) {
    -          while (warn != null) {
    -            System.out.println("SQLState: " + warn.getSQLState());
    -            System.out.println("Message:  " + warn.getMessage());
    -            System.out.println("Vendor: " + warn.getErrorCode());
    -            System.out.println("");
    -            warn = warn.getNextWarning();
    -          }
    -        }
    -      }
    -      catch (SQLException e) {
    -        System.out.println("Database access failed " + e);
    -        System.exit(1);
    -      }
    -    }
    -    
    -    return conn;
    -  }
    -
    -
    -  /**
    -   * Gets the current value of the detailLogID for storage as a primary key in
    -   * the DETAIL_LOG_ID field of the HARVEST_DETAIL_LOG table.
    -   * 
    -   * @return  the current value of the detailLogID
    -   */
    -  public int getDetailLogID() {
    -    int currentValue = detailLogID;
    -    
    -    detailLogID++;
    -    return currentValue;
    -  }
    -  
    -  
    -  /**
    -   * Gets the current value of the harvestLogID for storage as a primary key in
    -   * the HARVEST_LOG_ID field of the HARVEST_LOG table.
    -   * 
    -   * @return  the current value of the detailLogID
    -   */
    -  public int getHarvestLogID() {
    -    int currentValue = harvestLogID;
    -    
    -    harvestLogID++;
    -    return currentValue;
    -  }
    -  
    -
    -  /** 
    -   * Gets the maximum value of an integer field from a table.
    -   * 
    -   * @param tableName  the database table name
    -   * @param fieldName  the field name of the integer field in the table
    -   * @return  the maximum integer stored in the fieldName field of tableName
    -   */
    -  private int getMaxValue(String tableName, String fieldName) {
    -    int maxValue = 0;
    -    int fieldValue;
    -    String query = "SELECT " + fieldName + " FROM " + tableName;
    -    Statement stmt;
    -    
    -	try {
    -      stmt = conn.createStatement();
    -      ResultSet rs = stmt.executeQuery(query);
    -	
    -      while (rs.next()) {
    -        fieldValue = rs.getInt(fieldName);
    -        maxValue = Math.max(maxValue, fieldValue);
    -      }
    -      
    -      stmt.close();
    -    } 
    -    catch(SQLException ex) {
    -      System.out.println("SQLException: " + ex.getMessage());
    -    }
    -    
    -    return maxValue;
    -  }
    -  
    -  
    -  /** 
    -   * Gets the minimum value of an integer field from a table.
    -   * 
    -   * @param tableName  the database table name
    -   * @param fieldName  the field name of the integer field in the table
    -   * @return  the minimum integer stored in the fieldName field of tableName
    -   */
    -  private int getMinValue(String tableName, String fieldName) {
    -    int minValue = 0;
    -    int fieldValue;
    -    String query = "SELECT " + fieldName + " FROM " + tableName;
    -    Statement stmt;
    -    
    -    try {
    -      stmt = conn.createStatement();
    -      ResultSet rs = stmt.executeQuery(query);
    -	
    -      while (rs.next()) {
    -        fieldValue = rs.getInt(fieldName);
    -
    -        if (minValue == 0) {
    -          minValue = fieldValue;
    -        }
    -        else {
    -          minValue = Math.min(minValue, fieldValue);
    -        }
    -      }
    -      
    -      stmt.close();
    -    } 
    -    catch(SQLException ex) {
    -      System.out.println("SQLException: " + ex.getMessage());
    -    }
    -
    -    return minValue;
    -  }
    -  
    -  
    -  /**
    -   * For every Harvest site schedule in the database, harvest the
    -   * documents for that site if they are due to be harvested.
    -   * 
    -   * @throws SAXException
    -   * @throws IOException
    -   * @throws ParserConfigurationException
    -   */
    -  private void harvest() {
    -    HarvestSiteSchedule harvestSiteSchedule;
    -
    -    for (int i = 0; i < harvestSiteScheduleList.size(); i++) {
    -      harvestSiteSchedule = (HarvestSiteSchedule)harvestSiteScheduleList.get(i);
    -      
    -      if (Harvester.schemaLocation != null) {
    -        harvestSiteSchedule.setSchemaLocation(Harvester.schemaLocation);
    -      }
    -      
    -      harvestSiteSchedule.harvestDocumentList();
    -    }
    -  }
    -  
    -  
    -  /**
    -   * Initializes the detailLogID and harvestLogID values to their current
    -   * maximums + 1.
    -   */
    -  public void initLogIDs() {
    -    detailLogID = getMaxValue("HARVEST_DETAIL_LOG", "DETAIL_LOG_ID") + 1;
    -    harvestLogID = getMaxValue("HARVEST_LOG", "HARVEST_LOG_ID") + 1;
    -  }
    -  
    -
    -  /**
    -   * Prints the header of the harvest report.
    -   * 
    -   * @param out            the PrintStream object to print to
    -   * @param siteScheduleID the siteScheduleId of the HarvestSiteSchedule. Will
    -   *                       have a value of 0 if no particular site is involved,
    -   *                       which indicates that the report is being prepared
    -   *                       for the Harvester Administrator rather than for a
    -   *                       particular Site Contact.
    -   */
    -  void printHarvestHeader(PrintStream out, int siteScheduleID) {
    -    HarvestLog harvestLog;
    -    int logSiteScheduleID;
    -    int nErrors = 0;
    -    String phrase;
    -    
    -    for (int i = 0; i < harvestLogList.size(); i++) {
    -      harvestLog = (HarvestLog) harvestLogList.get(i);
    -      logSiteScheduleID = harvestLog.getSiteScheduleID();
    -      
    -      if ((siteScheduleID == 0) || (siteScheduleID == logSiteScheduleID)) {
    -        if (harvestLog.isErrorEntry()) {
    -          nErrors++;
    -        }
    -      }      
    -    }
    -
    -    out.println(marker);
    -    out.println(filler);
    -    out.println("* METACAT HARVESTER REPORT: " + timestamp);
    -    out.println(filler);
    -
    -    if (nErrors > 0) {
    -      phrase = (nErrors == 1) ? " ERROR WAS " : " ERRORS WERE ";
    -      out.println("* A TOTAL OF " + nErrors + phrase + "DETECTED.");
    -      out.println("* Please see the log entries below for additonal details.");
    -    }
    -    else {
    -      out.println("* NO ERRORS WERE DETECTED DURING THIS HARVEST.");
    -    }
    -    
    -    out.println(filler);
    -    out.println(marker);
    -  }
    -    
    -
    -  /**
    -   * Prints harvest log entries for this harvest run. Entries may be filtered
    -   * for a particular site, or all entries may be printed.
    -   * 
    -   * @param out            the PrintStream object to write to
    -   * @param maxCodeLevel   the maximum code level that should be printed,
    -   *                       e.g. "warning". Any log entries higher than this
    -   *                       level will not be printed.
    -   * @param siteScheduleID if greater than 0, indicates that the log
    -   *                       entry should only be printed for a particular site
    -   *                       as identified by its siteScheduleID. if 0, then
    -   *                       print output for all sites.
    -   */
    -  void printHarvestLog(PrintStream out, String maxCodeLevel, int siteScheduleID
    -                      ) {
    -    HarvestLog harvestLog;
    -    int logSiteScheduleID;
    -    int nErrors = 0;
    -    String phrase;
    -    
    -    out.println("");
    -    out.println(marker);
    -    out.println(filler);
    -    out.println("*                       LOG ENTRIES");
    -    out.println(filler);
    -    out.println(marker);
    -
    -    for (int i = 0; i < harvestLogList.size(); i++) {
    -      harvestLog = (HarvestLog) harvestLogList.get(i);
    -      logSiteScheduleID = harvestLog.getSiteScheduleID();
    -      if ((siteScheduleID == 0) || (siteScheduleID == logSiteScheduleID)) {
    -        harvestLog.printOutput(out, maxCodeLevel);
    -      }
    -    }
    -  }
    -    
    -
    -  /**
    -   * Prints the site schedule data for a given site.
    -   * 
    -   * @param out              the PrintStream to write to
    -   * @param siteScheduleID   the primary key in the HARVEST_SITE_SCHEDULE table
    -   */
    -  void printHarvestSiteSchedule(PrintStream out, int siteScheduleID) {
    -    HarvestSiteSchedule harvestSiteSchedule;
    -
    -    for (int i = 0; i < harvestSiteScheduleList.size(); i++) {
    -      harvestSiteSchedule = (HarvestSiteSchedule)harvestSiteScheduleList.get(i);
    -      if (harvestSiteSchedule.siteScheduleID == siteScheduleID) {
    -        harvestSiteSchedule.printOutput(out);
    -      }
    -    }
    -  }
    -  
    -
    -  /**
    -   * Prunes old records from the HARVEST_LOG table. Records are removed if
    -   * their HARVEST_DATE is older than a given number of days, as stored in the
    -   * logPeriod object field. First deletes records from the HARVEST_DETAIL_LOG
    -   * table that reference the to-be-pruned entries in the HARVEST_LOG table.
    -   */
    -  private void pruneHarvestLog() {
    -    long currentTime = harvestStartTime.getTime(); // time in milliseconds
    -    Date dateLastLog;                    // Prune everything prior to this date
    -    String deleteString;
    -    String deleteStringDetailLog;
    -    long delta;
    -    final long millisecondsPerDay = (1000 * 60 * 60 * 24);
    -    int recordsDeleted;
    -    int recordsDeletedDetail = 0;
    -    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd-MMM-yyyy");
    -    String dateString;
    -    ResultSet rs;
    -    String selectString;
    -    Statement stmt;
    -    long timeLastLog = 0;
    -    SQLWarning warn;
    -     
    -    delta = logPeriod * millisecondsPerDay;
    -    deleteString = "DELETE FROM HARVEST_LOG WHERE HARVEST_DATE < ";
    -    selectString="SELECT HARVEST_LOG_ID FROM HARVEST_LOG WHERE HARVEST_DATE < ";
    -    deleteStringDetailLog = 
    -                       "DELETE FROM HARVEST_DETAIL_LOG WHERE HARVEST_LOG_ID = ";
    -    timeLastLog = currentTime - delta;
    -    dateLastLog = new Date(timeLastLog);
    -    dateString = "'" + simpleDateFormat.format(dateLastLog) + "'";
    -    deleteString += dateString;
    -    selectString += dateString;
    -
    -    try {
    -      System.out.println(
    -                "Pruning log entries from HARVEST_DETAIL_LOG and HARVEST_LOG:");
    -
    -      /* Get the list of entries that need to be pruned from the HARVEST_LOG
    -       * table.
    -       */
    -      stmt = conn.createStatement();                            
    -      rs = stmt.executeQuery(selectString);
    -      warn = rs.getWarnings();
    -
    -      if (warn != null) {
    -        System.out.println("\n---Warning---\n");
    -
    -        while (warn != null) {
    -          System.out.println("Message: " + warn.getMessage());
    -          System.out.println("SQLState: " + warn.getSQLState());
    -          System.out.print("Vendor error code: ");
    -          System.out.println(warn.getErrorCode());
    -          System.out.println("");
    -          warn = warn.getNextWarning();
    -        }
    -      } 
    -
    -      /* Delete any entries from the HARVEST_DETAIL_LOG which reference
    -       * HARVEST_LOG_IDs that are about to be pruned. HARVEST_DETAIL_LOG must
    -       * be pruned first because its records have a child relationship to those
    -       * in HARVEST_LOG.
    -       */
    -      while (rs.next()) {
    -        harvestLogID = rs.getInt("HARVEST_LOG_ID");
    -        stmt = conn.createStatement();                            
    -        recordsDeleted = stmt.executeUpdate(deleteStringDetailLog + 
    -                                            harvestLogID);
    -        recordsDeletedDetail += recordsDeleted;
    -        stmt.close();
    -      }
    - 
    -      /* Now prune entries from the HARVEST_LOG table using a single update.
    -       */
    -      stmt = conn.createStatement();                            
    -      recordsDeleted = stmt.executeUpdate(deleteString);
    -      stmt.close();
    -
    -      System.out.println("  " + recordsDeletedDetail + 
    -                         " records deleted from HARVEST_DETAIL_LOG");
    -      System.out.println("  " + recordsDeleted + 
    -                         " records deleted from HARVEST_LOG");
    -    }
    -    catch (SQLException e) {
    -      System.out.println("SQLException: " + e.getMessage());
    -    }
    -  }
    -    
    -
    -  /**
    -   * Reads the HARVEST_SITE_SCHEDULE table in the database, creating
    -   * a HarvestSiteSchedule object for each row in the table.
    -   */
    -  private void readHarvestSiteSchedule() {
    -    HarvestSiteSchedule harvestSiteSchedule;
    -    ResultSet rs;
    -    SQLWarning warn;
    -    Statement stmt;
    -
    -    String contactEmail;
    -    String dateLastHarvest;
    -    String dateNextHarvest;
    -    String documentListURL;
    -    String ldapDN;
    -    String ldapPwd;
    -    int siteScheduleID;
    -    String unit;
    -    int updateFrequency;
    -        
    -    try {
    -      // Read the HARVEST_SITE_SCHEDULE table
    -      stmt = conn.createStatement();
    -      rs = stmt.executeQuery("SELECT * FROM HARVEST_SITE_SCHEDULE");
    -      warn = rs.getWarnings();
    -
    -      if (warn != null) {
    -        System.out.println("\n---Warning---\n");
    -
    -        while (warn != null) {
    -          System.out.println("Message: " + warn.getMessage());
    -          System.out.println("SQLState: " + warn.getSQLState());
    -          System.out.print("Vendor error code: ");
    -          System.out.println(warn.getErrorCode());
    -          System.out.println("");
    -          warn = warn.getNextWarning();
    -        }
    -      }
    -     
    -      while (rs.next()) {
    -        siteScheduleID = rs.getInt("SITE_SCHEDULE_ID");
    -        documentListURL = rs.getString("DOCUMENTLISTURL");
    -        ldapDN = rs.getString("LDAPDN");
    -        ldapPwd = rs.getString("LDAPPWD");
    -        dateNextHarvest = rs.getString("DATENEXTHARVEST");
    -        dateLastHarvest = rs.getString("DATELASTHARVEST");
    -        updateFrequency = rs.getInt("UPDATEFREQUENCY");
    -        unit = rs.getString("UNIT");
    -        contactEmail = rs.getString("CONTACT_EMAIL");
    -        
    -        warn = rs.getWarnings();
    -
    -        if (warn != null) {
    -          System.out.println("\n---Warning---\n");
    -      
    -          while (warn != null) {
    -            System.out.println("Message: " + warn.getMessage());
    -            System.out.println("SQLState: " + warn.getSQLState());
    -            System.out.print("Vendor error code: ");
    -            System.out.println(warn.getErrorCode());
    -            System.out.println("");
    -            warn = warn.getNextWarning();
    -          }
    -        }
    -      
    -        harvestSiteSchedule = new HarvestSiteSchedule(this,
    -                                                      siteScheduleID,
    -                                                      documentListURL,
    -                                                      ldapDN,
    -                                                      ldapPwd,
    -                                                      dateNextHarvest,
    -                                                      dateLastHarvest,
    -                                                      updateFrequency,
    -                                                      unit,
    -                                                      contactEmail
    -                                                     );
    -        harvestSiteScheduleList.add(harvestSiteSchedule);
    -      }
    -      
    -      rs.close();
    -      stmt.close();
    -    }
    -    catch (SQLException e) {
    -      System.out.println("Database access failed " + e);
    -      System.exit(1);
    -    }
    -    
    -  }
    -    
    -
    -  /**
    -   * Sends a report to the Harvester Administrator. The report prints each log
    -   * entry pertaining to this harvest run.
    -   *
    -   * @param maxCodeLevel  the maximum code level that should be printed,
    -   *                      e.g. "warning". Any log entries higher than this
    -   *                      level will not be printed.
    -   */
    -  void reportToAdministrator(String maxCodeLevel) {
    -    PrintStream body;
    -    String from = harvesterAdministrator;
    -    String[] fromArray;
    -    MailMessage msg;
    -    int siteScheduleID = 0;
    -    String subject = "Report from Metacat Harvester: " + timestamp;
    -    String to = harvesterAdministrator;
    -    
    -    if (!to.equals("")) {
    -      System.out.println("Sending report to Harvester Administrator at address "
    -                         + harvesterAdministrator);
    -      
    -      try {
    -        msg = new MailMessage(smtpServer);
    -
    -        if (from.indexOf(',') > 0) {
    -          fromArray = from.split(",");
    -          
    -          for (int i = 0; i < fromArray.length; i++) {
    -            if (i == 0) {
    -              msg.from(fromArray[i]);
    -            }
    -            
    -            msg.to(fromArray[i]);            
    -          }
    -        }
    -        else if (from.indexOf(';') > 0) {
    -          fromArray = from.split(";");
    -
    -          for (int i = 0; i < fromArray.length; i++) {
    -            if (i == 0) {
    -              msg.from(fromArray[i]);
    -            }
    -            
    -            msg.to(fromArray[i]);            
    -          }
    -        }
    -        else {
    -          msg.from(from);
    -          msg.to(to);
    -        }
    -        
    -        msg.setSubject(subject);
    -        body = msg.getPrintStream();
    -        printHarvestHeader(body, siteScheduleID);
    -        printHarvestLog(body, maxCodeLevel, siteScheduleID);
    -        msg.sendAndClose();
    -      }
    -      catch (IOException e) {
    -        System.out.println("There was a problem sending email to " + to);
    -        System.out.println("IOException: " + e.getMessage());
    -      }
    -    }
    -  }
    -  
    -
    -  /**
    -   * Sets the harvest start time for this harvest run.
    -   * 
    -   * @param date
    -   */
    -  public void setHarvestStartTime(Date date) {
    -    harvestStartTime = date;
    -  }
    -    
    -
    -  /**
    -   * Shuts down Harvester. Performs cleanup operations such as logging out
    -   * of Metacat and disconnecting from the database.
    -   */
    -  private void shutdown() {
    -    String maxCodeLevel = "debug";  // Print all log entries from level 1
    -                                    // ("error") to level 5 ("debug")
    -    int siteScheduleID = 0;
    -
    -    // Log shutdown operation
    -    System.out.println("Shutting Down Harvester");
    -    addLogEntry(0, "Shutting Down Harvester", "harvester.HarvesterShutdown", 0, null, "");
    -    pruneHarvestLog();
    -    closeConnection();
    -    // Print log to standard output and then email the Harvester administrator
    -    printHarvestLog(System.out, maxCodeLevel, siteScheduleID);
    -    reportToAdministrator(maxCodeLevel);      // Send a copy to harvester admin
    -  }
    -    
    -
    -    /**
    -	 * Initializes Harvester at startup. Connects to the database and to Metacat.
    -	 * 
    -	 * @param nHarvests        the nth harvest
    -	 * @param maxHarvests      the maximum number of harvests that this process
    -	 *                         can run
    -	 */
    -	private void startup(int nHarvests, int maxHarvests) {
    -		Boolean ctm;
    -		Integer lp;
    -		String metacatURL;
    -		Date now = new Date();
    -
    -		timestamp = now.toString();
    -		System.out.println(Harvester.marker);
    -		System.out.print(timestamp + ": Starting Next Harvest");
    -		if (maxHarvests > 0) {
    -			System.out.print(" (" + nHarvests + "/" + maxHarvests + ")");
    -		}
    -		System.out.print("\n");
    -		try {
    -			ctm = Boolean.valueOf(PropertyService.getProperty("harvester.connectToMetacat"));
    -			connectToMetacat = ctm.booleanValue();
    -			harvesterAdministrator = PropertyService
    -					.getProperty("harvester.administrator");
    -			smtpServer = PropertyService.getProperty("harvester.smtpServer");
    -
    -			lp = Integer.valueOf(PropertyService.getProperty("harvester.logPeriod"));
    -			logPeriod = lp.intValue();
    -		} catch (NumberFormatException e) {
    -			System.err.println("NumberFormatException: Error parsing logPeriod "
    -					+ logPeriod + e.getMessage());
    -			System.err.println("Defaulting to logPeriod of 90 days");
    -			logPeriod = 90;
    -		} catch (PropertyNotFoundException pnfe) {
    -			System.out.println("PropertyNotFoundException: Error getting property: "
    -					+ pnfe.getMessage());
    -			return;
    -		}
    -
    -		conn = getConnection();
    -		initLogIDs();
    -		setHarvestStartTime(now);
    -		// Log startup operation
    -		addLogEntry(0, "Starting Up Harvester", "harvester.HarvesterStartup", 0, null, "");
    -
    -		if (connectToMetacat()) {
    -			try {
    -				metacatURL = SystemUtil.getServletURL();
    -				System.out.println("Connecting to Metacat: " + metacatURL);
    -				metacat = MetacatFactory.createMetacatConnection(metacatURL);
    -			} catch (MetacatInaccessibleException e) {
    -				System.out.println("Metacat connection failed." + e.getMessage());
    -			} catch (Exception e) {
    -				System.out.println("Metacat connection failed." + e.getMessage());
    -			}
    -		}
    -	}
    -
    -}
    
  • src/edu/ucsb/nceas/metacat/harvesterClient/HarvesterRegistration.java+0 808 removed
    @@ -1,808 +0,0 @@
    -/**
    - *  '$RCSfile$'
    - *  Copyright: 2004 University of New Mexico and the 
    - *                  Regents of the University of California
    - *
    - *   '$Author$'
    - *     '$Date$'
    - * '$Revision$'
    - *
    - * This program is free software; you can redistribute it and/or modify
    - * it under the terms of the GNU General Public License as published by
    - * the Free Software Foundation; either version 2 of the License, or
    - * (at your option) any later version.
    - *
    - * This program is distributed in the hope that it will be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write to the Free Software
    - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    - */
    -
    -package edu.ucsb.nceas.metacat.harvesterClient;
    -
    -import com.oreilly.servlet.ParameterParser;
    -import java.io.IOException;
    -import java.io.PrintWriter;
    -import java.sql.Connection;
    -import java.sql.DriverManager;
    -import java.sql.ResultSet;
    -import java.sql.SQLException;
    -import java.sql.SQLWarning;
    -import java.sql.Statement;
    -import java.text.ParseException;
    -import java.text.SimpleDateFormat;
    -import java.util.Date;
    -import javax.servlet.ServletConfig;
    -import javax.servlet.ServletContext;
    -import javax.servlet.ServletException;
    -import javax.servlet.http.HttpServlet;
    -import javax.servlet.http.HttpServletRequest;
    -import javax.servlet.http.HttpServletResponse;
    -import javax.servlet.http.HttpSession;
    -
    -import edu.ucsb.nceas.metacat.properties.PropertyService;
    -import edu.ucsb.nceas.metacat.shared.ServiceException;
    -import edu.ucsb.nceas.utilities.PropertyNotFoundException;
    -
    -/**
    - * HarvesterRegistration is a servlet that implements harvester registration.
    - * The servlet reads parameters that were entered in a harvester registration
    - * form, checks the validity of the values, stores the values in the database
    - * by either inserting, updating, or removing a record in the
    - * HARVEST_SITE_SCHEDULE table.
    - * 
    - * @author    costa
    - * 
    - */
    -public class HarvesterRegistration extends HttpServlet {
    -
    -  /*
    -   * Class fields
    -   */
    -  private static final String CONFIG_DIR = "WEB-INF";
    -   
    -  private static final long serialVersionUID = 7390084694699704362L;
    -	
    -  /*
    -   * Object fields
    -   */
    -  private ServletConfig config = null;
    -  private ServletContext context = null;
    -  private String defaultDB;     // database connection, from properties file
    -  final private long millisecondsPerDay = (1000 * 60 * 60 * 24);
    -  private String password;      // database password, from properties file
    -  private String user;          // database user, from properties file
    -   
    -
    -  /*
    -   * Object methods
    -   */
    -   
    -   
    -  /**
    -   * Checks validity of user input values.
    -   * 
    -   * @param out             the PrintWriter output object
    -   * @param documentListURL the Harvest List URL specified by the user
    -   * @param updateFrequency the Harvest Frequency specified by the user
    -   * @return validValues    true if all values are valid, else false
    -   */
    -  private boolean checkValues(PrintWriter out,
    -                              String documentListURL,
    -                              int updateFrequency
    -                             ) {
    -    boolean validValues = true;
    -
    -    // Check validity of the Harvest List URL field    
    -    if (documentListURL.equals("")) {
    -      out.println("A value must be specified in the Harvest List URL field");
    -      validValues = false;
    -    }
    -
    -    // Check validity of the Harvest Frequency field    
    -    if ((updateFrequency < 0) || (updateFrequency > 99)) {
    -      out.println("Harvest Frequency should be in the range 1 to 99");
    -      validValues = false;
    -    }
    -    
    -    return validValues;
    -  }
    -  
    -  
    -  /**
    -   * Closes the database connection.
    -   * 
    -   * @param conn  The connection.
    -   */
    -  private void closeConnection(Connection conn) {
    -    try {
    -      if (conn != null) {
    -        conn.close();
    -      }
    -    }
    -    catch (SQLException e) {
    -      // ignored
    -    }
    -  }
    -
    -
    -  /**
    -   * Inserts a record to the HARVEST_SITE_SCHEDULE table.
    -   * 
    -   * @param out             the PrintWriter output object
    -   * @param conn            the Connection
    -   * @param siteScheduleID  the primary key for the table
    -   * @param contactEmail    contact email address of the site user
    -   * @param documentListURL the URL of the harvest list at the site
    -   * @param ldapDN          the site user's LDAP DN
    -   * @param ldapPwd         the site user's LDAP password
    -   * @param unit            the update frequency unit, e.g. "days", "weeks"
    -   * @param updateFrequency the update frequency, an integer in range 1-99
    -   */
    -  private void dbInsert(PrintWriter out,
    -                        Connection conn,
    -                        int siteScheduleID,
    -                        String contactEmail,
    -                        String documentListURL,
    -                        String ldapDN,
    -                        String ldapPwd,
    -                        String unit,
    -                        int updateFrequency
    -                       ) {
    -    String dateNextHarvest;
    -    long delta;
    -    Date dnh;                          // Date of next harvest
    -    Date now;                          // Today's date
    -    String query;
    -    Statement stmt;
    -    long timeNextHarvest;
    -    SimpleDateFormat writeFormat = new SimpleDateFormat("dd-MMM-yyyy");
    -    
    -    // Calculate the value of delta, the number of milliseconds between the
    -    // last harvest date and the next harvest date.
    -    delta = updateFrequency * millisecondsPerDay;
    -    
    -    if (unit.equals("weeks")) {
    -      delta *= 7;
    -    }
    -    else if (unit.equals("months")) {
    -      delta *= 30;
    -    }
    -
    -    now = new Date();
    -    timeNextHarvest = now.getTime();
    -    dnh = new Date(timeNextHarvest);
    -    dateNextHarvest = writeFormat.format(dnh);
    -	
    -    try {
    -      stmt = conn.createStatement();
    -      query = "insert into HARVEST_SITE_SCHEDULE " +
    -        "(SITE_SCHEDULE_ID, CONTACT_EMAIL, DOCUMENTLISTURL, LDAPDN, LDAPPWD, " +
    -        "UNIT, UPDATEFREQUENCY, DATENEXTHARVEST) " +
    -        "values(" + siteScheduleID + "," +
    -        quoteString(contactEmail) + "," +
    -        quoteString(documentListURL) + "," +
    -        quoteString(ldapDN) + "," +
    -        quoteString(ldapPwd) + "," +
    -        quoteString(unit) + "," +
    -        updateFrequency + "," +
    -        quoteString(dateNextHarvest) + ")";
    -                  
    -      System.out.println(query);
    -      stmt.executeUpdate(query);
    -      stmt.close();
    -      reportResults(out, ldapDN, contactEmail, documentListURL, updateFrequency,
    -                    unit, dateNextHarvest);
    -    }
    -    catch(SQLException e) {
    -      System.out.println("SQLException: " + e.getMessage());
    -	}
    -  }
    -   
    -
    -  /**
    -   * Removes a record from the HARVEST_SITE_SCHEDULE table.
    -   * 
    -   * @param out            the PrintWriter output object
    -   * @param conn           the Connection
    -   * @param siteScheduleID the primary key for the table
    -   * @param ldapDN          the site user's LDAP DN
    -   */
    -  private void dbRemove(PrintWriter out,
    -                        Connection conn,
    -                        int siteScheduleID,
    -                        String ldapDN
    -                       ) {
    -    String query = "DELETE FROM HARVEST_SITE_SCHEDULE WHERE " +
    -                   "SITE_SCHEDULE_ID=" + siteScheduleID;
    -    int nRecords = 0;
    -	Statement stmt;
    -     
    -	try {
    -      stmt = conn.createStatement();
    -      System.out.println(query);
    -      nRecords = stmt.executeUpdate(query);
    -      stmt.close();
    -      System.out.println(nRecords + " record(s) removed.");
    -      
    -      if (nRecords > 0) {
    -        out.println("Harvester registration removed for user " + ldapDN);
    -      }
    -      else {
    -        out.println("A problem was encountered removing registration for user " 
    -                    + ldapDN);
    -      }
    -    }
    -    catch(SQLException e) {
    -      System.out.println("SQLException: " + e.getMessage());
    -    }
    -  }
    -   
    -
    -  /**
    -   * Updates a record in the HARVEST_SITE_SCHEDULE table.
    -   * 
    -   * @param out             the PrintWriter output object
    -   * @param conn            the Connection
    -   * @param siteScheduleID  the primary key for the table
    -   * @param contactEmail    contact email address of the site user
    -   * @param documentListURL the URL of the harvest list at the site
    -   * @param ldapDN          the site user's LDAP DN
    -   * @param ldapPwd         the site user's LDAP password
    -   * @param unit            the update frequency unit, e.g. "days", "weeks"
    -   * @param updateFrequency the update frequency, an integer in range 1-99
    -   * @param dateLastHarvest the date of last harvest, 
    -   *                        e.g. "2004-04-30 00:00:00.0" or ""
    -   */
    -   private void dbUpdate(PrintWriter out,
    -                         Connection conn,
    -                         int siteScheduleID,
    -                         String contactEmail,
    -                         String documentListURL,
    -                         String ldapDN,
    -                         String ldapPwd,
    -                         String unit,
    -                         int updateFrequency,
    -                         String dateLastHarvest
    -                        ) {
    -    String dateNextHarvest;
    -    long delta;
    -    Date dlh;                          // Date of last harvest
    -    Date dnh;                          // Date of next harvest
    -    Date now = new Date();             // Today's date
    -//  SimpleDateFormat readFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S");
    -    SimpleDateFormat readFormat = new SimpleDateFormat("yyyy-MM-dd");
    -    SimpleDateFormat writeFormat = new SimpleDateFormat("dd-MMM-yyyy");
    -    Statement stmt;
    -    long timeLastHarvest;
    -    long timeNextHarvest;
    -    long timeNow = now.getTime();
    -    
    -    // Calculate the value of delta, the number of milliseconds between the
    -    // last harvest date and the next harvest date.
    -    delta = updateFrequency * millisecondsPerDay;
    -    
    -    if (unit.equals("weeks")) {
    -      delta *= 7;
    -    }
    -    else if (unit.equals("months")) {
    -      delta *= 30;
    -    }
    -
    -    if (dateLastHarvest.equals("")) {
    -      timeNextHarvest = timeNow;
    -    }
    -    else {
    -      try {
    -        dlh = readFormat.parse(dateLastHarvest);
    -        timeLastHarvest = dlh.getTime();
    -        timeNextHarvest = timeLastHarvest + delta;
    -        timeNextHarvest = Math.max(timeNextHarvest, timeNow);
    -      }
    -      catch (ParseException e) {
    -        System.out.println("Error parsing date: " + dateLastHarvest +
    -                           " " + e.getMessage());
    -        timeNextHarvest = timeNow;
    -      }
    -    }
    -    
    -    dnh = new Date(timeNextHarvest);
    -    dateNextHarvest = writeFormat.format(dnh);
    -	
    -    try {
    -      stmt = conn.createStatement();
    -      stmt.executeUpdate("UPDATE HARVEST_SITE_SCHEDULE SET CONTACT_EMAIL=" +
    -                         quoteString(contactEmail) +
    -                         " WHERE SITE_SCHEDULE_ID = " + siteScheduleID);
    -      stmt.executeUpdate("UPDATE HARVEST_SITE_SCHEDULE SET DOCUMENTLISTURL=" +
    -                         quoteString(documentListURL) +
    -                         " WHERE SITE_SCHEDULE_ID = " + siteScheduleID);
    -      stmt.executeUpdate("UPDATE HARVEST_SITE_SCHEDULE SET LDAPPWD=" +
    -                         quoteString(ldapPwd) +
    -                         " WHERE SITE_SCHEDULE_ID = " + siteScheduleID);
    -      stmt.executeUpdate("UPDATE HARVEST_SITE_SCHEDULE SET UNIT=" +
    -                         quoteString(unit) +
    -                         " WHERE SITE_SCHEDULE_ID = " + siteScheduleID);
    -      stmt.executeUpdate("UPDATE HARVEST_SITE_SCHEDULE SET UPDATEFREQUENCY=" +
    -                         updateFrequency +
    -                         " WHERE SITE_SCHEDULE_ID = " + siteScheduleID);
    -      stmt.executeUpdate("UPDATE HARVEST_SITE_SCHEDULE SET DATENEXTHARVEST=" +
    -                         quoteString(dateNextHarvest) +
    -                         " WHERE SITE_SCHEDULE_ID = " + siteScheduleID);
    -      stmt.close();
    -      reportResults(out, ldapDN, contactEmail, documentListURL, updateFrequency,
    -                    unit, dateNextHarvest);
    -    }
    -    catch(SQLException e) {
    -      System.out.println("SQLException: " + e.getMessage());
    -    }
    - 
    -  }
    -   
    -
    -  /**
    -   * Handles GET method requests. Displays the current registration info for
    -   * this user (if any), then allows the user to make changes and register or
    -   * unregister.
    -   * 
    -   * @param req                the request
    -   * @param res                the response
    -   * @throws ServletException
    -   * @throws IOException
    -   */
    -  public void doGet(HttpServletRequest req, HttpServletResponse res)
    -                               throws ServletException, IOException {
    -    Connection conn = getConnection();
    -    String contactEmail = "";
    -    String documentListURL = "http://";
    -    HttpSession httpSession;
    -    String ldapDN;
    -    String ldapPwd;
    -    String query;
    -    int siteScheduleID;
    -    Statement stmt;
    -    String unit = "days";
    -    int updateFrequency = 1;
    -
    -    httpSession = req.getSession(false);
    -    
    -    if (httpSession == null) {
    -      System.out.println("User did not log in.");
    -      return;
    -    }
    -
    -    // The user name and password are stored as session attributes by the
    -    // HarvesterRegistrationLogin servlet.
    -    ldapDN = (String) httpSession.getAttribute("username");
    -    ldapPwd = (String) httpSession.getAttribute("password");
    -
    -    siteScheduleID = getSiteScheduleID(conn, ldapDN);
    -
    -    // If the user is already registered, query the existing values and
    -    // initialize the form with them.
    -    if (siteScheduleID != 0) {
    -      query = "SELECT * FROM HARVEST_SITE_SCHEDULE WHERE SITE_SCHEDULE_ID=" +
    -              siteScheduleID;
    -      
    -      try {
    -        stmt = conn.createStatement();
    -        ResultSet rs = stmt.executeQuery(query);
    -        
    -        while (rs.next()) {
    -          contactEmail = rs.getString("CONTACT_EMAIL");
    -          documentListURL = rs.getString("DOCUMENTLISTURL");
    -          updateFrequency = rs.getInt("UPDATEFREQUENCY");
    -          unit = rs.getString("UNIT");
    -        }
    -        
    -        stmt.close();
    -      }
    -      catch (SQLException ex) {
    -        System.out.println("SQLException: " + ex.getMessage());
    -      }
    -    }
    -
    -    res.setContentType("text/html");
    -    PrintWriter out = res.getWriter();
    -
    -    // Print the registration form    
    -    out.println("<HTML>");
    -    out.println("<HEAD>");
    -    out.println("<TITLE>Metacat Harvester Registration</TITLE>");
    -    out.println("</HEAD>");
    -    out.println("<BODY>");
    -    out.println("<H2><B>Metacat Harvester Registration</B></H2>");
    -    out.println("<FORM METHOD=POST>");   // posts to itself
    -    out.println("Fill out the form below to schedule regular harvests of EML ");
    -    out.println("documents from your site.<BR>");
    -    out.println("To register or changes values, enter all values ");
    -    out.println("below and click <B>Register</B>. ");
    -    out.println("To unregister, simply click <B>Unregister</B>.<BR>");
    -    out.println("<table>");
    -    out.println("<tr>");
    -    out.println("<td>");
    -    out.println("Email address:");
    -    out.println("</td>");
    -    out.println("<td>");
    -    out.println("<INPUT TYPE=TEXT NAME=contactEmail SIZE=30 VALUE=");
    -    out.println(contactEmail + ">");
    -    out.println("</td>");
    -    out.println("</tr>");
    -    out.println("<tr>");
    -    out.println("<td>");
    -    out.println("Harvest List URL:");
    -    out.println("</td>");
    -    out.println("<td>");
    -    out.println("<INPUT TYPE=TEXT NAME=documentListURL SIZE=50 VALUE=");
    -    out.println(documentListURL + ">");
    -    out.println("</td>");
    -    out.println("</tr>");
    -    out.println("<tr>");
    -    out.println("<td>");
    -    out.println("Harvest Frequency");
    -    out.println("</td>");
    -    out.println("<td>");
    -    out.println("</td>");
    -    out.println("</tr>");
    -    out.println("<tr>");
    -    out.println("<td>");
    -    out.println("  Once every (1-99):");
    -    out.println("</td>");
    -    out.println("<td>");
    -    out.println("<INPUT TYPE=TEXT NAME=updateFrequency ");
    -    out.println("MAXLENGTH=2 SIZE=2 VALUE=");
    -    out.println(updateFrequency + ">");
    -    out.println("</td>");
    -    out.println("</tr>");
    -    out.println("<tr>");
    -    out.println("<td>");
    -    //out.println("Unit:");
    -    out.println("</td>");
    -    out.println("<td>");
    -    out.println("<INPUT TYPE=RADIO ");
    -    if (unit.equals("days")) out.println("CHECKED ");
    -    out.println("NAME=unit VALUE=days>day(s)");
    -    out.println("<INPUT TYPE=RADIO ");
    -    if (unit.equals("weeks")) out.println("CHECKED ");
    -    out.println("NAME=unit VALUE=weeks>week(s)");
    -    out.println("<INPUT TYPE=RADIO ");
    -    if (unit.equals("months")) out.println("CHECKED ");
    -    out.println("NAME=unit VALUE=months>month(s)");
    -    out.println("</td>");
    -    out.println("</tr>");
    -    out.println("<tr></tr>");
    -    out.println("<tr>");
    -    out.println("<td>");
    -    out.println("<INPUT TYPE=SUBMIT NAME=register VALUE=Register>");
    -    out.println("<INPUT TYPE=SUBMIT NAME=unregister VALUE=Unregister>");
    -    out.println("</td>");
    -    out.println("<td>");
    -    out.println("</td>");
    -    out.println("</tr>");
    -    out.println("</table>");
    -    out.println("</BODY>");
    -    out.println("</HTML>");
    -  }
    -
    -
    -  /**
    -   * Handles POST method requests. Reads values as entered by the user in the
    -   * harvester registration form and checks them for validity. Then either 
    -   * inserts, updates, or removes a record in the HARVEST_SITE_SCHEDULE table.
    -   * 
    -   * @param req                the request
    -   * @param res                the response
    -   * @throws ServletException
    -   * @throws IOException
    -   */
    -  public void doPost(HttpServletRequest req, HttpServletResponse res)
    -                               throws ServletException, IOException {
    -    Connection conn = getConnection();
    -    int maxValue;
    -    boolean remove = false;        // if true, remove record
    -    int siteScheduleID;
    -    String contactEmail;
    -    String dateLastHarvest;
    -    String dateNextHarvest;
    -    String documentListURL;
    -    HttpSession httpSession;
    -    String ldapDN;
    -    String ldapPwd;
    -    PrintWriter out;
    -    ParameterParser parameterParser = new ParameterParser(req);
    -    String register;
    -    String unit;
    -    String unregister;
    -    int updateFrequency;
    -    boolean validValues;
    -
    -    httpSession = req.getSession(false);
    -    
    -    if (httpSession == null) {
    -      System.out.println("User did not log in.");
    -      return;
    -    }
    -
    -    // The user name and password are stored as session attributes by the
    -    // HarvesterRegistrationLogin servlet
    -    ldapDN = (String) httpSession.getAttribute("username");
    -    ldapPwd = (String) httpSession.getAttribute("password");
    -
    -    contactEmail = parameterParser.getStringParameter("contactEmail", "None");
    -    documentListURL = parameterParser.getStringParameter("documentListURL", "");
    -    unit = parameterParser.getStringParameter("unit", "days");
    -    updateFrequency = parameterParser.getIntParameter("updateFrequency", 1);
    -    register = parameterParser.getStringParameter("register", "");
    -    unregister = parameterParser.getStringParameter("unregister", "");
    -    remove = (unregister.equalsIgnoreCase("Unregister"));
    -    siteScheduleID = getSiteScheduleID(conn, ldapDN);
    -    dateLastHarvest = getDateLastHarvest(conn, siteScheduleID);
    -
    -    res.setContentType("text/plain");
    -    out = res.getWriter();
    -
    -    if (!remove) {    
    -      validValues = checkValues(out, documentListURL, updateFrequency);
    -      
    -      if (!validValues) {
    -        return;
    -      }
    -    }
    -    
    -    if (siteScheduleID == 0) {
    -      if (remove) {
    -        // The user clicked Unregister, but no existing record was found
    -        System.out.println("Unable to remove record for user " + ldapDN);
    -        System.out.println("No matching record found in HARVEST_SITE_SCHEDULE");
    -        out.println("No record found for user " + ldapDN + ".");
    -        out.println("Since you were not registered, no action was taken.");
    -      }
    -      else {
    -        maxValue = getMaxValue(conn,
    -                               "HARVEST_SITE_SCHEDULE",
    -                               "SITE_SCHEDULE_ID");
    -        siteScheduleID = maxValue + 1;
    -        dbInsert(out, conn, siteScheduleID, contactEmail, documentListURL,
    -                 ldapDN, ldapPwd, unit, updateFrequency);
    -      }
    -    }
    -    else {
    -      // Either update or remove an existing record
    -      if (remove) {
    -        dbRemove(out, conn, siteScheduleID, ldapDN);
    -      }
    -      else {
    -        dbUpdate(out, conn, siteScheduleID, contactEmail, documentListURL,
    -                 ldapDN, ldapPwd, unit, updateFrequency, dateLastHarvest);
    -      }
    -    }
    -    
    -    closeConnection(conn);
    -  }
    -  
    -
    -  /**
    -   * Gets a database connection.
    -   * 
    -   * @return  conn, the Connection object
    -   */
    -  private Connection getConnection() {
    -    Connection conn = null;
    -    SQLWarning warn;
    -
    -    // Make the database connection
    -    try {
    -      System.out.println("Getting connection to Harvester tables");
    -      conn = DriverManager.getConnection(defaultDB, user, password);
    -
    -      // If a SQLWarning object is available, print its warning(s).
    -      // There may be multiple warnings chained.
    -      warn = conn.getWarnings();
    -      
    -      if (warn != null) {
    -        while (warn != null) {
    -          System.out.println("SQLState: " + warn.getSQLState());
    -          System.out.println("Message:  " + warn.getMessage());
    -          System.out.println("Vendor: " + warn.getErrorCode());
    -          System.out.println("");
    -          warn = warn.getNextWarning();
    -        }
    -      }
    -    }
    -    catch (SQLException e) {
    -      System.out.println("Database access failed " + e);
    -    }
    -    
    -    return conn;
    -  }
    -
    -
    -  /**
    -   * Gets the date of last harvest value from the HARVEST_SITE_SCHEDULE table,
    -   * given a siteScheduleID value (the primary key).
    -   * 
    -   * @param  conn            the connection
    -   * @param  siteScheduleID  the primary key
    -   * @return dateLastHarvest the string stored in the table, e.g.
    -   *                         "2004-04-30 00:00:00.0" or ""
    -   */
    -  private String getDateLastHarvest(Connection conn, int siteScheduleID) {
    -    String dateLastHarvest = "";
    -    String query = "SELECT DATELASTHARVEST FROM HARVEST_SITE_SCHEDULE " +
    -                   "WHERE SITE_SCHEDULE_ID=" + siteScheduleID;
    -	Statement stmt;
    -    
    -	try {
    -      stmt = conn.createStatement();
    -      ResultSet rs = stmt.executeQuery(query);
    -	
    -      while (rs.next()) {
    -        dateLastHarvest = rs.getString("DATELASTHARVEST");
    -        if (rs.wasNull()) {
    -          dateLastHarvest = "";  // Convert null value to empty string
    -        }
    -      }
    -      
    -      stmt.close();
    -    }
    -    catch (SQLException ex) {
    -      System.out.println("SQLException: " + ex.getMessage());
    -    }
    -    
    -    return dateLastHarvest;
    -  }
    -  
    -
    -  /** 
    -   * Gets the maximum value of an integer field from a table, given the table
    -   * name and the field name.
    -   * 
    -   * @param tableName  the database table name
    -   * @param fieldName  the field name of the integer field in the table
    -   * @return  the maximum integer stored in the fieldName field of tableName
    -   */
    -  private int getMaxValue(Connection conn, String tableName, String fieldName) {
    -    int maxValue = 0;
    -    int fieldValue;
    -    String query = "SELECT " + fieldName + " FROM " + tableName;
    -    Statement stmt;
    -    
    -    try {
    -      stmt = conn.createStatement();
    -      ResultSet rs = stmt.executeQuery(query);
    -      
    -      while (rs.next()) {
    -        fieldValue = rs.getInt(fieldName);
    -        maxValue = Math.max(maxValue, fieldValue);
    -      }
    -      
    -      stmt.close();
    -    } 
    -    catch (SQLException ex) {
    -      System.out.println("SQLException: " + ex.getMessage());
    -    }
    -    
    -    return maxValue;
    -  }
    -  
    -
    -  /**
    -   * Gets the siteScheduleID value from the HARVEST_SITE_SCHEDULE table, given
    -   * the value of the ldapDN field.
    -   * 
    -   * @param conn   the database connection
    -   * @param ldapDN the ldap DN string
    -   * @return  siteScheduleID, an integer, the primary key
    -   */
    -  private int getSiteScheduleID(Connection conn, String ldapDN) {
    -    String ldapDNValue;                       // value of LDAPDN field
    -    String query = "SELECT * FROM HARVEST_SITE_SCHEDULE";
    -    int siteScheduleID = 0;
    -    Statement stmt;
    -    
    -    
    -    try {
    -      stmt = conn.createStatement();
    -      ResultSet rs = stmt.executeQuery(query);
    -      
    -      while (rs.next()) {
    -        ldapDNValue = rs.getString("LDAPDN");
    -        
    -        if (ldapDNValue.equalsIgnoreCase(ldapDN)) {
    -          siteScheduleID = rs.getInt("SITE_SCHEDULE_ID");
    -        }
    -      }
    -      
    -      stmt.close();
    -    }
    -    catch (SQLException ex) {
    -      System.out.println("SQLException: " + ex.getMessage());
    -    }
    -    
    -    return siteScheduleID;
    -  }
    -  
    -
    -    /**
    -	 * Initializes the servlet. Reads properties and initializes object fields.
    -	 * 
    -	 * @throws ServletException
    -	 */
    -	public void init(ServletConfig config) throws ServletException {
    -		String database;
    -		String dbDriver = "";
    -		String dirPath;
    -
    -		super.init(config);
    -		this.config = config;
    -		this.context = config.getServletContext();
    -		dirPath = context.getRealPath(CONFIG_DIR);
    -
    -		try {
    -		    ServletContext context = config.getServletContext();
    -			PropertyService.getInstance(context);
    -
    -			dbDriver = PropertyService.getProperty("database.driver");
    -			defaultDB = PropertyService.getProperty("database.connectionURI");
    -			password = PropertyService.getProperty("database.password");
    -			user = PropertyService.getProperty("database.user");
    -		} catch (ServiceException se) {
    -			System.out.println("Error initializing PropertyService: " + se.getMessage());
    -		} catch (PropertyNotFoundException pnfe) {
    -			System.out.println("Error reading property: " + pnfe.getMessage());
    -		}
    -
    -		// Load the jdbc driver
    -		try {
    -			Class.forName(dbDriver);
    -		} catch (ClassNotFoundException e) {
    -			System.out.println("Can't load driver " + e);
    -		}
    -	}
    -
    -
    -  /**
    -	 * Surrounds a string with single quotes.
    -	 * 
    -	 * @param str
    -	 *            the original string
    -	 * @return the quoted string
    -	 */
    -  private String quoteString(String str) {
    -    return "'" + str + "'";
    -  }
    -  
    -  
    -  /**
    -   * Reports the results of an insert or update to the client.
    -   * 
    -   * @param out               the PrintWriter
    -   * @param ldapDN            the LDAP DN string
    -   * @param contactEmail      the email address of the site contact
    -   * @param documentListURL   the URL of the harvester document list at the site
    -   * @param updateFrequency   the harvest update frequency
    -   * @param unit              the unit (e.g. "days", "weeks", "months"
    -   * @param dateNextHarvest   the date of the next scheduled harvest
    -   */
    -  private void reportResults(PrintWriter out,
    -                             String ldapDN,
    -                             String contactEmail,
    -                             String documentListURL,
    -                             int updateFrequency,
    -                             String unit,
    -                             String dateNextHarvest
    -                            ) {
    -    out.println("Harvester registration updated for " + ldapDN);
    -    out.println("  Email Address:             " + contactEmail);
    -    out.println("  Harvest List URL:          " + documentListURL);
    -    out.println("  Harvest Frequency:         " + updateFrequency);
    -    out.println("  Unit:                      " + unit);
    -    out.println("");
    -    out.println("Next scheduled harvest date: " + dateNextHarvest);
    -  }
    -  
    -}
    
  • src/edu/ucsb/nceas/metacat/harvesterClient/HarvesterRegistrationLogin.java+0 135 removed
    @@ -1,135 +0,0 @@
    -/**
    - *  '$RCSfile$'
    - *  Copyright: 2004 University of New Mexico and the 
    - *                  Regents of the University of California
    - *
    - *   '$Author$'
    - *     '$Date$'
    - * '$Revision$'
    - *
    - * This program is free software; you can redistribute it and/or modify
    - * it under the terms of the GNU General Public License as published by
    - * the Free Software Foundation; either version 2 of the License, or
    - * (at your option) any later version.
    - *
    - * This program is distributed in the hope that it will be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write to the Free Software
    - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    - */
    -
    -package edu.ucsb.nceas.metacat.harvesterClient;
    -
    -import java.io.PrintWriter;
    -
    -import javax.servlet.ServletException;
    -import javax.servlet.http.HttpServlet;
    -import javax.servlet.http.HttpServletRequest;
    -import javax.servlet.http.HttpServletResponse;
    -import javax.servlet.http.HttpSession;
    -
    -import edu.ucsb.nceas.metacat.AuthSession;
    -import edu.ucsb.nceas.metacat.properties.PropertyService;
    -import edu.ucsb.nceas.metacat.util.SystemUtil;
    -
    -
    -/**
    - *  HarvesterRegistrationLogin implements a servlet to login to the Harvester
    - *  Registration servlet.
    - */
    -public class HarvesterRegistrationLogin extends HttpServlet {
    -
    -    final String LDAP_DOMAIN = ",dc=ecoinformatics,dc=org";
    -
    -    /**
    -     *  Handle "GET" method requests from HTTP clients
    -     *
    -     *  @param  req   The request
    -     *  @param  res   The response
    -     *  @throws ServletException, java.io.IOException
    -     */
    -    public void doGet(HttpServletRequest req, HttpServletResponse res)
    -                throws ServletException, java.io.IOException {
    -        handleGetOrPost(req, res);
    -    }
    -
    -
    -    /**
    -     *  Handle "POST" method requests from HTTP clients
    -     *
    -     *  @param  req   The request
    -     *  @param  res  The response
    -     *  @throws ServletException, java.io.IOException
    -     */
    -    public void doPost(HttpServletRequest req, HttpServletResponse res)
    -                throws ServletException, java.io.IOException {
    -        handleGetOrPost(req, res);
    -    }
    -
    -
    -    /**
    -     *  Handle "GET" or "POST" method requests from HTTP clients
    -     *
    -     *  @param  req   The request
    -     *  @param  res  The response
    -     *  @throws ServletException, java.io.IOException
    -     */
    -    private void handleGetOrPost(HttpServletRequest req,
    -                                 HttpServletResponse res)
    -                 throws ServletException, java.io.IOException {
    -        AuthSession authSession;
    -        String authSessionMessage;
    -        HttpSession httpSession;
    -        boolean isValid;
    -        String o = req.getParameter("o");
    -        String organization;
    -        String passwd = req.getParameter("passwd");
    -        PrintWriter out = res.getWriter();
    -        String uid = req.getParameter("uid");
    -        String user;
    -
    -        if ((uid == null) || (uid.equals(""))) {
    -          out.println("Invalid login: no Username specified.");
    -          return;
    -        }
    -        else if ((o == null) || (o.equals(""))) {
    -          out.println("Invalid login: no Organization selected.");
    -          return;
    -        }
    -        else if ((passwd == null) || (passwd.equals(""))) {
    -          out.println("Invalid login: no Password specified.");
    -          return;
    -        }
    -        else {
    -          user = "uid=" + uid + ",o=" + o + LDAP_DOMAIN;
    -        }
    -
    -        res.setContentType("text/plain");
    -        
    -        try {
    -          authSession = new AuthSession();
    -          isValid = authSession.authenticate(req, user, passwd);
    -          authSessionMessage = authSession.getMessage();
    -          System.out.println("authSession.authenticate(): "+authSessionMessage);
    -          out.println("authSession.authenticate(): " + authSessionMessage);
    -
    -          if (isValid) {
    -            httpSession = req.getSession(true);
    -            httpSession.setAttribute("username", user);
    -            httpSession.setAttribute("password", passwd);
    -            String context = PropertyService.getProperty("application.context");
    -            res.sendRedirect("/" + context + "/harvesterRegistration");
    -          }
    -          else {
    -            out.println("Invalid login");
    -          }
    -        } 
    -        catch (Exception e) {
    -          System.out.println("Error in AuthSession()" + e.getMessage());
    -        }
    -    }
    -}
    
  • src/edu/ucsb/nceas/metacat/harvesterClient/HarvesterServlet.java+0 100 removed
    @@ -1,100 +0,0 @@
    -/**
    - *  '$RCSfile$'
    - *  Copyright: 2004 University of New Mexico and the 
    - *             Regents of the University of California
    - *
    - *   '$Author$'
    - *     '$Date$'
    - * '$Revision$'
    - *
    - * This program is free software; you can redistribute it and/or modify
    - * it under the terms of the GNU General Public License as published by
    - * the Free Software Foundation; either version 2 of the License, or
    - * (at your option) any later version.
    - *
    - * This program is distributed in the hope that it will be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write to the Free Software
    - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    - */
    -
    -package edu.ucsb.nceas.metacat.harvesterClient;
    -
    -import javax.servlet.*;
    -import javax.servlet.http.*;
    -/**
    - * HarvesterServlet class allows Harvester to be run as a background
    - * process. This eliminates the need to run Harvester in a terminal window.
    - * To activate this servlet, uncomment the HarvesterServlet entry in the
    - * appropriate 'lib/web.xml.tomcat*' file.
    - * 
    - * @author costa
    - */
    -public class HarvesterServlet extends HttpServlet implements Runnable {
    -
    -  /*
    -   * Class fields
    -   */
    -  private static final String SCHEMA_DIR = "harvester";
    -  private static String SCHEMA_LOCATION;
    -  private static final String SCHEMA_NAME = "harvestList.xsd";
    -  static final long serialVersionUID = 0;  // Needed for Eclipse warning.
    -
    -  /*
    -   * Object fields
    -   */  
    -  Thread harvesterThread;                // background Harvester thread
    -
    -
    -  /**
    -   * When the thread is destroyed, sets the Harvester.keepRunning flag to false.
    -   */
    -  public void destroy() {
    -    Harvester.setKeepRunning(false);
    -  }
    -  
    -
    -  /**
    -   * Initializes the servlet. Reads properties and initializes object fields.
    -   * 
    -   * @throws ServletException
    -   */
    -  public void init(ServletConfig config) throws ServletException {
    -    ServletContext context = null;
    -    String fileSeparator = System.getProperty("file.separator");
    -    String schemaPath;
    -
    -    super.init(config);
    -    context = config.getServletContext();
    -    schemaPath = context.getRealPath(SCHEMA_DIR) + fileSeparator + SCHEMA_NAME;
    -    SCHEMA_LOCATION = "eml://ecoinformatics.org/harvestList " + schemaPath;
    -    harvesterThread = new Thread(this);
    -    harvesterThread.setPriority(Thread.MIN_PRIORITY);  // be a good citizen
    -    harvesterThread.start();
    -  }
    -
    -
    -  /**
    -   * Runs the Harvester main program in a separate thread. First sleeps for
    -   * 30 seconds to give Metacat a chance to fully initialize.
    -   */
    -  public void run() {
    -      String[] args = new String[2];
    -      args[0] = "false";     // Set to true if in command line mode or test mode
    -      args[1] = SCHEMA_LOCATION;
    -
    -      try {
    -        Thread.sleep(30000);    // Sleep 30 seconds before starting Harvester
    -      }
    -      catch (InterruptedException e) {
    -        System.err.println("InterruptedException: " + e.getMessage());
    -      }
    -
    -      Harvester.main(args);
    -  }
    -
    -}
    
  • src/edu/ucsb/nceas/metacat/harvesterClient/HarvestListEditor.java+0 1199 removed
    @@ -1,1199 +0,0 @@
    -/**
    - *  '$RCSfile$'
    - *  Copyright: 2004 University of New Mexico and the 
    - *                  Regents of the University of California
    - *
    - *   '$Author$'
    - *     '$Date$'
    - * '$Revision$'
    - *
    - * This program is free software; you can redistribute it and/or modify
    - * it under the terms of the GNU General Public License as published by
    - * the Free Software Foundation; either version 2 of the License, or
    - * (at your option) any later version.
    - *
    - * This program is distributed in the hope that it will be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write to the Free Software
    - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    - */
    -
    -package edu.ucsb.nceas.metacat.harvesterClient;
    -
    -import java.awt.BorderLayout;
    -import java.awt.Dimension;
    -import java.awt.event.ActionEvent;
    -import java.awt.event.ActionListener;
    -import java.io.File;
    -import java.io.FileInputStream;
    -import java.io.FileWriter;
    -import java.io.IOException;
    -import java.io.InputStream;
    -import java.io.InputStreamReader;
    -import java.io.PrintStream;
    -import java.io.PrintWriter;
    -import java.io.Reader;
    -import java.util.Properties;
    -import javax.swing.JButton;
    -import javax.swing.JFileChooser;
    -import javax.swing.JFrame;
    -import javax.swing.JMenu;
    -import javax.swing.JMenuBar;
    -import javax.swing.JMenuItem;
    -import javax.swing.JOptionPane;
    -import javax.swing.JPanel;
    -import javax.swing.JScrollPane;
    -import javax.swing.JTable;
    -import javax.swing.KeyStroke;
    -import javax.swing.ListSelectionModel;
    -import javax.swing.event.ListSelectionEvent;
    -import javax.swing.event.ListSelectionListener;
    -import javax.swing.table.AbstractTableModel;
    -import javax.swing.table.TableColumn;
    -import javax.swing.table.TableModel;
    -import javax.swing.text.Document;
    -import javax.xml.parsers.ParserConfigurationException;
    -import org.xml.sax.Attributes;
    -import org.xml.sax.ContentHandler;
    -import org.xml.sax.ErrorHandler;
    -import org.xml.sax.InputSource;
    -import org.xml.sax.SAXException;
    -import org.xml.sax.SAXParseException;
    -import org.xml.sax.XMLReader;
    -import org.xml.sax.helpers.DefaultHandler;
    -import org.xml.sax.helpers.XMLReaderFactory;
    -
    -/**
    - * The Harvest List Editor reads a Harvest List XML file and displays it as a 
    - * JTable. Allows user to add, modify, or delete <Document> elements in the
    - * Harvest List, and save changes back to the disk.
    - * 
    - */
    -public class HarvestListEditor extends JFrame implements ActionListener {
    -
    -  String clipboardDocumentType = "";
    -  String clipboardDocumentURL = "";
    -  String clipboardIdentifier = "";
    -  String clipboardRevision = "";
    -  String clipboardScope = "";
    -  JButton copyButton;
    -  JButton cutButton;
    -  String defaultDocumentType = "eml://ecoinformatics.org/eml-2.0.1";
    -  String defaultDocumentURL = "http://";
    -  String defaultHarvestList = "";
    -  String defaultIdentifier = "1";
    -  String defaultRevision = "1";
    -  String defaultScope = "dataset";
    -  Document doc;
    -  JScrollPane docPane;
    -  JFileChooser fileChooser = new JFileChooser();
    -  File harvestListFile;
    -  boolean harvestListHasChanged = false;
    -  JMenuBar menuBar;
    -  final int numColumns = 6;
    -  final int numRows = 1200;
    -  JButton pasteButton;
    -  JButton pasteDefaultsButton;
    -  Properties properties;
    -  private String schemaLocation = 
    -    "eml://ecoinformatics.org/harvestList harvestList.xsd";
    -  int selectedRow = -1;
    -  final JTable table;
    -  TableModel tableModel;
    -  File tempFile;
    -  String title = "Harvest List Editor";
    -  
    -  // Menu items
    -  JMenuItem exitMenuItem = new JMenuItem("Exit");
    -  JMenuItem newMenuItem = new JMenuItem("New");
    -  JMenuItem openMenuItem = new JMenuItem("Open...");
    -  JMenuItem saveMenuItem = new JMenuItem("Save");
    -  JMenuItem saveAsMenuItem = new JMenuItem("Save As...");
    -  JMenuItem validateMenuItem = new JMenuItem("Validate");
    -  
    -
    -  /**
    -   * The main program. Instantiate the main frame, a HarvestListEditor object.
    -   * 
    -   * @param args
    -   */
    -  public static void main(String[] args) {
    -    HarvestListEditor harvestListEditor = new HarvestListEditor();
    -  }
    -
    -
    -  /**
    -   * Constructor for HarvestListEditor class.
    -   */
    -  public HarvestListEditor() {
    -    super("Harvest List Editor");
    -
    -    JPanel buttonPanel = new JPanel();
    -    String[] fileItems = 
    -                  new String[] {"New", "Open...", "Save", "Save As...", "Exit"};
    -    JMenu fileMenu = new JMenu("File");
    -    char[] fileShortCuts = {'N', 'O', 'S', 'A', 'X'};
    -    TableColumn tableColumn;
    -    
    -    loadProperties();
    -    setSize(1000, 400);
    -    setDefaultCloseOperation(EXIT_ON_CLOSE);
    -    menuBar = new JMenuBar();
    -    
    -    /*
    -     * Add menu items to the File menu
    -     */
    -    newMenuItem.setAccelerator(KeyStroke.getKeyStroke('N',
    -									                  java.awt.Event.CTRL_MASK,
    -                                                      false));
    -    newMenuItem.addActionListener(this);
    -    fileMenu.add(newMenuItem);
    -
    -    openMenuItem.setAccelerator(KeyStroke.getKeyStroke('O',
    -									                   java.awt.Event.CTRL_MASK,
    -                                                       false));
    -    openMenuItem.addActionListener(this);
    -    fileMenu.add(openMenuItem);
    -
    -    saveMenuItem.setAccelerator(KeyStroke.getKeyStroke('S',
    -									                   java.awt.Event.CTRL_MASK,
    -                                                       false));
    -    saveMenuItem.addActionListener(this);
    -    saveMenuItem.setEnabled(false);
    -    fileMenu.add(saveMenuItem);
    -
    -    saveAsMenuItem.setAccelerator(KeyStroke.getKeyStroke('A',
    -									                   java.awt.Event.CTRL_MASK,
    -                                                       false));
    -    saveAsMenuItem.addActionListener(this);
    -    fileMenu.add(saveAsMenuItem);
    -
    -    validateMenuItem.setAccelerator(KeyStroke.getKeyStroke('V',
    -									                   java.awt.Event.CTRL_MASK,
    -                                                       false));
    -    validateMenuItem.addActionListener(this);
    -    fileMenu.add(validateMenuItem);
    -
    -    exitMenuItem.setAccelerator(KeyStroke.getKeyStroke('X',
    -									                   java.awt.Event.CTRL_MASK,
    -                                                       false));
    -    exitMenuItem.addActionListener(this);
    -    fileMenu.add(exitMenuItem);
    -    
    -    menuBar.add(fileMenu);      // Add the File menu to the menu bar
    -    setJMenuBar(menuBar);       // Set the frame's menu bar to this menu bar
    -
    -    //table = new JTable(numRows, numColumns);
    -    table = new JTable(new HarvestListTableModel());
    -    table.setPreferredScrollableViewportSize(new Dimension(900, 300));
    -    tableColumn = table.getColumnModel().getColumn(0);
    -    tableColumn.setPreferredWidth(30);
    -    tableColumn = table.getColumnModel().getColumn(1);
    -    tableColumn.setPreferredWidth(200);
    -    tableColumn = table.getColumnModel().getColumn(2);
    -    tableColumn.setPreferredWidth(50);
    -    tableColumn = table.getColumnModel().getColumn(3);
    -    tableColumn.setPreferredWidth(50);
    -    tableColumn = table.getColumnModel().getColumn(4);
    -    tableColumn.setPreferredWidth(250);
    -    tableColumn = table.getColumnModel().getColumn(5);
    -    tableColumn.setPreferredWidth(320);
    -    
    -    table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    -    tableModel = table.getModel();
    -    initHarvestList();
    -
    -    //Ask to be notified of selection changes.
    -    ListSelectionModel rowSM = table.getSelectionModel();
    -
    -    rowSM.addListSelectionListener(new ListSelectionListener() {
    -      public void valueChanged(ListSelectionEvent e) {
    -        ListSelectionModel lsm;
    -
    -        //Ignore extra messages.
    -        if (e.getValueIsAdjusting()) return;
    -
    -        lsm = (ListSelectionModel)e.getSource();
    -
    -        // If now row is selected, disable all buttons.
    -        if (lsm.isSelectionEmpty()) {
    -          selectedRow = -1;
    -          cutButton.setEnabled(false);
    -          copyButton.setEnabled(false);
    -          pasteButton.setEnabled(false);
    -          pasteDefaultsButton.setEnabled(false);
    -        }
    -        // If a row is selected, manage the buttons based on the selected row
    -        // and the current clipboard values.
    -        else {
    -          selectedRow = lsm.getMinSelectionIndex();
    -          manageButtons(selectedRow);
    -        }
    -      }
    -    });
    -
    -    docPane = new JScrollPane(table);
    -    getContentPane().add(docPane, BorderLayout.CENTER);
    -    
    -    cutButton = new JButton("Cut");
    -    copyButton = new JButton("Copy");
    -    pasteButton = new JButton("Paste");
    -    pasteDefaultsButton = new JButton("Paste Defaults");
    -
    -    // Action listener for the Copy button.    
    -    copyButton.addActionListener(new ActionListener() {
    -      public void actionPerformed(ActionEvent ae) {				
    -        copyRow(selectedRow);
    -        manageButtons(selectedRow);
    -        harvestListHasChanged = true;
    -			}
    -		}
    -    );
    -
    -    // Action listener for the Cut button.    
    -    cutButton.addActionListener(new ActionListener() {
    -      public void actionPerformed(ActionEvent ae) {				
    -        cutRow(selectedRow);
    -        manageButtons(selectedRow);
    -        harvestListHasChanged = true;
    -			}
    -		}
    -    );
    -
    -    // Action listener for the Paste button.    
    -    pasteButton.addActionListener(new ActionListener() {
    -      public void actionPerformed(ActionEvent ae) {
    -        pasteRow(selectedRow);
    -        manageButtons(selectedRow);
    -        harvestListHasChanged = true;
    -			}
    -		}
    -    );
    -
    -    // Action listener for the Paste Defaults button.    
    -    pasteDefaultsButton.addActionListener(new ActionListener() {
    -      public void actionPerformed(ActionEvent ae) {
    -        pasteDefaultValues(selectedRow);
    -        manageButtons(selectedRow);
    -        harvestListHasChanged = true;
    -			}
    -		}
    -    );
    -
    -    cutButton.setEnabled(false);
    -    copyButton.setEnabled(false);
    -    pasteButton.setEnabled(false);
    -    pasteDefaultsButton.setEnabled(false);
    -    buttonPanel.add(cutButton);
    -    buttonPanel.add(copyButton);
    -    buttonPanel.add(pasteButton);
    -    buttonPanel.add(pasteDefaultsButton);
    -    buttonPanel.setOpaque(true);
    -    getContentPane().add(buttonPanel, BorderLayout.SOUTH);
    -
    -    // If the default Harvest List option has a value, and the file exists, 
    -    // loads its contents.
    -    //
    -    if ((defaultHarvestList != null) && (!defaultHarvestList.equals(""))) {
    -      harvestListFile = new File(defaultHarvestList);
    -      if (harvestListFile.exists()) {
    -        try {
    -          loadHarvestList(harvestListFile);
    -          saveMenuItem.setEnabled(true);
    -        }
    -        catch (ParserConfigurationException e) {
    -          System.out.println("Error parsing Harvest List: " + e.getMessage());
    -        }        
    -      }
    -      else {
    -        System.out.println(
    -          "Warning: the default harvest list file that was specified in the " + 
    -          ".harvestListEditor configuration file does not exist:\n" +
    -          harvestListFile
    -                          );
    -        fileNew();
    -      }
    -    }
    -    else {
    -      fileNew();
    -    }
    -
    -    try {    
    -      tempFile = File.createTempFile("harvestListTemp", ".xml");
    -    }
    -    catch (IOException ioe) {
    -      System.out.println("Error creating temporary file: " + ioe.getMessage());
    -    }
    -    
    -    setVisible(true);
    -  }
    -
    -
    -  /**
    -   * Implements action listeners for menu items.
    -   * 
    -   * @param e   An ActionEvent object, determines the menu item that was
    -   *            selected.
    -   */
    -  public void actionPerformed(ActionEvent e) {
    -    if ((e.getActionCommand()).equals("New")) {
    -      fileNew();
    -    }    
    -    else if ((e.getActionCommand()).equals("Open...")) {
    -      fileOpen();
    -    }    
    -    else if ((e.getActionCommand()).equals("Save")) {
    -      fileSave();
    -    }    
    -    else if ((e.getActionCommand()).equals("Save As...")) {
    -      fileSaveAs();
    -    }
    -    else if ((e.getActionCommand()).equals("Validate")) {
    -      fileValidate();
    -    }
    -    else if ((e.getActionCommand()).equals("Exit")) {
    -      fileExit();
    -    }
    -  }
    -  
    -
    -  /**
    -   * Adds a new row to the table, setting values for each of the five columns
    -   * in the row.
    -   * 
    -   * @param rowIndex              the row index
    -   * @param scope                 the scope string
    -   * @param identifier            the identifier string
    -   * @param revision              the revision string
    -   * @param documentType          the document type
    -   * @param documentURL           the document URL
    -   */
    -  void addRow(int rowIndex, String scope, String identifier, String revision,
    -              String documentType, String documentURL) {
    -    tableModel.setValueAt(scope,                 rowIndex, 1);
    -    tableModel.setValueAt(identifier,            rowIndex, 2);
    -    tableModel.setValueAt(revision,              rowIndex, 3);
    -    tableModel.setValueAt(documentType,          rowIndex, 4);
    -    tableModel.setValueAt(documentURL,           rowIndex, 5);
    -  }
    -
    -
    -  /**
    -   * Composes a single tag line to be written in the Harvest List.
    -   * 
    -   * @param indentLevel    the number of spaces to begin the line with
    -   * @param tag            the tag name
    -   * @param text           the text to insert within the begin and end tags
    -   * @return line          the composed line
    -   */
    -  String composeLine(int indentLevel, String tag, String text) {
    -    String line = "";
    -    
    -    for (int i = 0; i < indentLevel; i++) {
    -      line += " ";
    -    }
    -    
    -    line += "<" + tag + ">";
    -    line += text;
    -    line += "</" + tag + ">";
    -    
    -    return line;
    -  }
    -  
    -
    -  /**
    -   * Clears all rows in the table, setting all values to null.
    -   */
    -  void clearHarvestList() {
    -    for (int rowIndex = 0; rowIndex < numRows; rowIndex++) {
    -      clearRow(rowIndex);
    -    }
    -  }
    -  
    -
    -  /**
    -   * Clears a single row in the tables, setting all five fields to null.
    -   * 
    -   * @param rowIndex   the index to the table row to be cleared
    -   */
    -  void clearRow(int rowIndex) {
    -    final String nil = "";
    -    
    -    tableModel.setValueAt(nil, rowIndex, 1);
    -    tableModel.setValueAt(nil, rowIndex, 2);
    -    tableModel.setValueAt(nil, rowIndex, 3);
    -    tableModel.setValueAt(nil, rowIndex, 4);
    -    tableModel.setValueAt(nil, rowIndex, 5);    
    -  }
    -  
    -
    -  /**
    -   * Copies the values in a given table row to the clipboard.
    -   * 
    -   * @param rowIndex  the index of the table row to be copied
    -   */
    -  void copyRow(int rowIndex) {
    -    clipboardScope = (String) tableModel.getValueAt(rowIndex, 1);
    -    clipboardIdentifier = (String) tableModel.getValueAt(rowIndex, 2);
    -    clipboardRevision = (String) tableModel.getValueAt(rowIndex, 3);
    -    clipboardDocumentType = (String) tableModel.getValueAt(rowIndex, 4);    
    -    clipboardDocumentURL = (String) tableModel.getValueAt(rowIndex, 5);
    -  }
    -  
    -
    -  /**
    -   * Cuts a row from the table. The row is copied to the clipboard and then
    -   * cleared.
    -   * 
    -   * @param rowIndex  the index of the table row to be copied
    -   */
    -  void cutRow(int rowIndex) {
    -    copyRow(rowIndex);
    -    clearRow(rowIndex);
    -  }
    -  
    -
    -  /**
    -   * Exit from the Harvest List Editor. Prompt to save changes if appropriate.
    -   */
    -  void fileExit() {
    -    int value;
    -
    -    if (harvestListHasChanged) {
    -      value = saveChangesDialog();
    -      
    -      if (value == JOptionPane.YES_OPTION) {
    -        try {
    -          // Save the changes then exit
    -          //
    -          fileSave();
    -          System.exit(0);
    -        }
    -        catch (Exception exception) {
    -          exception.printStackTrace();
    -        }
    -      }
    -      else if (value == JOptionPane.NO_OPTION) {
    -        // Exit without saving changes
    -        System.exit(0);
    -      } 
    -    }
    -    else {
    -      System.exit(0);
    -    }
    -  }
    -  
    -
    -  /**
    -   * Replace the current Harvest List with an empty Harvest List. Prompt to save
    -   * changes if appropriate.
    -   */
    -  void fileNew() {
    -    int value;
    -    
    -    if (harvestListHasChanged) {
    -      value = saveChangesDialog();
    -      
    -      if (value == JOptionPane.YES_OPTION) {
    -        try {
    -          fileSave();
    -        }
    -        catch (Exception exception) {
    -          exception.printStackTrace();
    -        }
    -      }
    -      else if (value == JOptionPane.CANCEL_OPTION) {
    -        return;
    -      }
    -    }
    -
    -    clearHarvestList();
    -    harvestListFile = null;
    -    setTitle(title + ": (Untitled)");
    -    saveMenuItem.setEnabled(false);
    -    harvestListHasChanged = false;    
    -  }
    -  
    -
    -  /**
    -   * Opens a file dialog to load a Harvest List. Prompts to save changes to the
    -   * current Harvest List if appropriate.
    -   */
    -  void fileOpen() {
    -    int value;
    -    
    -    if (harvestListHasChanged) {
    -      value = saveChangesDialog();
    -      
    -      if (value == JOptionPane.YES_OPTION) {
    -        try {
    -          fileSave();
    -        }
    -        catch (Exception exception) {
    -          exception.printStackTrace();
    -        }
    -      }
    -      else if (value == JOptionPane.CANCEL_OPTION) {
    -        return;
    -      }
    -    }
    -
    -    value = fileChooser.showOpenDialog(HarvestListEditor.this);
    -    
    -    if (value == JFileChooser.APPROVE_OPTION) {
    -      harvestListFile = fileChooser.getSelectedFile();
    -      try {
    -        clearHarvestList();
    -        loadHarvestList(harvestListFile);
    -      }
    -      catch (ParserConfigurationException e) {
    -        System.out.println("Error parsing Harvest List: " + e.getMessage());
    -      }        
    -      harvestListHasChanged = false;
    -      saveMenuItem.setEnabled(true);
    -    }
    -  }
    -  
    -
    -  /**
    -   * Save the current Harvest List to disk.
    -   */
    -  void fileSave() {
    -    if (harvestListFile != null) {
    -      writeFile(harvestListFile);
    -      harvestListHasChanged = false;
    -    }
    -    else {
    -      System.out.println("No action taken");
    -    }
    -  }
    -  
    -
    -  /**
    -   * Save the current Harvest List as a potentially different file name.
    -   */
    -  void fileSaveAs() {
    -    int returnVal;
    -    
    -    returnVal = fileChooser.showOpenDialog(HarvestListEditor.this);
    -    
    -    if (returnVal == JFileChooser.APPROVE_OPTION) {
    -      harvestListFile = fileChooser.getSelectedFile();
    -      writeFile(harvestListFile);
    -      setTitle(title + ": " + harvestListFile.getName());
    -      saveMenuItem.setEnabled(true);
    -      harvestListHasChanged = false;
    -    }
    -  }
    -  
    -  
    -  /**
    -   * Validate the Harvest List that is currently stored in the table. This is
    -   * implemented by writing the Harvest List to a temporary file and then
    -   * running the SAX parser on the temporary file.
    -   */
    -  void fileValidate() {
    -    FileInputStream fis;
    -    HarvestListHandler harvestListHandler = new HarvestListHandler();
    -    InputStreamReader inputStreamReader;
    -    boolean loadHarvestList = false;
    -    boolean validateHarvestList = true;
    -    
    -    writeFile(tempFile);
    -    
    -    try {
    -      fis = new FileInputStream(tempFile);
    -      inputStreamReader = new InputStreamReader(fis);
    -      harvestListHandler.runParser(this, inputStreamReader, schemaLocation,
    -                                   loadHarvestList, validateHarvestList);
    -      fis.close();
    -      tempFile.delete();
    -      harvestListMessage("Harvest List is valid");
    -    }
    -    catch (SAXException e) {
    -      harvestListMessage("Validation error: " + e.getMessage());
    -    }
    -    catch (ClassNotFoundException e) {
    -      System.out.println("ClassNotFoundException: " + e.getMessage());
    -    }
    -    catch (IOException ioe) {
    -      System.out.println("Error opening file: " + ioe.getMessage());
    -    }
    -  }
    -  
    -
    -  /**
    -   * Displays a short message in a dialog box.
    -   * 
    -   * @param message       the message text
    -   */
    -  void harvestListMessage(String message) {
    -    JOptionPane.showMessageDialog(this, message);
    -  }
    -  
    -
    -  /**
    -   * Initializes the Harvest List table, filling column 0 with row numbers.
    -   * This is a non-editable column, so its values should never change after
    -   * this point.
    -   */
    -  void initHarvestList() {
    -    for (int rowIndex = 0; rowIndex < numRows; rowIndex++) {
    -      tableModel.setValueAt(new Integer(rowIndex + 1).toString(), rowIndex, 0);
    -    }
    -  }
    -  
    -
    -  /**
    -   * Determines whether the clipboard is currently empty. The clipboard is
    -   * empty if all five of the fields are empty.
    -   * 
    -   * @return      true if the clipboard is empty, else false
    -   */
    -  boolean isEmptyClipboard() {
    -    boolean isEmpty = true;
    -    
    -    isEmpty = isEmpty && (clipboardScope.equals(""));
    -    isEmpty = isEmpty && (clipboardIdentifier.equals(""));
    -    isEmpty = isEmpty && (clipboardRevision.equals(""));
    -    isEmpty = isEmpty && (clipboardDocumentType.equals(""));
    -    isEmpty = isEmpty && (clipboardDocumentURL.equals(""));
    -    
    -    return isEmpty;
    -  }
    -    
    -
    -  /**
    -   * Determines whether a given row in the table is empty. A row is empty if
    -   * all five of its fields contain either null or "".
    -   * 
    -   * @param rowIndex    the index to the row in the table that is being checked
    -   * @return            true if the row is empty, else false
    -   */
    -  boolean isEmptyRow(int rowIndex) {
    -    boolean isEmpty = true;
    -    String scope = (String) tableModel.getValueAt(rowIndex, 1);
    -    String identifier = (String) tableModel.getValueAt(rowIndex, 2);
    -    String revision = (String) tableModel.getValueAt(rowIndex, 3);
    -    String documentType = (String) tableModel.getValueAt(rowIndex, 4);    
    -    String documentURL = (String) tableModel.getValueAt(rowIndex, 5);
    -    
    -    isEmpty = isEmpty && ((scope == null) || (scope.equals("")));
    -    isEmpty = isEmpty && ((identifier == null) || (identifier.equals("")));
    -    isEmpty = isEmpty && ((revision == null) || (revision.equals("")));
    -    isEmpty = isEmpty && ((documentType == null) || (documentType.equals("")));
    -    isEmpty = isEmpty && ((documentURL == null) || (documentURL.equals("")));
    -    
    -    return isEmpty;
    -  }
    -  
    -
    -  /**
    -   * Loads the Harvest List from a file. Parses the file using the inner class,
    -   * HarvestListHandler, a SAX parser.
    -   * 
    -   * @param harvestList  the File to be loaded
    -   * @throws ParserConfigurationException
    -   */
    -  void loadHarvestList(File harvestList) throws ParserConfigurationException {
    -    HarvestListHandler harvestListHandler = new HarvestListHandler();
    -    FileInputStream fis;
    -    InputStreamReader inputStreamReader;
    -    boolean loadHarvestList = true;
    -    boolean validateHarvestList = false;
    -
    -    try {
    -      fis = new FileInputStream(harvestList);
    -      inputStreamReader = new InputStreamReader(fis);
    -      //System.out.println("Opened file successfully.");
    -      harvestListHandler.runParser(this, inputStreamReader, schemaLocation,
    -                                   loadHarvestList, validateHarvestList);
    -      fis.close();
    -      setTitle(title + ": " + harvestListFile.getName());
    -    }
    -    catch (SAXException e) {
    -      System.out.println("Error parsing Harvest List: " + e.getMessage());
    -    }
    -    catch (ClassNotFoundException e) {
    -      System.out.println("ClassNotFoundException: " + e.getMessage());
    -    }
    -    catch (IOException ioe) {
    -      System.out.println("Error opening file: " + ioe.getMessage());
    -    }
    -  }
    -  
    -
    -  /**
    -   * Loads properties from the .harvestListEditor file in the user's home
    -   * directory.
    -   */
    -  void loadProperties () {
    -    String homedir = System.getProperty("user.home");
    -    File propertiesFile = new File(homedir, ".harvestListEditor");
    -
    -    properties = new Properties();
    -
    -    if (propertiesFile.exists()) {
    -      try {
    -        properties.load(new FileInputStream(propertiesFile));
    -        defaultHarvestList = properties.getProperty("defaultHarvestList");
    -        defaultDocumentType = properties.getProperty("defaultDocumentType");
    -        defaultDocumentURL = properties.getProperty("defaultDocumentURL");
    -        defaultIdentifier = properties.getProperty("defaultIdentifier");
    -        defaultRevision = properties.getProperty("defaultRevision");
    -        defaultScope = properties.getProperty("defaultScope");    
    -      }
    -      catch (IOException ioe) {
    -        System.out.println("Error loading properties file: " + 
    -                           ioe.getMessage());
    -      }  
    -    }
    -  }
    -  
    -
    -  /**
    -   * Enables or disables buttons depending on the state of the currently
    -   * selected row and the state of the clipboard.
    -   * 
    -   * @param rowIndex       the index of the currently selected row
    -   */
    -  void manageButtons(int rowIndex) {
    -    
    -    if (isEmptyRow(rowIndex)) {
    -      // Selected row is empty, so disable cut and copy
    -      cutButton.setEnabled(false);
    -      copyButton.setEnabled(false);
    -    }
    -    else {
    -      // Selected row is not empty, so enable cut and copy
    -      cutButton.setEnabled(true);
    -      copyButton.setEnabled(true);
    -    }
    -
    -    if (isEmptyClipboard()) {
    -      // Clipboard is empty, so disable paste
    -      pasteButton.setEnabled(false);
    -    }
    -    else {
    -      // Clipboard is not empty, so enable paste
    -      pasteButton.setEnabled(true);
    -    }
    -
    -    // Paste Defaults button is enabled whenever a row is selected    
    -    pasteDefaultsButton.setEnabled(true);
    -  }
    -  
    -
    -  /**
    -   * Pastes the clipboard values into the specified row.
    -   * 
    -   * @param rowIndex      the index of the row that is being pasted to
    -   */
    -  void pasteRow(int rowIndex) {
    -    tableModel.setValueAt(clipboardScope,        rowIndex, 1);
    -    tableModel.setValueAt(clipboardIdentifier,   rowIndex, 2);
    -    tableModel.setValueAt(clipboardRevision,     rowIndex, 3);
    -    tableModel.setValueAt(clipboardDocumentType, rowIndex, 4);
    -    tableModel.setValueAt(clipboardDocumentURL,  rowIndex, 5);
    -  }
    -  
    -
    -  /**
    -   * Pastes the default values into the specified row.
    -   * 
    -   * @param rowIndex      the index of the row that is being pasted to
    -   */
    -  void pasteDefaultValues(int rowIndex) {
    -    tableModel.setValueAt(defaultScope,        rowIndex, 1);
    -    tableModel.setValueAt(defaultIdentifier,   rowIndex, 2);
    -    tableModel.setValueAt(defaultRevision,     rowIndex, 3);
    -    tableModel.setValueAt(defaultDocumentType, rowIndex, 4);
    -    tableModel.setValueAt(defaultDocumentURL,  rowIndex, 5);
    -  }
    -  
    -
    -  /**
    -   * Dialog to determine whether user wants to save changes before proceeding.
    -   * 
    -   * @return   integer value that determines whether the user responded with
    -   *           "Yes", "No", or "Cancel"
    -   */
    -  int saveChangesDialog () {
    -    Object[] options = {"Yes", "No", "Cancel"};
    -    int value;
    -    
    -    value = JOptionPane.showOptionDialog(null,
    -                                         "Save Changes?",
    -                                         "Warning",
    -                                         JOptionPane.DEFAULT_OPTION,
    -                                         JOptionPane.WARNING_MESSAGE,
    -                                         null,
    -                                         options,
    -                                         options[0]); // default option
    -    return value;
    -  }
    -  
    -
    -  /**
    -   * Writes the contents of the table to file as XML.
    -   * 
    -   * @param harvestList       the File object to write to
    -   */
    -  void writeFile(File harvestList) {
    -    try {
    -      PrintWriter out = new PrintWriter(new FileWriter(harvestList));
    -      writeHarvestList(out);
    -    }
    -    catch (IOException ioe) {
    -      System.out.println("IOException: " + ioe.getMessage());
    -    }
    -  }
    -  
    -
    -  /**
    -   * Writes the contents of the table to a PrintWriter.
    -   * 
    -   * @param out       the PrintWriter to write the Harvest List to
    -   */
    -  void writeHarvestList(PrintWriter out) {
    -    out.println("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>");
    -    out.println("");
    -    out.println(
    -       "<hrv:harvestList xmlns:hrv=\"eml://ecoinformatics.org/harvestList\" >");
    -
    -    for (int i = 0; i < numRows; i++) {
    -      if (!isEmptyRow(i)) {
    -        writeRow(out, i);
    -      }
    -    }
    -
    -    out.println("");
    -    out.println("</hrv:harvestList>");
    -    out.close();
    -  }
    -  
    -
    -  /**
    -   * Writes a row of the table to file. A row corresponds to a single
    -   * <Document> element in the Harvest List.
    -   * 
    -   * @param out       the PrintWriter object for the file
    -   * @param rowIndex  the index of the table row that is being written to file
    -   */
    -  void writeRow(PrintWriter out, int rowIndex) {
    -    int indentLevel = 6;
    -    String scope = (String) tableModel.getValueAt(rowIndex, 1);
    -    String identifier = (String) tableModel.getValueAt(rowIndex, 2);
    -    String revision = (String) tableModel.getValueAt(rowIndex, 3);
    -    String documentType = (String) tableModel.getValueAt(rowIndex, 4);    
    -    String documentURL = (String) tableModel.getValueAt(rowIndex, 5);
    -
    -    out.println("");
    -    out.println("  <document>");
    -    out.println("    <docid>");
    -    out.println(composeLine(indentLevel, "scope", scope));
    -    out.println(composeLine(indentLevel, "identifier", identifier));
    -    out.println(composeLine(indentLevel, "revision", revision));
    -    out.println("    </docid>");
    -    indentLevel = 4;
    -    out.println(composeLine(indentLevel, "documentType", documentType));
    -    out.println(composeLine(indentLevel, "documentURL", documentURL));
    -    out.println("  </document>");
    -  }
    -  
    -
    -  /*
    -   * Inner class: HarvestListTableModel
    -   */
    -    class HarvestListTableModel extends AbstractTableModel {
    -      final boolean DEBUG = false;
    -      // Column names for the JTable  
    -      private String[] columnNames = {
    -                          "Row #",
    -                          "Scope",
    -                          "Identifier",
    -                          "Revision",
    -                          "Document Type",
    -                          "Document URL"
    -                         };
    -
    -      private Object[][] data = new Object[numRows][numColumns];
    -
    -        public int getColumnCount() {
    -            return columnNames.length;
    -        }
    -
    -        public int getRowCount() {
    -            return data.length;
    -        }
    -
    -        public String getColumnName(int col) {
    -            return columnNames[col];
    -        }
    -
    -        public Object getValueAt(int row, int col) {
    -            return data[row][col];
    -        }
    -
    -        /*
    -         * JTable uses this method to determine the default renderer/
    -         * editor for each cell.  If we didn't implement this method,
    -         * then the last column would contain text ("true"/"false"),
    -         * rather than a check box.
    -         */
    -        public Class getColumnClass(int c) {
    -            return getValueAt(0, c).getClass();
    -        }
    -
    -        /*
    -         * Don't need to implement this method unless your table's
    -         * editable.
    -         */
    -        public boolean isCellEditable(int row, int col) {
    -            //Note that the data/cell address is constant,
    -            //no matter where the cell appears onscreen.
    -            if (col < 1) {
    -                return false;
    -            } else {
    -                return true;
    -            }
    -        }
    -
    -        /*
    -         * Don't need to implement this method unless your table's
    -         * data can change.
    -         */
    -        public void setValueAt(Object value, int row, int col) {
    -            if (DEBUG) {
    -                System.out.println("Setting value at " + row + "," + col
    -                                   + " to " + value
    -                                   + " (an instance of "
    -                                   + value.getClass() + ")");
    -            }
    -
    -            data[row][col] = value;
    -            fireTableCellUpdated(row, col);
    -
    -            if (DEBUG) {
    -                System.out.println("New value of data:");
    -                printDebugData();
    -            }
    -        }
    -
    -        private void printDebugData() {
    -            int numRows = getRowCount();
    -            int numCols = getColumnCount();
    -
    -            for (int i=0; i < numRows; i++) {
    -                System.out.print("    row " + i + ":");
    -                for (int j=0; j < numCols; j++) {
    -                    System.out.print("  " + data[i][j]);
    -                }
    -                System.out.println();
    -            }
    -            System.out.println("--------------------------");
    -        }
    -    }
    -
    -  /**
    -   * This inner class extends DefaultHandler. It parses the Harvest List file,
    -   * writing a new row to the table every time it encounters a </Document>
    -   * end tag.
    -   */
    -  class HarvestListHandler extends DefaultHandler implements ErrorHandler {
    -  
    -    public String scope;
    -    public int identifier;
    -    public String identifierString;
    -    public String documentType;
    -    private HarvestListEditor harvestListEditor;
    -    boolean loadHarvestList;
    -    public int revision;
    -    public String revisionString;
    -    private int rowIndex = 0;
    -    public String documentURL;
    -    private String currentQname;
    -    public final static String DEFAULT_PARSER = 
    -           "org.apache.xerces.parsers.SAXParser";
    -    private boolean schemaValidate = true;
    -    private boolean validateHarvestList;
    -	
    -
    -	  /**
    -     * This method is called for any plain text within an element.
    -     * It parses the value for any of the following elements:
    -     * <scope>, <identifier>, <revision>, <documentType>, <documentURL>
    -     * 
    -     * @param ch          the character array holding the parsed text
    -     * @param start       the start index
    -     * @param length      the text length
    -     * 
    -     */
    -    public void characters (char ch[], int start, int length) {
    -      String s = new String(ch, start, length);
    - 
    -      if (length > 0) {           
    -        if (currentQname.equals("scope")) {
    -          scope += s;
    -        }
    -        else if (currentQname.equals("identifier")) {
    -          identifierString += s;
    -        }
    -        else if (currentQname.equals("revision")) {
    -          revisionString += s;
    -        }
    -        else if (currentQname.equals("documentType")) {
    -          documentType += s;
    -        }
    -        else if (currentQname.equals("documentURL")) {
    -          documentURL += s;
    -        }
    -      }
    -    }
    -
    -
    -    /** 
    -     * Handles an end-of-document event.
    -     */
    -    public void endDocument () {
    -    }
    -
    -
    -    /** 
    -     * Handles an end-of-element event. If the end tag is </Document>, then
    -     * creates a new HarvestDocument object and pushes it to the document
    -     * list.
    -     * 
    -     * @param uri
    -     * @param localname
    -     * @param qname
    -     */
    -    public void endElement(String uri, 
    -                           String localname,
    -                           String qname) {
    -      
    -      HarvestDocument harvestDocument;
    -      
    -      if (qname.equals("identifier")) {
    -        identifier = Integer.parseInt(identifierString);
    -      }
    -      else if (qname.equals("revision")) {
    -        revision = Integer.parseInt(revisionString);
    -      }
    -      else if (qname.equals("document")) {
    -        if (loadHarvestList) {
    -          harvestListEditor.addRow(rowIndex, scope, identifierString, 
    -                                   revisionString, documentType, documentURL);
    -        }
    -
    -        rowIndex++;
    -      }
    -
    -      currentQname = "";
    -    }
    -
    -
    -    /**
    -     * Method for handling errors during a parse
    -     *
    -     * @param exception         The parsing error
    -     * @exception SAXException  Description of Exception
    -     */
    -     public void error(SAXParseException e) throws SAXParseException {
    -        System.out.println("SAXParseException: " + e.getMessage());
    -        throw e;
    -    }
    -
    -
    -    /**
    -     * Run the validating parser
    -     *
    -     * @param xml             the xml stream to be validated
    -     * @schemaLocation        relative path the to XML Schema file, e.g. "."
    -     * @exception IOException thrown when test files can't be opened
    -     * @exception ClassNotFoundException thrown when SAX Parser class not found
    -     * @exception SAXException
    -     * @exception SAXParserException
    -     */
    -    public void runParser(HarvestListEditor harvestListEditor,
    -                          Reader xml, 
    -                          String schemaLocation,
    -                          boolean loadHarvestList,
    -                          boolean validateHarvestList)
    -           throws IOException, ClassNotFoundException,
    -                  SAXException, SAXParseException {
    -
    -      // Get an instance of the parser
    -      XMLReader parser;
    -      
    -      this.harvestListEditor = harvestListEditor;
    -      this.loadHarvestList = loadHarvestList;
    -      this.validateHarvestList = validateHarvestList;
    -      this.rowIndex = 0;
    -
    -      parser = XMLReaderFactory.createXMLReader(DEFAULT_PARSER);
    -      // Set Handlers in the parser
    -      parser.setContentHandler((ContentHandler)this);
    -      parser.setErrorHandler((ErrorHandler)this);
    -      parser.setFeature("http://xml.org/sax/features/namespaces", true);
    -      parser.setFeature("http://xml.org/sax/features/namespace-prefixes", true);
    -      parser.setFeature("http://xml.org/sax/features/validation", true);
    -      parser.setProperty(
    -              "http://apache.org/xml/properties/schema/external-schemaLocation", 
    -              schemaLocation);
    -
    -      if (schemaValidate) {
    -        parser.setFeature("http://apache.org/xml/features/validation/schema", 
    -                          true);
    -      }
    -    
    -      // Parse the document
    -      parser.parse(new InputSource(xml));
    -    }
    -
    -
    -    /**
    -     * Handles a start-of-document event.
    -     */
    -    public void startDocument () {
    -      //System.out.println("Started parsing Harvest List");
    -    }
    -
    -
    -    /** 
    -     * Handles a start-of-element event.
    -     * 
    -     * @param uri
    -     * @param localname
    -     * @param qname
    -     * @param attributes
    -     */
    -    public void startElement(String uri, 
    -                             String localname,
    -                             String qname,
    -                             Attributes attributes) {
    -      
    -      currentQname = qname;
    -
    -      if (qname.equals("scope")) {
    -        scope = "";
    -      }
    -      else if (qname.equals("identifier")) {
    -        identifierString = "";
    -      }
    -      else if (qname.equals("revision")) {
    -        revisionString = "";
    -      }
    -      else if (qname.equals("documentType")) {
    -        documentType = "";
    -      }
    -      else if (qname.equals("documentURL")) {
    -        documentURL = "";
    -      }
    -    }
    -  }
    -}
    \ No newline at end of file
    
  • src/edu/ucsb/nceas/metacat/harvesterClient/HarvestLog.java+0 368 removed
    @@ -1,368 +0,0 @@
    -/**
    - *  '$RCSfile$'
    - *  Copyright: 2004 University of New Mexico and the 
    - *                  Regents of the University of California
    - *
    - *   '$Author$'
    - *     '$Date$'
    - * '$Revision$'
    - *
    - * This program is free software; you can redistribute it and/or modify
    - * it under the terms of the GNU General Public License as published by
    - * the Free Software Foundation; either version 2 of the License, or
    - * (at your option) any later version.
    - *
    - * This program is distributed in the hope that it will be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write to the Free Software
    - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    - */
    -
    -package edu.ucsb.nceas.metacat.harvesterClient;
    -
    -import java.io.PrintStream;
    -import java.sql.Connection;
    -import java.sql.ResultSet;
    -import java.sql.SQLException;
    -import java.sql.SQLWarning;
    -import java.sql.Statement;
    -import java.text.SimpleDateFormat;
    -import java.util.Date;
    -import java.util.StringTokenizer;
    -
    -import edu.ucsb.nceas.metacat.properties.PropertyService;
    -import edu.ucsb.nceas.utilities.PropertyNotFoundException;
    -
    -/**
    - * Manages log entries to be inserted to the HARVEST_LOG table.
    - *
    - * @author  costa
    - */
    -public class HarvestLog {
    -
    -  private Connection conn;    
    -  private Harvester harvester;              // The parent Harvester object
    -  private int harvestLogID;
    -  private Date harvestDate;
    -  private int status;
    -  private final String marker =
    -"*****************************************************************************";
    -  private String message;
    -  private String harvestOperationCode;
    -  private int siteScheduleID;
    -  private String explanation;
    -  private String harvestOperationCodeLevel;
    -  private String timestamp;
    -  private HarvestDetailLog harvestDetailLog;  // Associated detail log, if any
    -    
    -
    -  /** 
    -   * Creates a new instance of HarvestLog. This constructor is used when
    -   * creating log entries that do not involve an error on a harvest document.
    -   * (For that type of log entry, use the alternate constructor below.)
    -   *
    -   * @param  harvester       the parent Harvester object
    -   * @param  conn            the database connection
    -   * @param  harvestLogID    the primary key in the HARVEST_LOG table
    -   * @param  harvestDate     the date of this harvest
    -   * @param  status          the status of the harvest operation
    -   * @param  message         the message text of the harvest operation
    -   * @param  harvestOperationCode  the harvest operation code
    -   * @param  siteScheduleID  the siteScheduleID for which this operation was
    -   *                         performed. 0 indicates that the operation did not
    -   *                         involve a particular harvest site.
    -   */
    -  public HarvestLog(Harvester  harvester,
    -                    Connection conn,
    -                    int        harvestLogID,
    -                    Date       harvestDate,
    -                    int        status,
    -                    String     message, 
    -                    String     harvestOperationCode,
    -                    int        siteScheduleID
    -                   ) {
    -    Date now = new Date();
    -    timestamp = now.toString();
    -
    -    this.harvester = harvester;
    -    this.conn = conn;
    -    this.harvestLogID = harvestLogID;
    -    this.harvestDate = harvestDate;
    -    this.status = status;
    -    this.message = message;
    -    this.harvestOperationCode = harvestOperationCode;
    -    this.siteScheduleID = siteScheduleID;
    -    
    -    harvestOperationCodeLevel = 
    -            getHarvestOperationCodeLevel(harvestOperationCode);
    -    explanation = getExplanation(harvestOperationCode);
    -    dbInsertHarvestLogEntry();   // Insert this entry to the HARVEST_LOG table
    -  }
    -    
    -
    -  /** 
    -   * Creates a new instance of HarvestLog and inserts this entry to the
    -   * HARVEST_LOG table. This version of the constructor also instantiates a 
    -   * HarvestDetailLog object and inserts it to the HARVEST_DETAIL_LOG table.
    -   *
    -   * @param  harvester       the parent Harvester object
    -   * @param  conn            the database connection
    -   * @param  harvestLogID    the primary key in the HARVEST_LOG table
    -   * @param  detailLogID     the primary key in the HARVEST_DETAIL_LOG table
    -   * @param  harvestDate     the date of this harvest
    -   * @param  status          the status of the harvest operation
    -   * @param  message         the message text of the harvest operation
    -   * @param  harvestOperationCode  the harvest operation code
    -   * @param  siteScheduleID  the siteScheduleID for which this operation was
    -   *                         performed. 0 indicates that the operation did not
    -   *                         involve a particular harvest site.
    -   * @param  harvestDocument the HarvestDocument involved in this operation
    -   * @param  errorMessage    the error message generated by this operation
    -   */
    -  public HarvestLog(Harvester  harvester,
    -                    Connection conn,
    -                    int        harvestLogID,
    -                    int        detailLogID,
    -                    Date       harvestDate,
    -                    int        status,
    -                    String     message, 
    -                    String     harvestOperationCode,
    -                    int        siteScheduleID,
    -                    HarvestDocument harvestDocument,
    -                    String     errorMessage
    -                   ) {
    -    Date now = new Date();
    -    timestamp = now.toString();
    -
    -    this.harvester = harvester;
    -    this.conn = conn;
    -    this.harvestLogID = harvestLogID;
    -    this.harvestDate = harvestDate;
    -    this.status = status;
    -    this.message = message;
    -    this.harvestOperationCode = harvestOperationCode;
    -    this.siteScheduleID = siteScheduleID;
    -    this.harvestDetailLog = new HarvestDetailLog(harvester, conn, detailLogID,
    -                                                 harvestLogID, harvestDocument,
    -                                                 errorMessage);
    -    harvestOperationCodeLevel = 
    -            getHarvestOperationCodeLevel(harvestOperationCode);
    -    explanation = getExplanation(harvestOperationCode);
    -    dbInsertHarvestLogEntry();               // Insert to the HARVEST_LOG table
    -    harvestDetailLog.dbInsertHarvestDetailLogEntry(); //  HARVEST_DETAIL_LOG
    -  }
    -    
    -
    -  /**
    -   * Inserts a new entry into the HARVEST_LOG table, based on the contents of
    -   * this HarvestLog object. Not yet implemented.
    -   */
    -  void dbInsertHarvestLogEntry() {
    -    String dequotedMessage = harvester.dequoteText(message);
    -    String insertString;
    -    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd-MMM-yyyy");
    -    Statement stmt;
    -
    -    insertString = "INSERT INTO HARVEST_LOG " +
    -                   "(HARVEST_LOG_ID, HARVEST_DATE, STATUS, MESSAGE," +
    -                   " HARVEST_OPERATION_CODE, SITE_SCHEDULE_ID) " +
    -                   "values(" +
    -                   harvestLogID + ", " +
    -                   "'" + simpleDateFormat.format(harvestDate) + "', " +
    -                   status + ", " +
    -                   "'" + timestamp + ": " + dequotedMessage + "', " +
    -                   "'" + harvestOperationCode + "', " +
    -                   siteScheduleID +
    -                   ")";
    -    try {
    -      stmt = conn.createStatement();
    -      stmt.executeUpdate(insertString);
    -      stmt.close();
    -    }
    -    catch(SQLException e) {
    -      System.out.println("SQLException: " + e.getMessage());
    -    }
    -  }
    -  
    -
    -  /**
    -   * Maps each code level to an integer value.
    -   * 
    -   * @param codeLevel        the code level: "error", "warning", "notice",
    -   *                         "info", or "debug"
    -   * @return codeLevelValue  the corresponding code level value
    -   */
    -  public int getCodeLevelValue(String codeLevel) {
    -    int codeLevelValue = 0;
    -    
    -    if (codeLevel.equalsIgnoreCase("error")) {
    -      codeLevelValue = 1;
    -    }
    -    else if (codeLevel.equalsIgnoreCase("warning")) {
    -      codeLevelValue = 2;
    -    }
    -    else if (codeLevel.equalsIgnoreCase("notice")) {
    -      codeLevelValue = 3;
    -    }
    -    else if (codeLevel.equalsIgnoreCase("info")) {
    -      codeLevelValue = 4;
    -    }
    -    else if (codeLevel.equalsIgnoreCase("debug")) {
    -      codeLevelValue = 5;
    -    }
    -    
    -    return codeLevelValue;
    -  }
    -  
    -
    -  /**
    -   * Returns an explanation string based on the value of a
    -   * harvestOperationCode string. The explanation string is a description
    -   * of the harvest operation specified by the harvestOperationCode.
    -   * 
    -   * @param  harvestOperationCode  string value of the harvest operation code
    -   * @return the explanation for this harvest operation, a String
    -   */
    -  public String getExplanation(String harvestOperationCode) {
    -    String explanation;
    -    String fieldName = "EXPLANATION";
    -    
    -    explanation = getHarvestOperation(fieldName, harvestOperationCode);
    -        
    -    return explanation;
    -  }
    -  
    -
    -  /**
    -   * Returns either an explanation string or a harvest operation code level 
    -   * string based on the value of a harvest operation code property. The
    -   * explanation and the code level are stored as comma-separated strings in
    -   * the metacat.properties file. For example, the HarvesterStartup
    -   * harvest operation code stores its explanation and code level like so:
    -   * 
    -   *            HarvesterStartup=Harvester start up,Info
    -   *
    -   * @param  fieldName  the field name to match, e.g. "EXPLANATION"
    -   * @param  harvestOperationCode  string value of the harvest operation code
    -   * @return the explanation string or the harvestOperationCodeLevel string
    -   */
    -  String getHarvestOperation(String fieldName, String harvestOperationCode) {
    -    String explanation = "No explanation available";
    -    String harvestOperationCodeLevel = "debug";
    -    String propertyValue = null;
    -    String returnString = "";
    -    StringTokenizer stringTokenizer;
    -    
    -    try {
    -		propertyValue = PropertyService.getProperty(harvestOperationCode);
    -	} catch (PropertyNotFoundException pnfe) {
    -		System.out.println("Error trying to get property: " + harvestOperationCode
    -					+ " : " + pnfe.getMessage());
    -	}
    -	stringTokenizer = new StringTokenizer(propertyValue, ",");
    -    
    -    explanation = (String) stringTokenizer.nextElement();
    -    harvestOperationCodeLevel = (String) stringTokenizer.nextElement();
    -                                           
    -    if (fieldName.equals("EXPLANATION")) {
    -      returnString = explanation;
    -    }
    -    else if (fieldName.equals("HARVEST_OPERATION_CODE_LEVEL")) {
    -      returnString = harvestOperationCodeLevel;
    -    }
    -    
    -    return returnString;
    -  }
    -  
    -
    -  /**
    -   * Returns a code level string based on a harvestOperationCode string.
    -   * The code level string is one of a set of possible code levels:
    -   * "error", "warning", "notice", "info", or "debug".
    -   * 
    -   * @param  harvestOperationCode  string value of the harvest operation code
    -   * @return the code level value, a String, one of the following:
    -   *         "error", "warning", "notice", "info", or "debug"
    -   */
    -  public String getHarvestOperationCodeLevel(String harvestOperationCode) {
    -    String harvestOperationCodeLevel;
    -    String fieldName = "HARVEST_OPERATION_CODE_LEVEL";
    -    
    -    harvestOperationCodeLevel = 
    -            getHarvestOperation(fieldName, harvestOperationCode);
    -        
    -    return harvestOperationCodeLevel;
    -  }
    -  
    -
    -  /**
    -   * Access function for the siteScheduleID field.
    -   * 
    -   * @return  siteScheduleID, an int. If 0, indicates that this log entry does
    -   *          not pertain to a particular site.
    -   */
    -  int getSiteScheduleID() {
    -    return siteScheduleID;
    -  }
    -  
    -
    -  /**
    -   * Determines whether this log entry had an error status.
    -   * 
    -   * @return  isError  true if this log entry had an error status, else false 
    -   */
    -  boolean isErrorEntry () {
    -    boolean isError;
    -    
    -    isError = (status != 0);
    -    
    -    return isError;
    -  }
    -
    -
    -  /**
    -   * Prints the contents of this HarvestLog object. Used in generating reports.
    -   * 
    -   * @param out        the PrintStream to write to
    -   * @param maxLevel  the maximum code level to output. If this log entry has a
    -   *                  higher code level than the maxLevel, no output
    -   *                  is issued. For example, if the maxLevel is "error"
    -   *                  (level 1), then anything lower ("warning", "notice", etc.)
    -   *                  will not generate any output.
    -   */
    -  public void printOutput(PrintStream out, String maxLevel) {
    -    int codeLevelValue = getCodeLevelValue(harvestOperationCodeLevel);
    -    int maxLevelValue = getCodeLevelValue(maxLevel);
    -    
    -    if (codeLevelValue <= maxLevelValue) {    
    -      out.println("");
    -      out.println(marker);
    -      out.println("*");
    -      out.println("* harvestLogID:         " + harvestLogID);
    -      out.println("* harvestDate:          " + harvestDate);
    -      out.println("* status:               " + status);
    -      out.println("* message:              " + message);
    -      out.println("* harvestOperationCode: " + harvestOperationCode);
    -      out.println("* description:          " + explanation);
    -
    -      if (harvestOperationCode.equals("harvester.GetHarvestListSuccess") ||
    -        harvestOperationCode.equals("harvester.GetHarvestListError")) {
    -        if (siteScheduleID != 0) {
    -          harvester.printHarvestSiteSchedule(out, siteScheduleID);
    -        }
    -      }
    -    
    -      if (harvestDetailLog != null) {
    -        harvestDetailLog.printOutput(out);
    -      }
    -
    -      out.println("*");
    -      out.println(marker);
    -    }
    -  }
    -
    -}
    
  • src/edu/ucsb/nceas/metacat/harvesterClient/HarvestSiteSchedule.java+0 814 removed
    @@ -1,814 +0,0 @@
    -/**
    - *  '$RCSfile$'
    - *  Copyright: 2004 University of New Mexico and the 
    - *                  Regents of the University of California
    - *
    - *   '$Author$'
    - *     '$Date$'
    - * '$Revision$'
    - *
    - * This program is free software; you can redistribute it and/or modify
    - * it under the terms of the GNU General Public License as published by
    - * the Free Software Foundation; either version 2 of the License, or
    - * (at your option) any later version.
    - *
    - * This program is distributed in the hope that it will be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write to the Free Software
    - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    - */
    -
    -package edu.ucsb.nceas.metacat.harvesterClient;
    -
    -import com.oreilly.servlet.MailMessage;
    -import java.io.FileNotFoundException;
    -import java.io.IOException;
    -import java.io.InputStream;
    -import java.io.InputStreamReader;
    -import java.io.PrintStream;
    -import java.io.Reader;
    -import java.net.MalformedURLException;
    -import java.net.URL;
    -import java.sql.Connection;
    -import java.sql.SQLException;
    -import java.sql.Statement;
    -import java.text.DateFormat;
    -import java.text.ParseException;
    -import java.text.SimpleDateFormat;
    -import java.util.ArrayList;
    -import java.util.Date;
    -import javax.xml.parsers.ParserConfigurationException;
    -import org.xml.sax.Attributes;
    -import org.xml.sax.ContentHandler;
    -import org.xml.sax.ErrorHandler;
    -import org.xml.sax.InputSource;
    -import org.xml.sax.SAXException;
    -import org.xml.sax.SAXParseException;
    -import org.xml.sax.XMLReader;
    -import org.xml.sax.helpers.DefaultHandler;
    -import org.xml.sax.helpers.XMLReaderFactory;
    -
    -import edu.ucsb.nceas.metacat.client.Metacat;
    -import edu.ucsb.nceas.metacat.client.MetacatException;
    -import edu.ucsb.nceas.metacat.client.MetacatInaccessibleException;
    -
    -
    -/**
    - * HarvestSiteSchedule manages a single entry in the HARVEST_SITE_SCHEDULE
    - * table, determining when and how to harvest the documents for a given site.
    - * 
    - * @author  costa
    - */
    -public class HarvestSiteSchedule {
    -    
    -  private String contactEmail;
    -  private String dateLastHarvest;
    -  private String dateNextHarvest;
    -  private long delta;
    -  private String documentListURL;
    -  private Harvester harvester;
    -  private ArrayList harvestDocumentList = new ArrayList();
    -  private String harvestSiteEndTime;
    -  private String harvestSiteStartTime;
    -  private String ldapDN;
    -  private String ldapPwd;
    -  final private long millisecondsPerDay = (1000 * 60 * 60 * 24);
    -  private String schemaLocation = 
    -    "eml://ecoinformatics.org/harvestList ../../lib/harvester/harvestList.xsd";
    -  int siteScheduleID;
    -  private String unit;
    -  private int updateFrequency;
    -    
    -  /**
    -   * Creates a new instance of HarvestSiteSchedule. Initialized with the data
    -   * that was read from a single row in the HARVEST_SITE_SCHEDULE table.
    -   * 
    -   * @param harvester       the parent Harvester object
    -   * @param siteScheduleID  the value of the SITE_SCHEDULE_ID field
    -   * @param documentListURL the value of the DOCUMENTLISTURL field
    -   * @param ldapDN          the value of the LDAPDN field
    -   * @param ldapPwd    the value of the LDAPPASSWORD field
    -   * @param dateNextHarvest the value of the DATENEXTHARVEST field
    -   * @param dateLastHarvest the value of the DATELASTHARVEST field
    -   * @param updateFrequency the value of the UPDATEFREQUENCY field
    -   * @param unit            the value of the UNIT field
    -   * @param contactEmail    the value of the CONTACT_EMAIL field
    -   */
    -  public HarvestSiteSchedule(
    -                              Harvester harvester,
    -                              int    siteScheduleID,
    -                              String documentListURL,
    -                              String ldapDN,
    -                              String ldapPwd,
    -                              String dateNextHarvest,
    -                              String dateLastHarvest,
    -                              int    updateFrequency,
    -                              String unit,
    -                              String contactEmail
    -                            )
    -  {
    -    this.harvester = harvester;
    -    this.siteScheduleID = siteScheduleID;
    -    this.documentListURL = documentListURL;
    -    this.ldapDN = ldapDN;
    -    this.ldapPwd = ldapPwd;
    -    this.dateNextHarvest = dateNextHarvest;
    -    this.dateLastHarvest = dateLastHarvest;
    -    this.updateFrequency = updateFrequency;
    -    this.unit = unit;
    -    this.contactEmail = contactEmail;
    -    
    -    // Calculate the value of delta, the number of milliseconds between the
    -    // last harvest date and the next harvest date.
    -    delta = updateFrequency * millisecondsPerDay;
    -    
    -    if (unit.equals("weeks")) {
    -      delta *= 7;
    -    }
    -    else if (unit.equals("months")) {
    -      delta *= 30;
    -    }
    -  }
    -  
    -  
    -  /**
    -   * Updates the DATELASTHARVEST and DATENEXTHARVEST values of the 
    -   * HARVEST_SITE_SCHEDULE table after a harvest operation has completed.
    -   * Calculates the date of the next harvest based on today's date and the 
    -   * update frequency.
    -   */
    -  private void dbUpdateHarvestDates() {
    -    Connection conn;
    -    long currentTime;                    // Current time in milliseconds
    -    Date dateNextHarvest;                // Date of next harvest
    -    String lastHarvest;
    -    String nextHarvest;
    -    Date now = new Date();
    -    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd-MMM-yyyy");
    -    Statement stmt;
    -    long timeNextHarvest;
    -    
    -    conn = harvester.getConnection();
    -    now = new Date();
    -    currentTime = now.getTime();
    -    timeNextHarvest = currentTime + delta;
    -    dateNextHarvest = new Date(timeNextHarvest);
    -    nextHarvest = "'" + simpleDateFormat.format(dateNextHarvest) + "'";
    -    lastHarvest = "'" + simpleDateFormat.format(now) + "'";
    -	
    -	try {
    -      stmt = conn.createStatement();
    -      stmt.executeUpdate(
    -                         "UPDATE HARVEST_SITE_SCHEDULE SET DATENEXTHARVEST = " +
    -                         nextHarvest +
    -                         " WHERE SITE_SCHEDULE_ID = " +
    -                         siteScheduleID);
    -      stmt.executeUpdate(
    -                         "UPDATE HARVEST_SITE_SCHEDULE SET DATELASTHARVEST = " +
    -                         lastHarvest +
    -                         " WHERE SITE_SCHEDULE_ID = " +
    -                         siteScheduleID);
    -      stmt.close();
    -    }
    -    catch(SQLException e) {
    -      System.out.println("SQLException: " + e.getMessage());
    -    }
    -  }
    -    
    -
    -  /**
    -   * Boolean to determine whether this site is currently due for its next
    -   * harvest.
    -   * 
    -   * @retrun     true if due for harvest, otherwise false
    -   */
    -  public boolean dueForHarvest() {
    -    boolean dueForHarvest = false;
    -//    DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S");
    -    DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
    -    Date now = new Date();
    -    Date dnh;                          // Date of next harvest
    -    long currentTime = now.getTime();  // Current time in milliseconds
    -    long timeNextHarvest = 0;
    -    
    -    try {
    -      dnh = dateFormat.parse(dateNextHarvest);
    -      timeNextHarvest = dnh.getTime();
    -      
    -      if (timeNextHarvest < currentTime) {
    -        dueForHarvest = true;
    -        System.out.println("Due for harvest: " + documentListURL);
    -      }
    -      else {
    -        System.out.println("Not due for harvest: " + documentListURL);
    -      }
    -    }
    -    catch (ParseException e) {
    -      System.out.println("Error parsing date: " + e.getMessage());
    -    }
    -    
    -    return dueForHarvest;
    -  }
    -  
    -
    -  /**
    -   * Accessor method for the schemaLocation field.
    -   * 
    -   * @return schemaLocation  the schema location string
    -   */
    -  public String getSchemaLocation() {
    -    return schemaLocation;
    -  }
    -
    -
    -  /**
    -   * Harvests each document in the site document list.
    -   * 
    -   * @throws SAXException
    -   * @throws IOException
    -   * @throws ParserConfigurationException
    -   */
    -  public void harvestDocumentList() {
    -    HarvestDocument harvestDocument;
    -    boolean success;
    -    
    -    if (dueForHarvest()) {
    -      try {
    -        success = parseHarvestList();
    -
    -        /* If the document list was validated, then proceed with harvesting
    -         * the documents
    -         */
    -        if (success) {
    -          metacatLogin();
    -        
    -          for (int i = 0; i < harvestDocumentList.size(); i++) {
    -            harvestDocument = (HarvestDocument) harvestDocumentList.get(i);
    -          
    -            if (harvestDocument != null) {
    -              harvestDocument.harvestDocument();
    -            }
    -          }
    -
    -          metacatLogout();      
    -          dbUpdateHarvestDates();  // Update the schedule
    -        }
    -      }
    -      catch (ParserConfigurationException e) {
    -        System.out.println("ParserConfigurationException: " + e.getMessage());
    -      }
    -      
    -      reportToSiteContact();
    -    }
    -  }
    -
    -
    -  /**
    -   * Login to Metacat using the ldapDN and ldapPwd
    -   */
    -  public void metacatLogin() {
    -    Metacat metacat = harvester.metacat;
    -    String response;
    -
    -    if (harvester.connectToMetacat()) {
    -      try {
    -        System.out.println("Logging in to Metacat: " + ldapDN);
    -        response = metacat.login(ldapDN, ldapPwd);
    -        //System.out.println("Metacat login response: " + response);
    -      } 
    -      catch (MetacatInaccessibleException e) {
    -        System.out.println("Metacat login failed." + e.getMessage());
    -      } 
    -      catch (Exception e) {
    -        System.out.println("Metacat login failed." + e.getMessage());
    -      }
    -    }    
    -  }
    -  
    -  
    -  /**
    -   * Logout from Metacat
    -   */
    -  private void metacatLogout() {
    -    Metacat metacat = harvester.metacat;
    -
    -    if (harvester.connectToMetacat()) {
    -      try {    
    -        // Log out from the Metacat session
    -        System.out.println("Logging out from Metacat");
    -        metacat.logout();
    -      }
    -      catch (MetacatInaccessibleException e) {
    -        System.out.println("Metacat inaccessible: " + e.getMessage());
    -      }
    -      catch (MetacatException e) {
    -        System.out.println("Metacat exception: " + e.getMessage());
    -      }
    -    }
    -  }
    -  
    -
    -  /**
    -   * Parses the site harvest list XML file to find out which documents to 
    -   * harvest.
    -   * 
    -   * @return  true if successful, otherwise false
    -   */
    -  public boolean parseHarvestList() 
    -          throws ParserConfigurationException {
    -    DocumentListHandler documentListHandler = new DocumentListHandler();
    -    InputStream inputStream;
    -    InputStreamReader inputStreamReader;
    -    String schemaLocation = getSchemaLocation();
    -    boolean success = false;
    -    URL url;
    -
    -    try {
    -      url = new URL(documentListURL);
    -      inputStream = url.openStream();
    -      harvester.addLogEntry(0,
    -                            "Retrieved: " + documentListURL,
    -                            "harvester.GetHarvestListSuccess",
    -                            siteScheduleID,
    -                            null,
    -                            "");
    -      inputStreamReader = new InputStreamReader(inputStream);
    -//      char[] harvestListChars = new char[1024];
    -//      inputStreamReader.read(harvestListChars, 0, 1024);
    -//      System.out.println("documentListURL: " + documentListURL);
    -//      String encoding = inputStreamReader.getEncoding();
    -//      System.out.println("encoding: " + encoding);
    -//      String harvestListStr = new String(harvestListChars);
    -//      System.out.println("harvestListStr:\n" + harvestListStr);
    -      documentListHandler.runParser(inputStreamReader, schemaLocation);
    -      harvester.addLogEntry(0,
    -                            "Validated: " + documentListURL,
    -                            "harvester.ValidateHarvestListSuccess",
    -                            siteScheduleID,
    -                            null,
    -                            "");
    -      success = true;
    -    }
    -    catch (MalformedURLException e){
    -      harvester.addLogEntry(1, "MalformedURLException: " + e.getMessage(), 
    -                            "harvester.GetHarvestListError", siteScheduleID, null, "");
    -    }
    -    catch (FileNotFoundException e) {
    -      harvester.addLogEntry(1, "FileNotFoundException: " + e.getMessage(), 
    -                            "harvester.GetHarvestListError", siteScheduleID, null, "");
    -    }
    -    catch (SAXException e) {
    -      harvester.addLogEntry(1, "SAXException: " + e.getMessage(), 
    -                          "harvester.ValidateHarvestListError", siteScheduleID, null, "");
    -    }
    -    catch (ClassNotFoundException e) {
    -      harvester.addLogEntry(1, "ClassNotFoundException: " + e.getMessage(),
    -                          "harvester.ValidateHarvestListError", siteScheduleID, null, "");
    -    }
    -    catch (IOException e) {
    -      harvester.addLogEntry(1, "IOException: " + e.getMessage(), 
    -                            "harvester.GetHarvestListError", siteScheduleID, null, "");
    -    }
    -    
    -    return success;
    -  }
    -
    -
    -  /**
    -   * Prints the data that is stored in this HarvestSiteSchedule object.
    -   * 
    -   * @param out   the PrintStream to write to
    -   */
    -  public void printOutput(PrintStream out) {
    -    out.println("* siteScheduleID:       " + siteScheduleID);
    -    out.println("* documentListURL:      " + documentListURL);
    -    out.println("* ldapDN:               " + ldapDN);
    -    out.println("* dateNextHarvest:      " + dateNextHarvest);
    -    out.println("* dateLastHarvest:      " + dateLastHarvest);
    -    out.println("* updateFrequency:      " + updateFrequency);
    -    out.println("* unit:                 " + unit);
    -    out.println("* contactEmail:         " + contactEmail);
    -  }
    -  
    -  /**
    -   * Reports a summary of the site harvest. Includes the following:
    -   *   A list of documents that were successfully inserted.
    -   *   A list of documents that were successfully updated.
    -   *   A list of documents that could not be accessed at the site.
    -   *   A list of documents that could not be uploaded to Metacat.
    -   *   A list of documents that were already found in Metacat.
    -   *   
    -   * @param out  the PrintStream to write to
    -   */
    -  void printSiteSummary(PrintStream out) {
    -    HarvestDocument harvestDocument;
    -    int nAccessError = 0;
    -    int nInserted = 0;
    -    int nMetacatHasIt = 0;
    -    int nUpdated = 0;
    -    int nUploadError = 0;
    -    
    -    for (int i = 0; i < harvestDocumentList.size(); i++) {
    -      harvestDocument = (HarvestDocument) harvestDocumentList.get(i);
    -          
    -      if (harvestDocument != null) {
    -        if (harvestDocument.accessError)  { nAccessError++; }
    -        if (harvestDocument.inserted)     { nInserted++; }
    -        if (harvestDocument.metacatHasIt) { nMetacatHasIt++; }
    -        if (harvestDocument.updated)      { nUpdated++; }
    -        if (harvestDocument.uploadError)  { nUploadError++; }
    -      }
    -    }
    -    
    -    if (nInserted > 0) {
    -      printSiteSummaryHeader(out);
    -      out.println("* The following document(s) were successfully inserted:");
    -      for (int i = 0; i < harvestDocumentList.size(); i++) {
    -        harvestDocument = (HarvestDocument) harvestDocumentList.get(i);          
    -        if (harvestDocument != null) {
    -          if (harvestDocument.inserted)  {
    -            harvestDocument.prettyPrint(out);
    -          }
    -        }
    -      }
    -      printSiteSummaryTrailer(out);
    -    }
    -
    -    if (nUpdated > 0) {
    -      printSiteSummaryHeader(out);
    -      out.println("* The following document(s) were successfully updated:");
    -      for (int i = 0; i < harvestDocumentList.size(); i++) {
    -        harvestDocument = (HarvestDocument) harvestDocumentList.get(i);          
    -        if (harvestDocument != null) {
    -          if (harvestDocument.updated)  {
    -            harvestDocument.prettyPrint(out);
    -          }
    -        }
    -      }
    -      printSiteSummaryTrailer(out);
    -    }
    -
    -    if (nAccessError > 0) {
    -      printSiteSummaryHeader(out);
    -      out.println("* The following document(s) could not be accessed");
    -      out.println("* at the site. Please check the URL to ensure that it is");
    -      out.println("* accessible at the site.");
    -      for (int i = 0; i < harvestDocumentList.size(); i++) {
    -        harvestDocument = (HarvestDocument) harvestDocumentList.get(i);
    -        if (harvestDocument != null) {
    -          if (harvestDocument.accessError)  {
    -            harvestDocument.prettyPrint(out);
    -          }
    -        }
    -      }
    -      printSiteSummaryTrailer(out);
    -    }
    -
    -    if (nUploadError > 0) {
    -      printSiteSummaryHeader(out);
    -      out.println("* The following document(s) could not be uploaded to");
    -      out.println("* Metacat because an error of some kind occurred.");
    -      out.println("* (See log entries below for additional details.) :");
    -      for (int i = 0; i < harvestDocumentList.size(); i++) {
    -        harvestDocument = (HarvestDocument) harvestDocumentList.get(i);          
    -        if (harvestDocument != null) {
    -          if (harvestDocument.uploadError)  {
    -            harvestDocument.prettyPrint(out);
    -          }
    -        }
    -      }
    -      printSiteSummaryTrailer(out);
    -    }
    -
    -    if (nMetacatHasIt > 0) {
    -      printSiteSummaryHeader(out);
    -      out.println("* The following document(s) were already found in Metacat:");
    -
    -      for (int i = 0; i < harvestDocumentList.size(); i++) {
    -        harvestDocument = (HarvestDocument) harvestDocumentList.get(i);
    -        if (harvestDocument != null) {
    -          if (harvestDocument.metacatHasIt)  {
    -            harvestDocument.prettyPrint(out);
    -          }
    -        }
    -      }
    -      printSiteSummaryTrailer(out);
    -    }
    -
    -  }
    -  
    -
    -  /**
    -   * Prints the header lines of a site summary entry.
    -   * 
    -   * @param out    the PrintStream to write to
    -   */
    -  void printSiteSummaryHeader(PrintStream out) {
    -    final String filler = Harvester.filler;
    -    final String marker = Harvester.marker;
    -
    -    out.println("");
    -    out.println(marker);
    -    out.println(filler);
    -  }
    -  
    -
    -  /**
    -   * Prints the trailing lines of a site summary entry.
    -   * 
    -   * @param out    the PrintStream to write to
    -   */
    -  void printSiteSummaryTrailer(PrintStream out) {
    -    final String filler = Harvester.filler;
    -    final String marker = Harvester.marker;
    -
    -    out.println(filler);
    -    out.println(marker);
    -  }
    -  
    -
    -  /**
    -   * Sends a report to the Site Contact summarizing the results of the harvest 
    -   * at that site.
    -   */
    -  void reportToSiteContact() {
    -    PrintStream body;
    -    String from = harvester.harvesterAdministrator;
    -    String[] fromArray;
    -    String maxCodeLevel = "notice";
    -    MailMessage msg;
    -    int nErrors = 0;
    -    String subject = "Report from Metacat Harvester: " + harvester.timestamp;
    -    String to = contactEmail;
    -    String[] toArray;
    -    
    -    if (!to.equals("")) {
    -      System.out.println("Sending report to siteScheduleID=" + siteScheduleID +
    -                         " at address: " + contactEmail);
    -      try {
    -        msg = new MailMessage(harvester.smtpServer);
    -        
    -        if (from.indexOf(',') > 0) {
    -          fromArray = from.split(",");
    -          
    -          for (int i = 0; i < fromArray.length; i++) {
    -            if (i == 0) {
    -              msg.from(fromArray[i]);
    -            }
    -            
    -            msg.cc(fromArray[i]);
    -            
    -          }
    -        }
    -        else if (from.indexOf(';') > 0) {
    -          fromArray = from.split(";");
    -
    -          for (int i = 0; i < fromArray.length; i++) {
    -            if (i == 0) {
    -              msg.from(fromArray[i]);
    -            }
    -            
    -            msg.cc(fromArray[i]);
    -            
    -          }
    -        }
    -        else {
    -          msg.from(from);
    -          msg.cc(from);
    -        }
    -        
    -        if (to.indexOf(',') > 0) {
    -          toArray = to.split(",");
    -          
    -          for (int i = 0; i < toArray.length; i++) {
    -            msg.to(toArray[i]);
    -          }
    -        }
    -        else if (to.indexOf(';') > 0) {
    -          toArray = to.split(";");
    -          
    -          for (int i = 0; i < toArray.length; i++) {
    -            msg.to(toArray[i]);
    -          }
    -        }
    -        else {
    -          msg.to(to);
    -        }
    -        
    -        msg.setSubject(subject);
    -        body = msg.getPrintStream();
    -        harvester.printHarvestHeader(body, siteScheduleID);
    -        printSiteSummary(body);
    -        harvester.printHarvestLog(body, maxCodeLevel, siteScheduleID);
    -        msg.sendAndClose();        
    -      }
    -      catch (IOException e) {
    -        System.out.println("There was a problem sending email to " + to);
    -        System.out.println("IOException: " + e.getMessage());
    -      }
    -    }
    -  }
    -    
    -
    -  /**
    -   * Accessor method for setting the value of the schemaLocation field.
    -   * 
    -   * @param schemaLocation  the new value of the schemaLocation field
    -   */
    -  public void setSchemaLocation(String schemaLocation) {
    -    this.schemaLocation = schemaLocation;
    -  }
    -
    -
    -  /**
    -   * This inner class extends DefaultHandler. It parses the document list,
    -   * creating a new HarvestDocument object every time it finds a </Document>
    -   * end tag.
    -   */
    -  class DocumentListHandler extends DefaultHandler implements ErrorHandler {
    -  
    -    public String scope;
    -    public int identifier;
    -    public String identifierString;
    -    public String documentType;
    -    public int revision;
    -    public String revisionString;
    -    public String documentURL;
    -    private String currentQname;
    -    public final static String DEFAULT_PARSER = 
    -           "org.apache.xerces.parsers.SAXParser";
    -    private boolean schemaValidate = true;
    -	
    -
    -	  /**
    -     * This method is called for any plain text within an element.
    -     * It parses the value for any of the following elements:
    -     * <scope>, <identifier>, <revision>, <documentType>, <documentURL>
    -     * 
    -     * @param ch          the character array holding the parsed text
    -     * @param start       the start index
    -     * @param length      the text length
    -     * 
    -     */
    -    public void characters (char ch[], int start, int length) {
    -      String s = new String(ch, start, length);
    - 
    -      if (length > 0) {           
    -        if (currentQname.equals("scope")) {
    -          scope += s;
    -        }
    -        else if (currentQname.equals("identifier")) {
    -          identifierString += s;
    -        }
    -        else if (currentQname.equals("revision")) {
    -          revisionString += s;
    -        }
    -        else if (currentQname.equals("documentType")) {
    -          documentType += s;
    -        }
    -        else if (currentQname.equals("documentURL")) {
    -          documentURL += s;
    -        }
    -      }
    -    }
    -
    -
    -    /** 
    -     * Handles an end-of-document event.
    -     */
    -    public void endDocument () {
    -      System.out.println("Finished parsing " + documentListURL);
    -    }
    -
    -
    -    /** 
    -     * Handles an end-of-element event. If the end tag is </Document>, then
    -     * creates a new HarvestDocument object and pushes it to the document
    -     * list.
    -     * 
    -     * @param uri
    -     * @param localname
    -     * @param qname
    -     */
    -    public void endElement(String uri, 
    -                           String localname,
    -                           String qname) {
    -      
    -      HarvestDocument harvestDocument;
    -      
    -      if (qname.equals("identifier")) {
    -        identifier = Integer.parseInt(identifierString);
    -      }
    -      else if (qname.equals("revision")) {
    -        revision = Integer.parseInt(revisionString);
    -      }
    -      else if (qname.equals("document")) {
    -        harvestDocument = new HarvestDocument(
    -                                              harvester,
    -                                              HarvestSiteSchedule.this,
    -                                              scope,
    -                                              identifier,
    -                                              revision,
    -                                              documentType,
    -                                              documentURL
    -                                             );
    -        harvestDocumentList.add(harvestDocument);
    -      }
    -
    -      currentQname = "";
    -    }
    -
    -
    -    /**
    -     * Method for handling errors during a parse
    -     *
    -     * @param exception         The parsing error
    -     * @exception SAXException  Description of Exception
    -     */
    -     public void error(SAXParseException e) throws SAXParseException {
    -        System.out.println("SAXParseException: " + e.getMessage());
    -        throw e;
    -    }
    -
    -
    -    /**
    -     * Run the validating parser
    -     *
    -     * @param xml             the xml stream to be validated
    -     * @schemaLocation        relative path the to XML Schema file, e.g. "."
    -     * @exception IOException thrown when test files can't be opened
    -     * @exception ClassNotFoundException thrown when SAX Parser class not found
    -     * @exception SAXException
    -     * @exception SAXParserException
    -     */
    -    public void runParser(Reader xml, String schemaLocation)
    -           throws IOException, ClassNotFoundException,
    -                  SAXException, SAXParseException {
    -
    -      // Get an instance of the parser
    -      XMLReader parser;
    -
    -      parser = XMLReaderFactory.createXMLReader(DEFAULT_PARSER);
    -      // Set Handlers in the parser
    -      parser.setContentHandler((ContentHandler)this);
    -      parser.setErrorHandler((ErrorHandler)this);
    -      parser.setFeature("http://xml.org/sax/features/namespaces", true);
    -      parser.setFeature("http://xml.org/sax/features/namespace-prefixes", true);
    -      parser.setFeature("http://xml.org/sax/features/validation", true);
    -      parser.setProperty(
    -              "http://apache.org/xml/properties/schema/external-schemaLocation", 
    -              schemaLocation);
    -
    -      if (schemaValidate) {
    -        parser.setFeature("http://apache.org/xml/features/validation/schema", 
    -                          true);
    -      }
    -    
    -      // Parse the document
    -      parser.parse(new InputSource(xml));
    -    }
    -    /**
    -     * Handles a start-of-document event.
    -     */
    -    public void startDocument () {
    -      System.out.println("Started parsing " + documentListURL);
    -    }
    -
    -
    -    /** 
    -     * Handles a start-of-element event.
    -     * 
    -     * @param uri
    -     * @param localname
    -     * @param qname
    -     * @param attributes
    -     */
    -    public void startElement(String uri, 
    -                             String localname,
    -                             String qname,
    -                             Attributes attributes) {
    -      
    -      currentQname = qname;
    -
    -      if (qname.equals("scope")) {
    -        scope = "";
    -      }
    -      else if (qname.equals("identifier")) {
    -        identifierString = "";
    -      }
    -      else if (qname.equals("revision")) {
    -        revisionString = "";
    -      }
    -      else if (qname.equals("documentType")) {
    -        documentType = "";
    -      }
    -      else if (qname.equals("documentURL")) {
    -        documentURL = "";
    -      }
    -    }
    -  }
    -}
    
  • src/edu/ucsb/nceas/metacat/harvesterClient/LoginServlet.java+0 117 removed
    @@ -1,117 +0,0 @@
    -/**
    - *  '$RCSfile$'
    - *  Copyright: 2004 University of New Mexico and the 
    - *                  Regents of the University of California
    - *
    - *   '$Author$'
    - *     '$Date$'
    - * '$Revision$'
    - *
    - * This program is free software; you can redistribute it and/or modify
    - * it under the terms of the GNU General Public License as published by
    - * the Free Software Foundation; either version 2 of the License, or
    - * (at your option) any later version.
    - *
    - * This program is distributed in the hope that it will be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write to the Free Software
    - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    - */
    -
    -package edu.ucsb.nceas.metacat.harvesterClient;
    -
    -import java.io.PrintWriter;
    -import javax.servlet.ServletConfig;
    -import javax.servlet.ServletContext;
    -import javax.servlet.ServletException;
    -import javax.servlet.ServletInputStream;
    -import javax.servlet.http.HttpServlet;
    -import javax.servlet.http.HttpServletRequest;
    -import javax.servlet.http.HttpServletResponse;
    -import javax.servlet.http.HttpSession;
    -import javax.servlet.http.HttpUtils;
    -import javax.servlet.ServletOutputStream;
    -import edu.ucsb.nceas.metacat.AuthSession;
    -
    -/**
    - *  LoginServlet implements a Harvester servlet to login to Metacat
    - */
    -public class LoginServlet extends HttpServlet {
    -
    -  public void destroy() {
    -    // Close all connections
    -    System.out.println("Destroying LoginServlet");
    -  }
    -
    -  /**
    -   *  Handle "GET" method requests from HTTP clients
    -   *
    -   *  @param  request   The request
    -   *  @param  response  The response
    -   *  @throws ServletException, java.io.IOException
    -   */
    -  public void doGet(HttpServletRequest request, HttpServletResponse response)
    -          throws ServletException, java.io.IOException {
    -    // Process the data and send back the response
    -    handleGetOrPost(request, response);
    -  }
    -
    -  /**
    -   *  Handle "POST" method requests from HTTP clients
    -   *
    -   *  @param  request   The request
    -   *  @param  response  The response
    -   *  @throws ServletException, java.io.IOException
    -   */
    -  public void doPost(HttpServletRequest request, HttpServletResponse response)
    -          throws ServletException, java.io.IOException {
    -    // Process the data and send back the response
    -    handleGetOrPost(request, response);
    -  }
    -
    -  /**
    -   *  Handle "GET" or "POST" method requests from HTTP clients
    -   *
    -   *  @param  request   The request
    -   *  @param  response  The response
    -   *  @throws ServletException, java.io.IOException
    -   */
    -  private void handleGetOrPost(HttpServletRequest request,
    -                               HttpServletResponse response)
    -          throws ServletException, java.io.IOException {
    -    AuthSession authSession = null;
    -    HttpSession httpSession;
    -    boolean isValid;
    -    PrintWriter out = response.getWriter();
    -    String passwd = request.getParameter("passwd");
    -    String user = request.getParameter("user");
    -
    -    response.setContentType("text/plain");
    -
    -    try {
    -      authSession = new AuthSession();
    -    } 
    -    catch (Exception e) {
    -      out.println("Error creating AuthSession: " + e.getMessage());
    -      return;
    -    }
    -
    -    isValid = authSession.authenticate(request, user, passwd);
    -    
    -    if (isValid) {
    -      System.out.println(authSession.getMessage());
    -      httpSession = request.getSession(true);
    -      httpSession.setAttribute("username", user);
    -      httpSession.setAttribute("password", passwd);
    -      response.sendRedirect("../style/skins/dev/harvesterUpload.html");
    -    }
    -    else {
    -      out.println("Error authenticating Metacat login: " + 
    -                  authSession.getMessage());
    -    }
    -  }
    -}
    
  • src/edu/ucsb/nceas/metacat/harvesterClient/MetUpload.java+0 347 removed
    @@ -1,347 +0,0 @@
    -/**
    - *  '$RCSfile$'
    - *  Copyright: 2004 University of New Mexico and the 
    - *                  Regents of the University of California
    - *
    - *   '$Author$'
    - *     '$Date$'
    - * '$Revision$'
    - *
    - * This program is free software; you can redistribute it and/or modify
    - * it under the terms of the GNU General Public License as published by
    - * the Free Software Foundation; either version 2 of the License, or
    - * (at your option) any later version.
    - *
    - * This program is distributed in the hope that it will be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write to the Free Software
    - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    - */
    -
    -package edu.ucsb.nceas.metacat.harvesterClient;
    -
    -import java.io.*;
    -import java.util.*;
    -import javax.servlet.ServletConfig;
    -import javax.servlet.ServletContext;
    -import javax.servlet.ServletException;
    -import javax.servlet.ServletInputStream;
    -import javax.servlet.http.HttpServlet;
    -import javax.servlet.http.HttpServletRequest;
    -import javax.servlet.http.HttpServletResponse;
    -import javax.servlet.http.HttpSession;
    -import javax.servlet.http.HttpUtils;
    -import javax.servlet.ServletOutputStream;
    -import com.oreilly.servlet.multipart.FilePart;
    -import com.oreilly.servlet.multipart.MultipartParser;
    -import com.oreilly.servlet.multipart.ParamPart;
    -import com.oreilly.servlet.multipart.Part;
    -
    -import edu.ucsb.nceas.metacat.client.*;
    -import edu.ucsb.nceas.metacat.properties.PropertyService;
    -import edu.ucsb.nceas.metacat.shared.ServiceException;
    -import edu.ucsb.nceas.metacat.util.SystemUtil;
    -import edu.ucsb.nceas.utilities.GeneralPropertyException;
    -import edu.ucsb.nceas.utilities.IOUtil;
    -
    -/**
    - *  MetUpload implements a Harvester servlet to insert, update, or delete
    - *  a single file to Metacat.
    - */
    -public class MetUpload extends HttpServlet {
    -
    -  /*
    -   * Class fields
    -   */
    -  private static final String CONFIG_DIR = "WEB-INF";
    -  private static final String CONFIG_NAME = "metacat.properties";
    -   
    -  /* Object fields */
    -  private ServletConfig config = null;
    -  private ServletContext context = null;
    -  private String metacatURL;
    -
    -  /**
    -   *  Handle POST requests made to the Harvester MetUpload servlet.
    -   *
    -   *  @param  req   The request
    -   *  @param  res   The response
    -   *  @throws IOException
    -   */
    -  public void doPost(HttpServletRequest req, HttpServletResponse res) 
    -          throws IOException {
    -    Part            aPart;
    -    boolean         delete = false;
    -    String          docid = "";
    -    String          fieldName;
    -    String          fieldValue;
    -    String          fileName = "";
    -    FilePart        fPart = null;
    -    PrintWriter     out = res.getWriter();
    -    MultipartParser parser = new MultipartParser(req, 1024 * 1024);
    -    ParamPart       pPart;
    -    HttpSession     sess = req.getSession(true);
    -    String          password = (String) sess.getAttribute("password");
    -    StringReader    sr = null;
    -    boolean         upload = false;
    -    String          username = (String) sess.getAttribute("username");
    -    
    -    res.setContentType("text/plain");
    -
    -    try {
    -      while ((aPart = parser.readNextPart()) != null) {
    -
    -        if (aPart.isParam() == true) {
    -          pPart = (ParamPart) aPart;
    -          fieldName = pPart.getName();
    -
    -          if (fieldName != null) {
    -            if (fieldName.equals("docid")) {
    -              docid = pPart.getStringValue();
    -            }
    -            else if (fieldName.equals("Upload")) {
    -              upload = true;
    -            }
    -            else if (fieldName.equals("Delete")) {
    -              delete = true;
    -            }            
    -          }
    -        }
    -        else if (aPart.isFile() == true) {
    -          fPart = (FilePart) aPart;
    -          fieldName = fPart.getName();
    -          fileName = fPart.getFileName();
    -          sr = writeTempFile(fPart, out, docid, fileName);
    -        }
    -
    -      }
    -    }
    -    catch (Exception e) {
    -      System.out.println("Error parsing parameters: " + e.getMessage());
    -    }
    -
    -    if (upload) {
    -      upload(out, docid, sr, username, password);
    -    }
    -    if (delete) {
    -      delete(out, docid, username, password);
    -    }
    -  }
    -
    -
    -  /**
    -   * Deletes a file from Metacat based on its docid.
    -   * 
    -   * @param out        the PrintWriter output stream
    -   * @param docid      the Metacat document id, e.g. document.1.1
    -   * @param username   the Metacat username
    -   * @param password   the Metacat password
    -   */
    -  private void delete(PrintWriter out, 
    -                      String docid,
    -                      String username,
    -                      String password
    -                     ) {
    -    Metacat  metacat;
    -    String   metacatResponse;
    -
    -    if (docid.equals("")) {
    -      out.println("Error deleting document: No DocID specified");
    -      return;
    -    }
    -
    -    try {    
    -      metacat = MetacatFactory.createMetacatConnection(metacatURL);
    -      metacat.login(username, password);
    -      metacatResponse = metacat.delete(docid);
    -      out.println(metacatResponse);
    -    }
    -    catch (MetacatAuthException e) {
    -      out.println("Metacat delete failed: MetacatAuthException:" + 
    -                  e.getMessage());
    -    }
    -    catch (MetacatInaccessibleException e) {
    -      out.println("Metacat delete failed:  MetacatInaccessibleException:" + 
    -                  e.getMessage());
    -    }
    -    catch (InsufficientKarmaException e) {
    -      out.println("Metacat delete failed: InsufficientKarmaException:" + 
    -                   e.getMessage());
    -    }
    -    catch (MetacatException e) {
    -      out.println("Metacat delete failed: MetacatException:" + 
    -                  e.getMessage());
    -    }
    -
    -  }
    -
    -  /**
    -	 * Initializes the servlet. Reads properties and initializes object fields.
    -	 * 
    -	 * @throws ServletException
    -	 */
    -	public void init(ServletConfig config) throws ServletException {
    -		String dirPath;
    -
    -		super.init(config);
    -		this.config = config;
    -		this.context = config.getServletContext();
    -		dirPath = context.getRealPath(CONFIG_DIR);
    -
    -		try {
    -			PropertyService.getInstance();
    -			metacatURL = SystemUtil.getServletURL();
    -		} catch (ServiceException se) {
    -			System.out.println("Service problem while initializing MetUpload: " + se.getMessage());
    -		} catch (GeneralPropertyException gpe) {
    -			System.out.println("Error initializing properties utility: " + gpe.getMessage());
    -		}
    -
    -		System.out.println("metacatURL: " + metacatURL);
    -	}
    -
    -
    -  /**
    -	 * Uploads a file to Metacat for insertion or updating. This implementation
    -	 * is limited by the fact that all ".1" documents are inserted while all
    -	 * other revisions are updated. This logic can be improved after the Metacat
    -	 * interface is extended with additional methods to query information about
    -	 * revisions, for example, hasDocument() and highestRevision().
    -	 * 
    -	 * @param out
    -	 *            the PrintWriter output stream
    -	 * @param docid
    -	 *            the docid, e.g. "document.1.1"
    -	 * @param sr
    -	 *            the StringReader containing the contents of the document
    -	 * @param username
    -	 *            the Metacat username
    -	 * @param password
    -	 *            the Metacat password
    -	 */
    -  private void upload(PrintWriter out, 
    -                      String docid,
    -                      StringReader sr,
    -                      String username,
    -                      String password
    -                     ) {
    -    FileReader      fr;
    -    Metacat         metacat;
    -    String          metacatResponse;
    -    String          revision;
    -    int             strLen;
    -
    -    if (docid.equals("")) {
    -      out.println("Error uploading: No docid specified");
    -      return;
    -    }
    -    
    -    if (sr == null) {
    -      out.println("Error uploading: No EML file specified");
    -      return;
    -    }
    -
    -    try {
    -      metacat = MetacatFactory.createMetacatConnection(metacatURL);
    -      metacat.login(username, password);
    -      strLen = docid.length();
    -      revision = docid.substring((strLen - 2), strLen);
    -                
    -      if (revision.equals(".1")) {
    -        metacatResponse = metacat.insert(docid, sr, null);
    -      }
    -      else {
    -        metacatResponse = metacat.update(docid, sr, null);
    -      }
    -
    -      out.println(metacatResponse);
    -    }
    -    catch (MetacatAuthException e) {
    -      out.println("Metacat upload failed: MetacatAuthException:" + 
    -                  e.getMessage());
    -    }
    -    catch (MetacatInaccessibleException e) {
    -      out.println("Metacat upload failed:  MetacatInaccessibleException:" + 
    -                  e.getMessage());
    -    }
    -    catch (InsufficientKarmaException e) {
    -      out.println("Metacat upload failed: InsufficientKarmaException:" + 
    -                   e.getMessage());
    -    }
    -    catch (MetacatException e) {
    -      out.println("Metacat upload failed: MetacatException:" + 
    -                  e.getMessage());
    -    }
    -    catch (IOException e) {
    -      out.println("Metacat upload failed: IOException:" + 
    -                  e.getMessage());
    -    }
    -            
    -  }
    -  
    -
    -  /**
    -   * Writes the uploaded file to disk and then reads it into a StringReader for
    -   * subsequent upload to Metacat.
    -   * 
    -   * @param fPart     the FilePart object containing the file form parameter
    -   * @param out       the PrintWriter output stream
    -   * @param docid     the document id, e.g. "document.1.1"
    -   * @param fileName  the name of the file to be written to disk
    -   * @return sr       a StringReader containing the contents of the file
    -   */
    -  private StringReader writeTempFile(FilePart fPart,
    -                                     PrintWriter out, 
    -                                     String docid,
    -                                     String fileName
    -                                    ) {
    -    FileReader      fr;
    -    String          metacatResponse;
    -    StringReader    sr = null;
    -    File            tmpDir;
    -    String          tmpDirPath;
    -    File            tmpFile;
    -    String          tmpFilePath = "";
    -    String          xmlString = "";
    -
    -    if ((fileName == null) || fileName.equals("")) {
    -      return sr;
    -    }
    -    
    -    tmpDirPath = System.getProperties().getProperty("java.io.tmpdir");
    -    tmpDir = new File(tmpDirPath);
    -    
    -    // Create the temporary directory if it doesn't exist
    -    try {
    -      if (!tmpDir.exists()) {
    -        tmpDir.mkdirs();
    -      }
    -    }
    -    catch (SecurityException e) {
    -      out.println("Can't create directory: " + tmpDir.getPath());
    -      out.println(e.getMessage());
    -    }
    -
    -    // Write the image to a file
    -    try {
    -      tmpFile = new File(tmpDirPath, fileName);
    -      fPart.writeTo(tmpFile);
    -      tmpFilePath = tmpDirPath + File.separator + fileName;
    -      fr = new FileReader(tmpFilePath);
    -      xmlString = IOUtil.getAsString(fr, true);
    -      sr = new StringReader(xmlString);
    -      tmpFile.delete();           // Clean up the temporary file from disk
    -    }
    -    catch (IOException e) {
    -      out.println("IOException: " + tmpFilePath + e.getMessage());
    -    }
    -
    -    return sr;
    -  }
    -  
    -  
    -}
    
  • test/edu/ucsb/nceas/metacattest/harvesterClient/HarvestDetailLogTest.java+0 182 removed
    @@ -1,182 +0,0 @@
    -/**
    - *  '$RCSfile$'
    - *  Copyright: 2004 Regents of the University of California and the
    - *              National Center for Ecological Analysis and Synthesis,
    - *              and the University of New Mexico
    - *              
    - *  Purpose: To test the HarvestDetailLog class by using JUnit
    - *
    - *   '$Author$'
    - *     '$Date$'
    - * '$Revision$'
    - *
    - * This program is free software; you can redistribute it and/or modify
    - * it under the terms of the GNU General Public License as published by
    - * the Free Software Foundation; either version 2 of the License, or
    - * (at your option) any later version.
    - *
    - * This program is distributed in the hope that it will be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write to the Free Software
    - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    - */
    -
    -package edu.ucsb.nceas.metacattest.harvesterClient;
    -
    -import edu.ucsb.nceas.MCTestCase;
    -import edu.ucsb.nceas.metacat.harvesterClient.Harvester;
    -import edu.ucsb.nceas.metacat.harvesterClient.HarvestDetailLog;
    -import edu.ucsb.nceas.metacat.harvesterClient.HarvestDocument;
    -import edu.ucsb.nceas.metacat.harvesterClient.HarvestSiteSchedule;
    -import edu.ucsb.nceas.metacat.properties.PropertyService;
    -import edu.ucsb.nceas.metacat.util.MetacatUtil;
    -
    -import java.sql.Connection;
    -import junit.framework.Test;
    -import junit.framework.TestSuite;
    -
    -/**
    - * Tests HarvestDetailLog code using JUnit.
    - *
    - * @author  costa
    - */
    -public class HarvestDetailLogTest extends MCTestCase {
    -
    -  private Harvester harvester;
    -  private HarvestDetailLog harvestDetailLog;
    -  private HarvestDocument harvestDocument;
    -  private HarvestSiteSchedule harvestSiteSchedule;
    -  /* Initialize Properties*/
    -  static
    -  {
    -	  try
    -	  {
    -		  PropertyService.getInstance();
    -	  }
    -	  catch(Exception e)
    -	  {
    -		  System.err.println("Exception in initialize option in MetacatServletNetTest "+e.getMessage());
    -	  }
    -  }
    -
    -  /**
    -   * Constructor for this test.
    -   * 
    -   * @param name     name of the test case
    -   */
    -  public HarvestDetailLogTest(String name) {
    -    super(name);
    -  }
    -  
    -
    -  /**
    -   * Sets up the test by instantiating HarvestSiteSchedule, HarvestDocument,
    -   * and HarvestDetailLog objects.
    -   */
    -  protected void setUp() {
    -    Connection conn;
    -    boolean commandLineMode = true;
    -    String contactEmail = "jdoe@institution.edu";
    -    String dateLastHarvest = "2004-04-01 00:00:00.0";
    -    String dateNextHarvest = "2004-05-01 00:00:00.0";
    -    int detailLogID;
    -    String documentListURL = 
    -                 "http://www.institution.edu/~jdoe/public_html/harvestList.xml";
    -    String documentType = "eml://ecoinformatics.org/eml-2.0.0";
    -    String documentURL = 
    -                   "http://www.institution.edu/~jdoe/public_html/document1.xml";
    -    String errorMessage = "JUnit testing";
    -    int harvestLogID;
    -    int identifier = 1;
    -    String ldapDN = "uid=jdoe,o=lter,dc=ecoinformatics,dc=org";
    -    String ldapPwd = "secretpassword";
    -    int revision = 1;
    -    String scope = "docname";
    -    int siteScheduleID = 1;
    -    boolean test = true;
    -    String unit = "months";
    -    int updateFrequency = 1;
    -  
    -    harvester = new Harvester();
    -    Harvester.loadProperties(metacatContextDir);
    -    conn = harvester.getConnection();  // initializes the database connection
    -    harvester.initLogIDs();
    -    harvestLogID = harvester.getHarvestLogID();
    -    detailLogID = harvester.getDetailLogID();
    -
    -    harvestSiteSchedule = new HarvestSiteSchedule(harvester,
    -                                                  siteScheduleID,
    -                                                  documentListURL,
    -                                                  ldapDN,
    -                                                  ldapPwd,
    -                                                  dateNextHarvest,
    -                                                  dateLastHarvest,
    -                                                  updateFrequency,
    -                                                  unit,
    -                                                  contactEmail
    -                                                 );
    -
    -    harvestDocument = new HarvestDocument(harvester,
    -                                          harvestSiteSchedule,
    -                                          scope,
    -                                          identifier,
    -                                          revision,
    -                                          documentType,
    -                                          documentURL
    -                                        );
    -    
    -    harvestDetailLog = new HarvestDetailLog(harvester, conn, harvestLogID, 
    -                                            detailLogID, harvestDocument, 
    -                                            errorMessage);
    -  }
    -  
    -
    -  /**
    -   * Closes the database connection when the test completes.
    -   */
    -  protected void tearDown() {
    -    harvester.closeConnection();
    -  }
    -
    -
    -  /**
    -   * Tests that the harvestDetailLog object was constructed.
    -   */
    -  public void testHarvestDetailLogObject() {
    -    assertTrue(harvestDetailLog != null);
    -  }
    -  
    -  
    -  /**
    -   * Tests the printOutput() method.
    -   */
    -  public void testPrintOutput() {
    -    harvestDetailLog.printOutput(System.out);
    -  }
    -  
    -  
    -  /**
    -   * Returns the test suite. The test suite consists of all methods in this
    -   * class whose names start with "test".
    -   * 
    -   * @return  a TestSuite object
    -   */
    -  public static Test suite() {
    -    return new TestSuite(HarvestDetailLogTest.class);
    -  }
    -  
    -
    -  /**
    -   * The main program. Runs the test suite.
    -   * 
    -   * @param args   command line argument array.
    -   */
    -  public static void main(String args[]) {
    -    junit.textui.TestRunner.run(suite());
    -  }
    -
    -}
    
  • test/edu/ucsb/nceas/metacattest/harvesterClient/HarvestDocumentTest.java+0 202 removed
    @@ -1,202 +0,0 @@
    -/**
    - *  '$RCSfile$'
    - *  Copyright: 2004 Regents of the University of California and the
    - *              National Center for Ecological Analysis and Synthesis,
    - *              and the University of New Mexico
    - *              
    - *  Purpose: To test the HarvestDocument class by using JUnit
    - *
    - *   '$Author$'
    - *     '$Date$'
    - * '$Revision$'
    - *
    - * This program is free software; you can redistribute it and/or modify
    - * it under the terms of the GNU General Public License as published by
    - * the Free Software Foundation; either version 2 of the License, or
    - * (at your option) any later version.
    - *
    - * This program is distributed in the hope that it will be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write to the Free Software
    - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    - */
    -
    -package edu.ucsb.nceas.metacattest.harvesterClient;
    -
    -import edu.ucsb.nceas.MCTestCase;
    -import edu.ucsb.nceas.metacat.harvesterClient.HarvestDocument;
    -import edu.ucsb.nceas.metacat.harvesterClient.HarvestSiteSchedule;
    -import edu.ucsb.nceas.metacat.harvesterClient.Harvester;
    -import edu.ucsb.nceas.metacat.properties.PropertyService;
    -import edu.ucsb.nceas.metacat.util.MetacatUtil;
    -
    -import java.io.StringReader;
    -import java.util.Date;
    -import junit.framework.Test;
    -import junit.framework.TestSuite;
    -
    -/**
    - * Tests HarvestDocument code using JUnit.
    - *
    - * @author  costa
    - */
    -public class HarvestDocumentTest extends MCTestCase {
    -
    -  private Harvester harvester;
    -  private HarvestDocument harvestDocument;
    -  private HarvestSiteSchedule harvestSiteSchedule;
    -  /* Initialize Properties*/
    -  static
    -  {
    -	  try
    -	  {
    -		  PropertyService.getInstance();
    -	  }
    -	  catch(Exception e)
    -	  {
    -		  System.err.println("Exception in initialize option in MetacatServletNetTest "+e.getMessage());
    -	  }
    -  }
    -
    -  /**
    -   * Constructor for this test.
    -   * 
    -   * @param name     name of the test case
    -   */
    -  public HarvestDocumentTest(String name) {
    -    super(name);
    -  }
    -  
    -
    -  /**
    -   * Sets up the test by instantiating HarvestSiteSchedule and HarvestDocument
    -   * objects.
    -   */
    -  protected void setUp() {
    -    boolean commandLineMode = true;
    -    String contactEmail = "jdoe@institution.edu";
    -    String dateLastHarvest = "2004-04-01 00:00:00.0";
    -    String dateNextHarvest = "2004-05-01 00:00:00.0";
    -    int detailLogID;
    -    String documentListURL = 
    -                 "https://code.ecoinformatics.org/code/metacat/branches/METACAT_1_9_4_BRANCH/test/harvester/sampleHarvestList.xml";
    -    String documentType = "eml://ecoinformatics.org/eml-2.0.0";
    -    String documentURL = 
    -                     "https://code.ecoinformatics.org/code/metacat/branches/METACAT_1_9_4_BRANCH/test/eml-sample.xml";
    -    String errorMessage = "JUnit Testing";
    -    int harvestLogID;
    -    String harvestOperationCode = "harvester.HarvesterStartup";
    -    Date harvestStartTime = new Date();
    -    int identifier = 1;
    -    String ldapDN = "uid=jdoe,o=lter,dc=ecoinformatics,dc=org";
    -    String ldapPwd = "secretpassword";
    -    String message = "JUnit Testing";
    -    int revision = 1;
    -    String scope = "docname";
    -    int siteScheduleID = 1;
    -    int status = 0;
    -    boolean test = true;
    -    String unit = "months";
    -    int updateFrequency = 1;
    -
    -    harvester = new Harvester();
    -    Harvester.loadProperties(metacatContextDir);
    -    harvester.getConnection();  // initializes the database connection
    -    harvester.initLogIDs();
    -    harvester.setHarvestStartTime(new Date());
    -
    -    harvestSiteSchedule = new HarvestSiteSchedule(harvester,
    -                                                  siteScheduleID,
    -                                                  documentListURL,
    -                                                  ldapDN,
    -                                                  ldapPwd,
    -                                                  dateNextHarvest,
    -                                                  dateLastHarvest,
    -                                                  updateFrequency,
    -                                                  unit,
    -                                                  contactEmail
    -                                                 );
    -
    -    harvestDocument = new HarvestDocument(harvester,
    -                                          harvestSiteSchedule,
    -                                          scope,
    -                                          identifier,
    -                                          revision,
    -                                          documentType,
    -                                          documentURL
    -                                        );
    -  }
    -  
    -
    -  /**
    -   * Closes the database connection after the test completes.
    -   */
    -  protected void tearDown() {
    -    harvester.closeConnection();
    -  }
    -  
    -
    -  /**
    -   * Tests the getSiteDocument() method. The test succeeds if a non-null
    -   * StringReader is returned.
    -   */
    -  public void testGetSiteDocument() {
    -    StringReader stringReader = null;
    -    stringReader = harvestDocument.getSiteDocument();
    -    assertTrue(stringReader != null);
    -  }
    -  
    -  
    -  /**
    -   * Tests that the harvesterDocument object was created successfully.
    -   */
    -  public void testHarvestDocumentObject() {
    -    assertTrue(harvestDocument != null);
    -  }
    -  
    -
    -  /**
    -   * Tests the metacatHighestRevision() method. This test ensures that -1
    -   * is returned for a non-existent document.
    -   */
    -  public void testMetacatHighestRevision() {
    -    int highestRevision;
    -    
    -    highestRevision = harvestDocument.metacatHighestRevision();
    -    assertTrue(highestRevision == -1);
    -  }
    -
    -
    -  /**
    -   * Tests the printOutput() method.
    -   */
    -  public void testPrintOutput() {
    -    harvestDocument.printOutput(System.out);
    -  }
    -  
    -  
    -  /**
    -   * Returns the test suite. The test suite consists of all methods in this
    -   * class whose names start with "test".
    -   * 
    -   * @return  a TestSuite object
    -   */
    -  public static Test suite() {
    -    return new TestSuite(HarvestDocumentTest.class);
    -  }
    -  
    -
    -  /**
    -   * The main program. Runs the test suite.
    -   * 
    -   * @param args   command line argument array.
    -   */
    -  public static void main(String args[]) {
    -    junit.textui.TestRunner.run(suite());
    -  }
    -
    -}
    
  • test/edu/ucsb/nceas/metacattest/harvesterClient/HarvesterTest.java+0 158 removed
    @@ -1,158 +0,0 @@
    -/**
    - *  '$RCSfile$'
    - *  Copyright: 2004 Regents of the University of California and the
    - *              National Center for Ecological Analysis and Synthesis,
    - *              and the University of New Mexico
    - *              
    - *  Purpose: To test the Harvester class by using JUnit
    - *
    - *   '$Author$'
    - *     '$Date$'
    - * '$Revision$'
    - *
    - * This program is free software; you can redistribute it and/or modify
    - * it under the terms of the GNU General Public License as published by
    - * the Free Software Foundation; either version 2 of the License, or
    - * (at your option) any later version.
    - *
    - * This program is distributed in the hope that it will be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write to the Free Software
    - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    - */
    -
    -package edu.ucsb.nceas.metacattest.harvesterClient;
    -
    -import edu.ucsb.nceas.MCTestCase;
    -import edu.ucsb.nceas.metacat.harvesterClient.Harvester;
    -import edu.ucsb.nceas.metacat.properties.PropertyService;
    -import edu.ucsb.nceas.metacat.util.MetacatUtil;
    -import edu.ucsb.nceas.utilities.PropertyNotFoundException;
    -
    -import junit.framework.Test;
    -import junit.framework.TestSuite;
    -
    -/**
    - * Tests Harvester code using JUnit.
    - *
    - * @author  costa
    - */
    -public class HarvesterTest extends MCTestCase {
    -
    -  private Harvester harvester;
    -	/* Initialize Properties */
    -	static {
    -		try {
    -			PropertyService.getInstance();
    -		} catch (Exception e) {
    -			System.err.println("Exception in initialize option in MetacatServletNetTest "
    -					+ e.getMessage());
    -		}
    -	}
    -
    -  /**
    -	 * Constructor for this test.
    -	 * 
    -	 * @param name
    -	 *            name of the test case
    -	 */
    -  public HarvesterTest(String name) {
    -    super(name);
    -  }
    -  
    -
    -  /**
    -   * Sets up the test by instantiating a Harvester object.
    -   */
    -  protected void setUp() {
    -    harvester = new Harvester();
    -  }
    -  
    -
    -  /**
    -   * No clean-up actions necessary for these tests.
    -   */
    -  protected void tearDown() {
    -  }
    -  
    -
    -  /**
    -   * Tests the dequoteText() string function. It converts single quotes to
    -   * double quotes.
    -   */
    -  public void testDequoteText() {
    -    String singleQuoteString = "I can't see how it's done!\n";
    -    String compareString = "I can\"t see how it\"s done!";
    -    String dequotedString = "";
    -    
    -    dequotedString = harvester.dequoteText(singleQuoteString);
    -    assertTrue(dequotedString.equals(compareString));
    -    System.out.println("Dequoted string: " + dequotedString);
    -  }
    -  
    -  
    -  /**
    -   * Tests that the Harvester object was created successfully.
    -   */
    -  public void testHarvesterObject() {
    -    assertTrue(harvester != null);
    -  }
    -  
    -  
    -    /**
    -	 * Tests loading of Harvester properties from a configuration file.
    -	 */
    -	public void testLoadProperties() {
    -	    boolean commandLineMode = true;
    -		String ctm = null;
    -		boolean test = true;
    -
    -		Harvester.loadProperties(metacatContextDir);
    -		try {
    -			ctm = PropertyService.getProperty("harvester.connectToMetacat");
    -		} catch (PropertyNotFoundException pnfe) {
    -			fail("Could not get connectToMetacat property: "+ pnfe.getMessage());
    -		}
    -		assertTrue(ctm.equals("true") || ctm.equals("false"));
    -	}
    -  
    -  
    -  /**
    -	 * Prints the files in the current working directory. This may be useful for
    -	 * determining which directory all other tests are running in.
    -	 */
    -  public void testWorkingDirectory() {
    -    String[] dir = new java.io.File(".").list(); // Get files in current dir
    -
    -    java.util.Arrays.sort(dir);                  // Sort the directory listing
    -
    -    for (int i=0; i<dir.length; i++)
    -      System.out.println(dir[i]);                // Print the list
    -  }
    -  
    -  
    -  /**
    -   * Returns the test suite. The test suite consists of all methods in this
    -   * class whose names start with "test".
    -   * 
    -   * @return  a TestSuite object
    -   */
    -  public static Test suite() {
    -    return new TestSuite(HarvesterTest.class);
    -  }
    -  
    -
    -  /**
    -   * The main program. Runs the test suite.
    -   * 
    -   * @param args   command line argument array.
    -   */
    -  public static void main(String args[]) {
    -    junit.textui.TestRunner.run(suite());
    -  }
    -
    -}
    
  • test/edu/ucsb/nceas/metacattest/harvesterClient/HarvestLogTest.java+0 253 removed
    @@ -1,253 +0,0 @@
    -/**
    - *  '$RCSfile$'
    - *  Copyright: 2004 Regents of the University of California and the
    - *              National Center for Ecological Analysis and Synthesis,
    - *              and the University of New Mexico
    - *              
    - *  Purpose: To test the HarvestLog class by using JUnit
    - *
    - *   '$Author$'
    - *     '$Date$'
    - * '$Revision$'
    - *
    - * This program is free software; you can redistribute it and/or modify
    - * it under the terms of the GNU General Public License as published by
    - * the Free Software Foundation; either version 2 of the License, or
    - * (at your option) any later version.
    - *
    - * This program is distributed in the hope that it will be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write to the Free Software
    - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    - */
    -
    -package edu.ucsb.nceas.metacattest.harvesterClient;
    -
    -import edu.ucsb.nceas.metacat.harvesterClient.HarvestSiteSchedule;
    -import java.sql.Connection;
    -import java.util.Date;
    -
    -import edu.ucsb.nceas.MCTestCase;
    -import edu.ucsb.nceas.metacat.harvesterClient.Harvester;
    -import edu.ucsb.nceas.metacat.harvesterClient.HarvestDocument;
    -import edu.ucsb.nceas.metacat.harvesterClient.HarvestLog;
    -import edu.ucsb.nceas.metacat.properties.PropertyService;
    -import edu.ucsb.nceas.metacat.util.MetacatUtil;
    -
    -import junit.framework.Test;
    -import junit.framework.TestSuite;
    -
    -/**
    - * Tests HarvestLog code using JUnit.
    - *
    - * @author  costa
    - */
    -public class HarvestLogTest extends MCTestCase {
    -
    -  private Connection conn;
    -  private Harvester harvester;
    -  private HarvestLog harvestLogShallow;
    -  private HarvestLog harvestLogDeep;
    -  private HarvestSiteSchedule harvestSiteSchedule;
    -  /* Initialize Properties*/
    -  static
    -  {
    -	  try
    -	  {
    -		  PropertyService.getInstance();
    -	  }
    -	  catch(Exception e)
    -	  {
    -		  System.err.println("Exception in initialize option in MetacatServletNetTest "+e.getMessage());
    -	  }
    -  }
    -
    -  /**
    -   * Constructor for this test.
    -   * 
    -   * @param name     name of the test case
    -   */
    -  public HarvestLogTest(String name) {
    -    super(name);
    -  }
    -  
    -
    -  /**
    -   * Sets up the test by instantiating a HarvestSiteSchedule, HarvestDocument,
    -   * and two HarvestLog objects. The harvestLogShallow is a HarvestLog that
    -   * does not have an associated HarvestDetailLog. The harvestLogDeep is a
    -   * HarvestLog that does have an associated HarvestDetailLog.
    -   */
    -  protected void setUp() {
    -    boolean commandLineMode = true;
    -    String contactEmail = "jdoe@institution.edu";
    -    String dateLastHarvest = "2004-04-01 00:00:00.0";
    -    String dateNextHarvest = "2004-05-01 00:00:00.0";
    -    int detailLogID;
    -    String documentListURL = 
    -                 "http://www.institution.edu/~jdoe/public_html/harvestList.xml";
    -    String documentType = "eml://ecoinformatics.org/eml-2.0.0";
    -    String documentURL = 
    -                   "http://www.institution.edu/~jdoe/public_html/document1.xml";
    -    String errorMessage = "JUnit Testing";
    -    HarvestDocument harvestDocument = null;
    -    int harvestLogID;
    -    String harvestOperationCode = "harvester.HarvesterStartup";
    -    Date harvestStartTime = new Date();
    -    int identifier = 1;
    -    String ldapDN = "uid=jdoe,o=lter,dc=ecoinformatics,dc=org";
    -    String ldapPwd = "secretpassword";
    -    String message = "JUnit Testing";
    -    int revision = 1;
    -    String scope = "docname";
    -    int siteScheduleID = 1;
    -    int status = 0;
    -    boolean test = true;
    -    String unit = "months";
    -    int updateFrequency = 1;
    -
    -    harvester = new Harvester();
    -    Harvester.loadProperties(metacatContextDir);
    -    conn = harvester.getConnection();  // initializes the database connection
    -    harvester.initLogIDs();
    -    harvestLogID = harvester.getHarvestLogID();
    -    harvestLogShallow = new HarvestLog(harvester, conn, harvestLogID, 
    -                                       harvestStartTime, status, 
    -                                       message, harvestOperationCode, 
    -                                       siteScheduleID);
    -
    -    harvestLogID = harvester.getHarvestLogID();
    -    detailLogID = harvester.getDetailLogID();
    -    harvestSiteSchedule = new HarvestSiteSchedule(harvester,
    -                                                  siteScheduleID,
    -                                                  documentListURL,
    -                                                  ldapDN,
    -                                                  ldapPwd,
    -                                                  dateNextHarvest,
    -                                                  dateLastHarvest,
    -                                                  updateFrequency,
    -                                                  unit,
    -                                                  contactEmail
    -                                                 );
    -
    -    harvestDocument = new HarvestDocument(harvester,
    -                                          harvestSiteSchedule,
    -                                          scope,
    -                                          identifier,
    -                                          revision,
    -                                          documentType,
    -                                          documentURL
    -                                        );
    -    
    -
    -    harvestLogDeep = new HarvestLog(harvester, conn, harvestLogID, detailLogID, 
    -                                    harvestStartTime, status, message,
    -                                    harvestOperationCode, siteScheduleID,
    -                                    harvestDocument, errorMessage);    
    -  }
    -  
    -
    -  /** 
    -   * Closes the database connection after the test completes.
    -   */
    -  protected void tearDown() {
    -    harvester.closeConnection();
    -  }
    -  
    -
    -  /**
    -   * Tests the getCodeLevelValue() method by comparing the value returned for
    -   * "error" (lowest level) to the value returned for "debug" (highest level).
    -   */
    -  public void testGetCodeLevelValue() {
    -    int lowLevel = harvestLogShallow.getCodeLevelValue("error");
    -    int highLevel = harvestLogShallow.getCodeLevelValue("debug");
    -    
    -    assertTrue(lowLevel < highLevel);
    -  }
    -  
    -
    -  /**
    -   * Tests the getExplanation() method. Check that a harvest operation code is
    -   * associated with an appropriate explanation string.
    -   */
    -  public void testGetExplanation() {
    -    String harvestOperationCode = "harvester.HarvesterStartup";
    -    String explanation;
    -
    -    explanation = harvestLogShallow.getExplanation(harvestOperationCode);
    -    assertTrue(explanation.equals("Harvester start up"));    
    -  }
    -  
    -
    -  /**
    -   * Tests the getHarvestOperationCodeLevel() method. Check that the method
    -   * returns an appropriate code level for a given harvest operation code.
    -   */
    -  public void testGetHarvestOperationCodeLevel() {
    -    String harvestOperationCode = "harvester.HarvesterStartup";
    -    String harvestOperationCodeLevel;
    -
    -    harvestOperationCodeLevel = 
    -           harvestLogShallow.getHarvestOperationCodeLevel(harvestOperationCode);
    -    assertTrue(harvestOperationCodeLevel.equalsIgnoreCase("Info"));    
    -  }
    -
    -
    -  /**
    -   * Tests the construction of HarvestLog object, and a HarvestLog object
    -   * that contains a HarvestDetailLog object.
    -   */
    -  public void testHarvestLogObject() {
    -    assertTrue(harvestLogShallow != null);
    -    assertTrue(harvestLogDeep != null);
    -  }
    -  
    -  
    -  /**
    -   * Tests the printOutput() method when the code level of this operation is
    -   * greater than the maximum level we wish to print. This means that the output
    -   * should not be printed.
    -   */
    -  public void testPrintOutputExceedsMax() {
    -    System.out.println("No output should be printed:");
    -    harvestLogDeep.printOutput(System.out, "Error");
    -  }
    -  
    -  
    -  /**
    -   * Tests the printOutput() method when the code level of this operation is
    -   * less than the maximum level we wish to print. This means that the output
    -   * should be printed.
    -   */
    -  public void testPrintOutputWithinMax() {
    -    System.out.println("The log output should be printed:");
    -    harvestLogDeep.printOutput(System.out, "Debug");
    -  }
    -  
    -  
    -  /**
    -   * Returns the test suite. The test suite consists of all methods in this
    -   * class whose names start with "test".
    -   * 
    -   * @return  a TestSuite object
    -   */
    -  public static Test suite() {
    -    return new TestSuite(HarvestLogTest.class);
    -  }
    -  
    -
    -  /**
    -   * The main program. Runs the test suite.
    -   * 
    -   * @param args   command line argument array.
    -   */
    -  public static void main(String args[]) {
    -    junit.textui.TestRunner.run(suite());
    -  }
    -
    -}
    
  • test/edu/ucsb/nceas/metacattest/harvesterClient/HarvestSiteScheduleTest.java+0 219 removed
    @@ -1,219 +0,0 @@
    -/**
    - *  '$RCSfile$'
    - *  Copyright: 2004 Regents of the University of California and the
    - *              National Center for Ecological Analysis and Synthesis,
    - *              and the University of New Mexico
    - *              
    - *  Purpose: To test the HarvestSiteSchedule class by using JUnit
    - *
    - *   '$Author$'
    - *     '$Date$'
    - * '$Revision$'
    - *
    - * This program is free software; you can redistribute it and/or modify
    - * it under the terms of the GNU General Public License as published by
    - * the Free Software Foundation; either version 2 of the License, or
    - * (at your option) any later version.
    - *
    - * This program is distributed in the hope that it will be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write to the Free Software
    - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    - */
    -
    -package edu.ucsb.nceas.metacattest.harvesterClient;
    -
    -import edu.ucsb.nceas.MCTestCase;
    -import edu.ucsb.nceas.metacat.harvesterClient.Harvester;
    -import edu.ucsb.nceas.metacat.harvesterClient.HarvestSiteSchedule;
    -import edu.ucsb.nceas.metacat.properties.PropertyService;
    -import edu.ucsb.nceas.metacat.util.MetacatUtil;
    -
    -import java.util.Date;
    -import javax.xml.parsers.ParserConfigurationException;
    -import junit.framework.Test;
    -import junit.framework.TestSuite;
    -
    -/**
    - * Tests HarvestSiteSchedule code using JUnit.
    - *
    - * @author  costa
    - */
    -public class HarvestSiteScheduleTest extends MCTestCase {
    -
    -  private Harvester harvester;
    -  private HarvestSiteSchedule harvestSiteScheduleFuture; // future date next har
    -  private HarvestSiteSchedule harvestSiteSchedulePast; // past date next harvest
    -  /* Initialize Properties*/
    -  static
    -  {
    -	  try
    -	  {
    -		  PropertyService.getInstance();
    -	  }
    -	  catch(Exception e)
    -	  {
    -		  System.err.println("Exception in initialize option in MetacatServletNetTest "+e.getMessage());
    -	  }
    -  }
    -
    -  /**
    -   * Constructor for this test.
    -   * 
    -   * @param name     name of the test case
    -   */
    -  public HarvestSiteScheduleTest(String name) {
    -    super(name);
    -  }
    -  
    -
    -  /**
    -   * Sets up the HarvestSiteScheduleTest by creating a pair of 
    -   * HarvestSiteSchedule objects. The harvestSiteScheduleFuture object
    -   * is used for a site with a future date of next harvest (not due for 
    -   * harvest now), while the harvestSiteSchedulePast object is used for a site 
    -   * with a past date of next harvest (is due for harvest now).
    -   */
    -  protected void setUp() {
    -    boolean commandLineMode = true;
    -    String contactEmail = "jdoe@institution.edu";
    -    String dateLastHarvest = "2004-04-01 00:00:00.0";
    -    String dateNextHarvestFuture = "2056-01-01 00:00:00.0";
    -    String dateNextHarvestPast = "2000-01-01 00:00:00.0";
    -    String documentListURL = 
    -                "https://code.ecoinformatics.org/code/metacat/branches/METACAT_1_9_4_BRANCH/test/harvester/sampleHarvestList.xml";
    -    String errorMessage = "JUnit Testing";
    -    String ldapDN = "uid=jdoe,o=lter,dc=ecoinformatics,dc=org";
    -    String ldapPwd = "secretpassword";
    -    int siteScheduleID = 1;
    -    boolean test = true;
    -    String unit = "months";
    -    int updateFrequency = 1;
    -
    -    harvester = new Harvester();
    -    Harvester.loadProperties(metacatContextDir);
    -    harvester.getConnection();  // initializes the database connection
    -    harvester.initLogIDs();
    -    harvester.setHarvestStartTime(new Date());
    -
    -    harvestSiteScheduleFuture = new HarvestSiteSchedule(harvester,
    -                                                  siteScheduleID,
    -                                                  documentListURL,
    -                                                  ldapDN,
    -                                                  ldapPwd,
    -                                                  dateNextHarvestFuture,
    -                                                  dateLastHarvest,
    -                                                  updateFrequency,
    -                                                  unit,
    -                                                  contactEmail
    -                                                 );
    -
    -    harvestSiteSchedulePast = new HarvestSiteSchedule(harvester,
    -                                                  siteScheduleID,
    -                                                  documentListURL,
    -                                                  ldapDN,
    -                                                  ldapPwd,
    -                                                  dateNextHarvestPast,
    -                                                  dateLastHarvest,
    -                                                  updateFrequency,
    -                                                  unit,
    -                                                  contactEmail
    -                                                 );
    -
    -  }
    -  
    -
    -  /**
    -   * Closes the database connection after the test completes.
    -   */
    -  protected void tearDown() {
    -    harvester.closeConnection();
    -  }
    -  
    -
    -  /**
    -   * Tests the dueForHarvest() method in the case where a site is not due for
    -   * a harvest.
    -   */
    -  public void testDueForHarvestFalse() {
    -    boolean dueForHarvest;
    -    
    -    dueForHarvest = harvestSiteScheduleFuture.dueForHarvest();
    -    assertTrue(dueForHarvest == false);
    -  }
    -  
    -
    -  /**
    -   * Tests the dueForHarvest() method in the case where a site is due for
    -   * a harvest.
    -   */
    -  public void testDueForHarvestTrue() {
    -    boolean dueForHarvest;
    -    
    -    dueForHarvest = harvestSiteSchedulePast.dueForHarvest();
    -    assertTrue(dueForHarvest == true);
    -  }
    -
    -
    -  /**
    -   * Tests the parseHarvestList() method.
    -   */
    -  public void testParseHarvestList() {
    -    boolean success = false;
    -    String schemaLocation =
    -         "eml://ecoinformatics.org/harvestList ./lib/harvester/harvestList.xsd";
    -         
    -    harvestSiteScheduleFuture.setSchemaLocation(schemaLocation);
    -    
    -    try {
    -      success = harvestSiteScheduleFuture.parseHarvestList();
    -      assertTrue(success == true);
    -    }
    -    catch (ParserConfigurationException e) {
    -      fail("ParserConfigurationException: " + e.getMessage());
    -    }    
    -  }
    -
    -
    -  /**
    -   * Tests the printOutput() method.
    -   */
    -  public void testPrintOutput() {
    -    harvestSiteScheduleFuture.printOutput(System.out);
    -  }
    -  
    -
    -  /**
    -   * Tests that the harvesterDocument object was created successfully.
    -   */
    -  public void testHarvestSiteScheduleObject() {
    -    assertTrue(harvestSiteScheduleFuture != null);
    -    assertTrue(harvestSiteSchedulePast != null);
    -  }
    -  
    -  
    -  /**
    -   * Returns the test suite. The test suite consists of all methods in this
    -   * class whose names start with "test".
    -   * 
    -   * @return  a TestSuite object
    -   */
    -  public static Test suite() {
    -    return new TestSuite(HarvestSiteScheduleTest.class);
    -  }
    -  
    -
    -  /**
    -   * The main program. Runs the test suite.
    -   * 
    -   * @param args   command line argument array.
    -   */
    -  public static void main(String args[]) {
    -    junit.textui.TestRunner.run(suite());
    -  }
    -
    -}
    

Vulnerability mechanics

Root cause

"Missing input sanitization in `HarvesterRegistration.dbInsert()` — the `quoteString()` helper wraps user-supplied values in single quotes without escaping, enabling SQL injection via string concatenation."

Attack vector

An unauthenticated attacker sends a crafted HTTP request to the `/harvesterRegistration` endpoint with malicious payloads in the `unit`, `contactEmail`, or `documentListURL` parameters. The servlet does not verify a real LDAP identity, so the vulnerable `INSERT` proceeds without authentication. Because the PostgreSQL backend supports stacked queries via `Statement.executeUpdate()`, the attacker can inject arbitrary SQL commands, achieving full read/write/execute access in the Metacat database context.

Affected code

The vulnerable code resides in the `HarvesterRegistration` servlet, specifically the `dbInsert()` method which builds an SQL `INSERT` statement against the `HARVEST_SITE_SCHEDULE` table using string concatenation. The `quoteString()` helper wraps values in single quotes without any escaping, and the three request parameters `unit`, `contactEmail`, and `documentListURL` reach this sink. The entire `harvesterClient` package, including `HarvesterRegistration.java`, was removed in commit [patch_id=6110799].

What the fix does

The patch [patch_id=6110799] removes the entire `harvesterClient` package (16 files, 6471 lines), including `HarvesterRegistration.java` which contained the SQL injection vulnerability. By deleting the vulnerable endpoint entirely, the attack surface is eliminated. The advisory states this was remediated in Metacat 3.0.0.

Preconditions

  • networkThe `/harvesterRegistration` endpoint must be exposed and reachable over the network.
  • authNo authentication or LDAP identity verification is required; the servlet allows the insert to proceed without checking credentials.
  • inputThe attacker must supply values for `unit`, `contactEmail`, or `documentListURL` parameters containing SQL metacharacters.

Generated on Jun 15, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

2

News mentions

0

No linked articles in our index yet.