CVE-2013-10019 (published 2023-02-20T07:15Z)

A vulnerability was found in OCLC-Research OAICat 1.5.61. It has been rated as critical. This issue affects some unknown processing. The manipulation leads to sql injection. The attack may be initiated remotely. Upgrading to version 1.5.62 is able to address this issue. The identifier of the patch is 6cc65501869fa663bcd24a70b63f41f5cfe6b3e1. It is recommended to upgrade the affected component. The identifier VDB-221489 was assigned to this vulnerability.

CVSS v3 base score: 9.8, CRITICAL (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)

Weakness information:
cwe_id: CWE-89
cwe_name: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')
description: The product constructs all or part of an SQL command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended SQL command when it is sent to a downstream component. Without sufficient removal or quoting of SQL syntax in user-controllable inputs, the generated SQL query can cause those inputs to be interpreted as SQL instead of ordinary user data.
extended_description: 
            
            
         
         

Fix information:
repo_url: https://github.com/OCLC-Research/oaicat
commit_details: repo_url: https://github.com/OCLC-Research/oaicat
author: realworldobject@gmail.com
author_date: 2013-10-18 17:27:18+00:00
msg: Added a AbstractCatalog.paramRegex property to address an SQL injection vulnerability that was reported by Ward van Wanrooij. [https://code.google.com/p/oaicat/issues/detail?id=7]
repository: repo_url: https://github.com/OCLC-Research/oaicat
repo_name: OCLC-Research/oaicat
description: Automatically exported from code.google.com/p/oaicat
repo_language: Java
owner: OCLC-Research
file_changes: filename: build.xml
change_type: ModificationType.MODIFY
diff: @@ -69,7 +69,7 @@
 -->
 
   <property name="app.name"      value="oaicat"/>
-  <property name="appp.version"   value="1.5.61"/>
+  <property name="appp.version"   value="1.5.62"/>
   <property name="build.home"    value="build"/>
   <property name="catalina.home" value="../../../.."/> <!-- UPDATE THIS! -->
   <property name="dist.home"     value="dist"/>

programming_language: HTML
filename: dist.html
change_type: ModificationType.MODIFY
diff: @@ -7,141 +7,144 @@
   <body>
     <h1>OAICat Distribution Files</h1>
     <ul>
-      <li><a href="oaicat-1.5.61.tar.gz">oaicat-1.5.61.tar.gz</a> Latest version</li>
-      <li><a href="oaicat-1.5.61.zip">oaicat-1.5.61.zip</a> Latest version</li>
-      
+      <li><a href="oaicat-1.5.62.tar.gz">oaicat-1.5.62.tar.gz</a> Latest version</li>
+      <li><a href="oaicat-1.5.62.zip">oaicat-1.5.62.zip</a> Latest version</li>
+
+      <li><a href="oaicat-1.5.61.tar.gz">oaicat-1.5.61.tar.gz</a></li>
+      <li><a href="oaicat-1.5.61.zip">oaicat-1.5.61.zip</a></li>
+
       <li><a href="oaicat-1.5.60.tar.gz">oaicat-1.5.60.tar.gz</a></li>
       <li><a href="oaicat-1.5.60.zip">oaicat-1.5.60.zip</a></li>
-      
+
       <li><a href="oaicat-1.5.59.tar.gz">oaicat-1.5.59.tar.gz</a></li>
       <li><a href="oaicat-1.5.59.zip">oaicat-1.5.59.zip</a></li>
-      
+
       <li><a href="oaicat-1.5.58.tar.gz">oaicat-1.5.58.tar.gz</a></li>
       <li><a href="oaicat-1.5.58.zip">oaicat-1.5.58.zip</a></li>
-      
+
       <li><a href="oaicat-1.5.57.tar.gz">oaicat-1.5.57.tar.gz</a></li>
       <li><a href="oaicat-1.5.57.zip">oaicat-1.5.57.zip</a></li>
-      
+
       <li><a href="oaicat-1.5.56.tar.gz">oaicat-1.5.56.tar.gz</a></li>
       <li><a href="oaicat-1.5.56.zip">oaicat-1.5.56.zip</a></li>
-      
+
       <li><a href="oaicat-1.5.55.tar.gz">oaicat-1.5.55.tar.gz</a></li>
       <li><a href="oaicat-1.5.55.zip">oaicat-1.5.55.zip</a></li>
-      
+
       <li><a href="oaicat-1.5.54.tar.gz">oaicat-1.5.54.tar.gz</a></li>
       <li><a href="oaicat-1.5.54.zip">oaicat-1.5.54.zip</a></li>
-      
+
       <li><a href="oaicat-1.5.53.tar.gz">oaicat-1.5.53.tar.gz</a></li>
       <li><a href="oaicat-1.5.53.zip">oaicat-1.5.53.zip</a></li>
-      
+
       <li><a href="oaicat-1.5.52.tar.gz">oaicat-1.5.52.tar.gz</a></li>
       <li><a href="oaicat-1.5.52.zip">oaicat-1.5.52.zip</a></li>
-      
+
       <li><a href="oaicat-1.5.51.tar.gz">oaicat-1.5.51.tar.gz</a></li>
       <li><a href="oaicat-1.5.51.zip">oaicat-1.5.51.zip</a></li>
-      
+
       <li><a href="oaicat-1.5.50.tar.gz">oaicat-1.5.50.tar.gz</a></li>
       <li><a href="oaicat-1.5.50.zip">oaicat-1.5.50.zip</a></li>
-      
+
       <li><a href="oaicat-1.5.49.tar.gz">oaicat-1.5.49.tar.gz</a></li>
       <li><a href="oaicat-1.5.49.zip">oaicat-1.5.49.zip</a></li>
-      
+
       <li><a href="oaicat-1.5.48.tar.gz">oaicat-1.5.48.tar.gz</a></li>
       <li><a href="oaicat-1.5.48.zip">oaicat-1.5.48.zip</a></li>
-      
+
       <li><a href="oaicat-1.5.47.tar.gz">oaicat-1.5.47.tar.gz</a></li>
       <li><a href="oaicat-1.5.47.zip">oaicat-1.5.47.zip</a></li>
-      
+
       <li><a href="oaicat-1.5.46.tar.gz">oaicat-1.5.46.tar.gz</a></li>
       <li><a href="oaicat-1.5.46.zip">oaicat-1.5.46.zip</a></li>
-      
+
       <li><a href="oaicat-1.5.45.tar.gz">oaicat-1.5.45.tar.gz</a></li>
       <li><a href="oaicat-1.5.45.zip">oaicat-1.5.45.zip</a></li>
-      
+
       <li><a href="oaicat-1.5.44.tar.gz">oaicat-1.5.44.tar.gz</a></li>
       <li><a href="oaicat-1.5.44.zip">oaicat-1.5.44.zip</a></li>
-      
+
       <li><a href="oaicat-1.5.43.tar.gz">oaicat-1.5.43.tar.gz</a></li>
       <li><a href="oaicat-1.5.43.zip">oaicat-1.5.43.zip</a></li>
-      
+
       <li><a href="oaicat-1.5.42.tar.gz">oaicat-1.5.42.tar.gz</a></li>
       <li><a href="oaicat-1.5.42.zip">oaicat-1.5.42.zip</a></li>
-      
+
       <li><a href="oaicat-1.5.41.tar.gz">oaicat-1.5.41.tar.gz</a></li>
       <li><a href="oaicat-1.5.41.zip">oaicat-1.5.41.zip</a></li>
-      
+
       <li><a href="oaicat-1.5.40.tar.gz">oaicat-1.5.40.tar.gz</a></li>
       <li><a href="oaicat-1.5.40.zip">oaicat-1.5.40.zip</a></li>
-      
+
       <li><a href="oaicat-1.5.39.tar.gz">oaicat-1.5.39.tar.gz</a></li>
       <li><a href="oaicat-1.5.39.zip">oaicat-1.5.39.zip</a></li>
-      
+
       <li><a href="oaicat-1.5.38.tar.gz">oaicat-1.5.38.tar.gz</a></li>
       <li><a href="oaicat-1.5.38.zip">oaicat-1.5.38.zip</a></li>
-      
+
       <li><a href="oaicat-1.5.37.tar.gz">oaicat-1.5.37.tar.gz</a></li>
       <li><a href="oaicat-1.5.37.zip">oaicat-1.5.37.zip</a></li>
-      
+
       <li><a href="oaicat-1.5.36.tar.gz">oaicat-1.5.36.tar.gz</a></li>
       <li><a href="oaicat-1.5.36.zip">oaicat-1.5.36.zip</a></li>
-      
+
       <li><a href="oaicat-1.5.35.tar.gz">oaicat-1.5.35.tar.gz</a></li>
       <li><a href="oaicat-1.5.35.zip">oaicat-1.5.35.zip</a></li>
-      
+
       <li><a href="oaicat-1.5.34.tar.gz">oaicat-1.5.34.tar.gz</a></li>
       <li><a href="oaicat-1.5.34.zip">oaicat-1.5.34.zip</a></li>
-      
+
       <li><a href="oaicat-1.5.33.tar.gz">oaicat-1.5.33.tar.gz</a></li>
       <li><a href="oaicat-1.5.33.zip">oaicat-1.5.33.zip</a></li>
-      
+
       <li><a href="oaicat-1.5.32.tar.gz">oaicat-1.5.32.tar.gz</a></li>
       <li><a href="oaicat-1.5.32.zip">oaicat-1.5.32.zip</a></li>
-      
+
       <li><a href="oaicat-1.5.31.tar.gz">oaicat-1.5.31.tar.gz</a></li>
       <li><a href="oaicat-1.5.31.zip">oaicat-1.5.31.zip</a></li>
-      
+
       <li><a href="oaicat-1.5.30.tar.gz">oaicat-1.5.30.tar.gz</a></li>
       <li><a href="oaicat-1.5.30.zip">oaicat-1.5.30.zip</a></li>
-      
+
       <li><a href="oaicat-1.5.29.tar.gz">oaicat-1.5.29.tar.gz</a></li>
       <li><a href="oaicat-1.5.29.zip">oaicat-1.5.29.zip</a></li>
-      
+
       <li><a href="oaicat-1.5.28.tar.gz">oaicat-1.5.28.tar.gz</a></li>
       <li><a href="oaicat-1.5.28.zip">oaicat-1.5.28.zip</a></li>
-      
+
       <li><a href="oaicat-1.5.27.tar.gz">oaicat-1.5.27.tar.gz</a></li>
       <li><a href="oaicat-1.5.27.zip">oaicat-1.5.27.zip</a></li>
-      
+
       <li><a href="oaicat-1.5.26.tar.gz">oaicat-1.5.26.tar.gz</a></li>
       <li><a href="oaicat-1.5.26.zip">oaicat-1.5.26.zip</a></li>
-      
+
       <li><a href="oaicat-1.5.25.tar.gz">oaicat-1.5.25.tar.gz</a></li>
       <li><a href="oaicat-1.5.25.zip">oaicat-1.5.25.zip</a></li>
-      
+
       <li><a href="oaicat-1.5.24.tar.gz">oaicat-1.5.24.tar.gz</a></li>
       <li><a href="oaicat-1.5.24.zip">oaicat-1.5.24.zip</a></li>
-      
+
       <li><a href="oaicat-1.5.23.tar.gz">oaicat-1.5.23.tar.gz</a></li>
       <li><a href="oaicat-1.5.23.zip">oaicat-1.5.23.zip</a></li>
-      
+
       <li><a href="oaicat-1.5.22.tar.gz">oaicat-1.5.22.tar.gz</a></li>
       <li><a href="oaicat-1.5.22.zip">oaicat-1.5.22.zip</a></li>
-      
+
       <li><a href="oaicat-1.5.21.tar.gz">oaicat-1.5.21.tar.gz</a></li>
       <li><a href="oaicat-1.5.21.zip">oaicat-1.5.21.zip</a></li>
-      
+
       <li><a href="oaicat-1.5.20.tar.gz">oaicat-1.5.20.tar.gz</a></li>
       <li><a href="oaicat-1.5.20.zip">oaicat-1.5.20.zip</a></li>
-      
+
       <li><a href="oaicat-1.5.19.tar.gz">oaicat-1.5.19.tar.gz</a></li>
       <li><a href="oaicat-1.5.19.zip">oaicat-1.5.19.zip</a></li>
-      
+
       <li><a href="oaicat-1.5.18.tar.gz">oaicat-1.5.18.tar.gz</a></li>
       <li><a href="oaicat-1.5.18.zip">oaicat-1.5.18.zip</a></li>
-      
+
       <li><a href="oaicat-1.5.17.tar.gz">oaicat-1.5.17.tar.gz</a></li>
       <li><a href="oaicat-1.5.17.zip">oaicat-1.5.17.zip</a></li>
-      
+
       <li><a href="oaicat-1.5.16.tar.gz">oaicat-1.5.16.tar.gz</a></li>
       <li><a href="oaicat-1.5.16.zip">oaicat-1.5.16.zip</a></li>
       <li><a href="oaicat-1.5.15.tar.gz">oaicat-1.5.15.tar.gz</a></li>

programming_language: HTML
filename: version
change_type: ModificationType.MODIFY
diff: @@ -1,5 +1,9 @@
 OAICat version file. This file records major changes to the OAICat software.
 
+2013-10-18 1.5.62
+Bug fix:
+- Added a AbstractCatalog.paramRegex property to address an SQL injection vulnerability that was reported by Ward van Wanrooij. [https://code.google.com/p/oaicat/issues/detail?id=7]
+
 2013-04-18 1.5.61
 Enhancement:
 - change mechanism for locating the oaicat.properties configuration file.

programming_language: Markdown
filename: OAIHandler.java
change_type: ModificationType.MODIFY
diff: @@ -58,7 +58,7 @@ public class OAIHandler extends HttpServlet {
     
     public static final String PROPERTIES_SERVLET_CONTEXT_ATTRIBUTE = OAIHandler.class.getName() + ".properties";
     
-    private static final String VERSION = "1.5.61";
+    private static final String VERSION = "1.5.62";
     private static boolean debug = false;
 
 //    private Transformer transformer = null;

programming_language: Java
filename: AbstractCatalog.java
change_type: ModificationType.MODIFY
diff: @@ -47,22 +47,22 @@ public abstract class AbstractCatalog {
      * native "item" to the various metadataFormats to be supported.
      */
     private RecordFactory recordFactory;
-    
+
     /**
      * is this repository harvestable?
      */
     private boolean harvestable = true;
-    
+
     /**
      * optional property to limit the life of resumptionTokens (<0 indicates no limit)
      **/
     private int millisecondsToLive = -1;
-    
+
     /**
      * Index into VALID_GRANULARITIES and FROM_GRANULARITIES
      */
     private int supportedGranularityOffset = -1;
-    
+
     /**
      * All possible valid granularities
      */
@@ -70,7 +70,7 @@ public abstract class AbstractCatalog {
         "YYYY-MM-DD",
         "YYYY-MM-DDThh:mm:ssZ"
     };
-    
+
     /**
      * minimum valid 'from' granularities
      */
@@ -78,42 +78,51 @@ public abstract class AbstractCatalog {
         "0000-01-01",
         "0000-01-01T00:00:00Z"
     };
-    
+
+    /**
+     * Default regex pattern for validating parameters (can be overridden using an AbstractCatalog.paramRegex property
+     */
+    private String paramRegex = "^[a-zA-Z0-9\\.\\/\\:\\_\\-]*$";
+
     /**
      * return a handle to the RecordFactory
      * @return guess
      */
     public RecordFactory getRecordFactory() { return recordFactory; }
-    
+
     public void setHarvestable(boolean harvestable) {
         this.harvestable = harvestable;
     }
-    
+
+    public void setParamRegex(String s) {
+    	this.paramRegex = s;
+    }
+
     /**
      * Is this repository harvestable?
      * @return true if harvestable, false otherwise.
      */
     public boolean isHarvestable() { return harvestable; }
-    
+
     /**
      * get the optional millisecondsToLive property (<0 indicates no limit)
      **/
     public int getMillisecondsToLive() { return millisecondsToLive; }
-    
+
     public void setRecordFactory(RecordFactory recordFactory) {
         this.recordFactory = recordFactory;
     }
-    
+
     public void setSupportedGranularityOffset(int i) {
         supportedGranularityOffset = i;
     }
-    
+
     /**
      * Convert the requested 'from' parameter to the finest granularity supported
      * by this repository.
      * @exception BadArgumentException one or more of the arguments are bad.
      */
-    public String toFinestFrom(String from) 
+    public String toFinestFrom(String from)
     throws BadArgumentException {
         if (debug) {
             System.out.println("AbstractCatalog.toFinestFrom: from=" + from);
@@ -126,18 +135,18 @@ public abstract class AbstractCatalog {
             StringBuffer sb = new StringBuffer(from);
             if (sb.charAt(sb.length()-1) == 'Z')
                 sb.setLength(sb.length()-1);
-            
+
             sb.append(FROM_GRANULARITIES[supportedGranularityOffset].substring(sb.length()));
             from = sb.toString();
         }
-        
+
         if (!isValidGranularity(from)) {
             throw new BadArgumentException();
         }
-        
+
         return from;
     }
-    
+
     /**
      * Convert the requested 'until' paramter to the finest granularity supported
      * by this repository
@@ -153,11 +162,11 @@ public abstract class AbstractCatalog {
         if (until.length() > VALID_GRANULARITIES[supportedGranularityOffset].length()) {
             throw new BadArgumentException();
         }
-        
+
         StringBuffer sb = new StringBuffer(until);
         if (sb.charAt(sb.length()-1) == 'Z')
             sb.setLength(sb.length()-1);
-        
+
         if (sb.length() < VALID_GRANULARITIES[0].length()) {
             while (sb.length() < 4) sb.append("9");
             switch (sb.length()) {
@@ -170,20 +179,20 @@ public abstract class AbstractCatalog {
             case 8: // YYYY-MM-
                 sb.append("31");
                 break;
-                
+
             case 6: // YYYY-M
             case 9: // YYYY-MM-D
                 throw new BadArgumentException();
             }
         }
-        
+
         until = sb.toString();
         if (until.length() == VALID_GRANULARITIES[supportedGranularityOffset].length()) {
             if (!isValidGranularity(until))
                 throw new BadArgumentException();
             return until;
         }
-        
+
         if (sb.length() < VALID_GRANULARITIES[1].length()) {
             switch (sb.length()) {
             case 10: // YYYY-MM-DD
@@ -197,23 +206,23 @@ public abstract class AbstractCatalog {
 //              case 16: // YYYY-MM-DDThh:mm
 //              sb.append("Z");
 //              break;
-                
+
 //              case 12: // YYYY-MM-DDTh
 //              case 15: // YYYY-MM-DDThh:m
 //              throw new BadGranularityException();
 //              }
 //              }
-                
+
 //              until = sb.toString();
 //              if (until.length() == VALID_GRANULARITIES[supportedGranularityOffset].length()) {
 //              if (!isValidGranularity(until))
 //              throw new BadGranularityException();
 //              return until;
 //              }
-                
+
 //              if (sb.charAt(sb.length()-1) == 'Z')
 //              sb.setLength(sb.length()-1); // remove the trailing 'Z'
-                
+
 //              if (sb.length() < VALID_GRANULARITIES[2].length()) {
 //              switch (sb.length()) {
             case 16: // YYYY-MM-DDThh:mm
@@ -223,22 +232,22 @@ public abstract class AbstractCatalog {
             case 19: // YYYY-MM-DDThh:mm:ss
                 sb.append("Z");
                 break;
-                
+
             case 18: // YYYY-MM-DDThh:mm:s
                 throw new BadArgumentException();
             }
         }
-        
+
 //      until = sb.toString();
 //      if (until.length() == VALID_GRANULARITIES[supportedGranularityOffset].length()) {
 //      if (!isValidGranularity(until))
 //      throw new BadGranularityException();
 //      return until;
 //      }
-        
+
 //      if (sb.charAt(sb.length()-1) == 'Z')
 //      sb.setLength(sb.length()-1); // remove the trailing 'Z'
-        
+
 //      switch (sb.length()) {
 //      case 19: // YYYY-MM-DDThh:mm:ss
 //      sb.append(".");
@@ -248,13 +257,13 @@ public abstract class AbstractCatalog {
 //      sb.append("Z");
 //      break;
 //      }
-        
+
         until = sb.toString();
         if (!isValidGranularity(until))
             throw new BadArgumentException();
         return until;
     }
-    
+
     /**
      * Does the specified date conform to the supported granularity of this repository?
      * @param date a UTC date
@@ -264,7 +273,7 @@ public abstract class AbstractCatalog {
     private boolean isValidGranularity(String date) {
         if (date.length() > VALID_GRANULARITIES[supportedGranularityOffset].length())
             return false;
-        
+
         if (date.length() < VALID_GRANULARITIES[0].length()
                 || !Character.isDigit(date.charAt(0)) // YYYY
                 || !Character.isDigit(date.charAt(1))
@@ -278,7 +287,7 @@ public abstract class AbstractCatalog {
                         || !Character.isDigit(date.charAt(9))) {
             return false;
         }
-        
+
         if (date.length() > VALID_GRANULARITIES[0].length()) {
             if (date.charAt(10) != 'T'
                 || date.charAt(date.length()-1) != 'Z'
@@ -291,7 +300,7 @@ public abstract class AbstractCatalog {
 //                      return false;
 //                      }
 //                      }
-                        
+
 //                      if (date.length() > VALID_GRANULARITIES[1].length()) {
 //                      if (
                         || date.charAt(16) != ':'
@@ -300,17 +309,17 @@ public abstract class AbstractCatalog {
                 return false;
             }
         }
-        
+
 //      if (date.length() > VALID_GRANULARITIES[2].length()) {
 //      if (date.charAt(19) != '.'
 //      || !Character.isDigit(date.charAt(20))) { // s
 //      return false;
 //      }
-        
+
 //      }
         return true;
     }
-    
+
     /**
      * Retrieve the Crosswalks property
      *
@@ -318,28 +327,28 @@ public abstract class AbstractCatalog {
      * formats supported by this application.
      */
     public Crosswalks getCrosswalks() { return recordFactory.getCrosswalks(); }
-    
+
     /**
      * Retrieve the list of supported Sets. This should probably be initialized
      * by the constructor from the properties object that is passed to it.
      *
-     * @return a Map object containing <setSpec> values as the Map keys and 
+     * @return a Map object containing <setSpec> values as the Map keys and
      * <setName> values for the corresponding the Map values.
      * @exception NoSetHierarchyException No sets are defined for this repository
      * @exception OAIInternalServerError An error occurred
      */
     public abstract Map listSets() throws NoSetHierarchyException, OAIInternalServerError;
-    
+
     /**
      * Retrieve the next cluster of supported sets.
-     * @return a Map object containing <setSpec> values as the Map keys and 
+     * @return a Map object containing <setSpec> values as the Map keys and
      * <setName> values for the corresponding the Map values.
      * @exception BadResumptionTokenException The resumptionToken is bad.
      * @exception OAIInternalServerError An error occurred
      */
     public abstract Map listSets(String resumptionToken)
     throws BadResumptionTokenException, OAIInternalServerError;
-    
+
     /**
      * Factory method for creating an AbstractCatalog instance. The properties
      * object must contain the following entries:
@@ -429,16 +438,16 @@ public abstract class AbstractCatalog {
         }
         return oaiCatalog;
     }
-    
+
     /**
      * Allow the database to return some Identify &lt;description&gt; elements
-     * 
+     *
      * @return an XML String fragment containing description elements
      */
     public String getDescriptions() {
         return null;
     }
-    
+
     /**
      * Retrieve a list of schemaLocation values associated with the specified
      * identifier.
@@ -452,7 +461,7 @@ public abstract class AbstractCatalog {
      */
     public abstract Vector getSchemaLocations(String identifier)
     throws IdDoesNotExistException, NoMetadataFormatsException, OAIInternalServerError;
-    
+
     /**
      * Retrieve a list of Identifiers that satisfy the criteria parameters
      *
@@ -474,7 +483,7 @@ public abstract class AbstractCatalog {
     public abstract Map listIdentifiers(String from, String until, String set, String metadataPrefix)
     throws BadArgumentException, CannotDisseminateFormatException, NoItemsMatchException,
     NoSetHierarchyException, OAIInternalServerError;
-    
+
     /**
      * Retrieve the next set of Identifiers associated with the resumptionToken
      *
@@ -489,7 +498,7 @@ public abstract class AbstractCatalog {
      */
     public abstract Map listIdentifiers(String resumptionToken)
     throws BadResumptionTokenException, OAIInternalServerError;
-    
+
     /**
      * Retrieve the specified metadata for the specified identifier
      *
@@ -502,23 +511,23 @@ public abstract class AbstractCatalog {
      */
     public abstract String getRecord(String identifier, String metadataPrefix)
     throws IdDoesNotExistException, CannotDisseminateFormatException, OAIInternalServerError;
-    
+
     /**
      * Retrieve the specified metadata for the specified identifier
      *
      * @param identifier the OAI identifier
      * @return the String containing the result record.
      * @exception OAIInternalServerError signals an http status code 500 problem
-     * @throws CannotDisseminateFormatException 
-     * @throws IdDoesNotExistException 
-     * @throws IdDoesNotExistException 
+     * @throws CannotDisseminateFormatException
+     * @throws IdDoesNotExistException
+     * @throws IdDoesNotExistException
      */
     public String getMetadata(String identifier, String metadataPrefix)
     throws OAIInternalServerError, IdDoesNotExistException,
     IdDoesNotExistException, CannotDisseminateFormatException {
         throw new OAIInternalServerError("You need to override AbstractCatalog.getMetadata()");
     }
-    
+
     /**
      * Retrieve a list of records that satisfy the specified criteria
      *
@@ -545,10 +554,10 @@ public abstract class AbstractCatalog {
         Map listIdentifiersMap = listIdentifiers(from, until, set, metadataPrefix);
         String resumptionToken = (String)listIdentifiersMap.get("resumptionToken");
         Iterator identifiers = (Iterator)listIdentifiersMap.get("identifiers");
-        
+
         Map listRecordsMap = new HashMap();
         ArrayList records = new ArrayList();
-        
+
         while (identifiers.hasNext()) {
             String identifier = (String)identifiers.next();
             try {
@@ -564,7 +573,7 @@ public abstract class AbstractCatalog {
         }
         return listRecordsMap;
     }
-    
+
     /**
      * Retrieve the next set of records associated with the resumptionToken
      *
@@ -582,10 +591,10 @@ public abstract class AbstractCatalog {
         resumptionToken = (String)listIdentifiersMap.get("resumptionToken");
         Iterator identifiers = (Iterator)listIdentifiersMap.get("identifiers");
         String metadataPrefix = (String)listIdentifiersMap.get("metadataPrefix");
-        
+
         Map listRecordsMap = new HashMap();
         ArrayList records = new ArrayList();
-        
+
         while (identifiers.hasNext()) {
             String identifier = (String)identifiers.next();
             try {
@@ -604,11 +613,11 @@ public abstract class AbstractCatalog {
         }
         return listRecordsMap;
     }
-    
+
     public Map getResumptionMap(String resumptionToken) {
         return getResumptionMap(resumptionToken, -1, -1);
     }
-    
+
     public Map getResumptionMap(String resumptionToken, int completeListSize, int cursor) {
         Map resumptionMap = null;
         if (resumptionToken != null) {
@@ -628,9 +637,24 @@ public abstract class AbstractCatalog {
         }
         return resumptionMap;
     }
-    
+
     /**
      * close the repository
      */
     public abstract void close();
+
+    /**
+     * Validate the parameter value
+     * The default regex pattern can be overridden by setting a AbstractCatalog.paramRegex property
+     *
+     * @param key
+     * @param value
+     * @return true if the parameter is valid, false if not
+     */
+	public boolean isValidParam(String key, String value) {
+		if (paramRegex != null && paramRegex.length() > 0) {
+			return value.matches(paramRegex);
+		}
+		return true;
+	}
 }

programming_language: Java
filename: ExtendedJDBCOAICatalog.java
change_type: ModificationType.MODIFY
diff: @@ -48,40 +48,40 @@ import ORG.oclc.oai.util.OAIUtil;
  */
 public class ExtendedJDBCOAICatalog extends AbstractCatalog {
     private static final boolean debug = true;
-    
+
     /**
      * SQL identifier query (loaded from properties)
      * \\i -> localIdentifier, \\o -> oaiIdentifier
      */
     private String identifierQuery = null;
-    
+
     /**
      * SQL range query (loaded from properties)
      * \\f -> from, \\u -> until
      */
     private String rangeQuery = null;
-    
+
     /**
      * SQL range query (loaded from properties)
      * \\f -> from, \\u -> until, \\s -> set
      */
     private String rangeSetQuery = null;
-    
+
     /**
      * SQL query to get a list of available sets
      */
     private String setQuery = null;
-    
+
     /**
      * SQL query to get a list of available sets that apply to a particular identifier
      */
     private String setSpecQuery = null;
-    
+
     /**
      * SQL query to get a list of available abouts that apply to a particular identifier
      */
     private String aboutQuery = null;
-    
+
     /**
      * SQL column labels containing the values of particular interest
      */
@@ -90,19 +90,19 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
     private String setSpecListLabel = null;
     private String setNameLabel = null;
     private String setDescriptionLabel = null;
-    
+
     /**
      * maximum number of entries to return for ListRecords and ListIdentifiers
      * (loaded from properties)
      */
     private int maxListSize;
-    
+
     /**
      * Set Strings to be loaded from the properties file
      * (if they are to be loaded from properties rather than queried from the database)
      */
     ArrayList sets = new ArrayList();
-    
+
     /**
      * The JDBC Connection
      */
@@ -111,12 +111,12 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
     private String jdbcURL = null;
     private String jdbcLogin = null;
     private String jdbcPasswd = null;
-    
+
     /**
      * pending resumption tokens
      */
     private HashMap resumptionResults = new HashMap();
-    
+
     /**
      * Construct a ExtendedJDBCOAICatalog object
      *
@@ -130,7 +130,11 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
         } else {
             this.maxListSize = Integer.parseInt(maxListSize);
         }
-        
+
+        String paramRegex = properties.getProperty("AbstractCatalog.paramRegex");
+        if (paramRegex != null) {
+            setParamRegex(paramRegex);
+        }
         String jdbcDriverName = properties.getProperty("ExtendedJDBCOAICatalog.jdbcDriverName");
         if (jdbcDriverName == null) {
             throw new IllegalArgumentException("ExtendedJDBCOAICatalog.jdbcDriverName is missing from the properties file");
@@ -139,32 +143,32 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
         if (jdbcURL == null) {
             throw new IllegalArgumentException("ExtendedJDBCOAICatalog.jdbcURL is missing from the properties file");
         }
-        
+
         jdbcLogin = properties.getProperty("ExtendedJDBCOAICatalog.jdbcLogin");
         if (jdbcLogin == null) {
             throw new IllegalArgumentException("ExtendedJDBCOAICatalog.jdbcLogin is missing from the properties file");
         }
-        
+
         jdbcPasswd = properties.getProperty("ExtendedJDBCOAICatalog.jdbcPasswd");
         if (jdbcPasswd == null) {
             throw new IllegalArgumentException("ExtendedJDBCOAICatalog.jdbcPasswd is missing from the properties file");
         }
-        
+
         rangeQuery = properties.getProperty("ExtendedJDBCOAICatalog.rangeQuery");
         if (rangeQuery == null) {
             throw new IllegalArgumentException("ExtendedJDBCOAICatalog.rangeQuery is missing from the properties file");
         }
-        
+
         rangeSetQuery = properties.getProperty("ExtendedJDBCOAICatalog.rangeSetQuery");
         if (rangeSetQuery == null) {
             throw new IllegalArgumentException("ExtendedJDBCOAICatalog.rangeSetQuery is missing from the properties file");
         }
-        
+
         identifierQuery = properties.getProperty("ExtendedJDBCOAICatalog.identifierQuery");
         if (identifierQuery == null) {
             throw new IllegalArgumentException("ExtendedJDBCOAICatalog.identifierQuery is missing from the properties file");
         }
-        
+
         aboutQuery = properties.getProperty("ExtendedJDBCOAICatalog.aboutQuery");
         if (aboutQuery != null) {
             aboutValueLabel = properties.getProperty("ExtendedJDBCOAICatalog.aboutValueLabel");
@@ -172,7 +176,7 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
                 throw new IllegalArgumentException("ExtendedJDBCOAICatalog.aboutValueLabel is missing from the properties file");
             }
         }
-        
+
         setSpecQuery = properties.getProperty("ExtendedJDBCOAICatalog.setSpecQuery");
         setSpecItemLabel = properties.getProperty("ExtendedJDBCOAICatalog.setSpecItemLabel");
         if (setSpecItemLabel == null) {
@@ -190,7 +194,7 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
 //      if (setDescriptionLabel == null) {
 //      throw new IllegalArgumentException("ExtendedJDBCOAICatalog.setDescriptionLabel is missing from the properties file");
 //      }
-        
+
         // See if a setQuery exists
         setQuery = properties.getProperty("ExtendedJDBCOAICatalog.setQuery");
         if (setQuery == null) {
@@ -204,11 +208,11 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
                 }
             }
         }
-        
+
         String temp = properties.getProperty("ExtendedJDBCOAICatalog.isPersistentConnection");
         if ("false".equalsIgnoreCase(temp))
             isPersistentConnection = false;
-        
+
         // open the connection
         try {
             Class.forName(jdbcDriverName);
@@ -216,7 +220,7 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
             throw new IllegalArgumentException("ExtendedJDBCOAICatalog.jdbcDriverName is invalid: "
                     + jdbcDriverName);
         }
-        
+
         if (isPersistentConnection) {
             try {
                 persistentConnection = getNewConnection();
@@ -226,12 +230,12 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
             }
         }
     }
-    
+
     private Connection getNewConnection() throws SQLException {
         // open the connection
         return DriverManager.getConnection(jdbcURL, jdbcLogin, jdbcPasswd);
     }
-    
+
     private Connection startConnection() throws SQLException {
         if (persistentConnection != null) {
             if (persistentConnection.isClosed())
@@ -241,7 +245,7 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
             return getNewConnection();
         }
     }
-    
+
     private void endConnection(Connection con) throws OAIInternalServerError {
         try {
             if (persistentConnection == null)
@@ -250,7 +254,7 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
             throw new OAIInternalServerError(e.getMessage());
         }
     }
-    
+
     /**
      * Retrieve a list of schemaLocation values associated with the specified
      * oaiIdentifier.
@@ -298,7 +302,7 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
             throw new OAIInternalServerError(e.getMessage());
         }
     }
-    
+
     /**
      * Get remainder of the nativeItem. By default, it is assumed
      * the entire nativeItem is produced by the default query.
@@ -308,7 +312,7 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
      */
     protected void extendItem(Connection con, HashMap nativeItem) {
     }
-    
+
     /**
      * Since the columns should only be read once, copy them into a
      * HashMap and consider that to be the "record"
@@ -335,7 +339,7 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
         }
         return tableItems;
     }
-    
+
     /**
      * insert actual from, until, and set parameters into the rangeQuery String
      * NOTE! This retrieves an extra record so we can decide if EOF has been reached.
@@ -353,12 +357,12 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
             tokenizer = new StringTokenizer(rangeQuery, "\\");
         else
             tokenizer = new StringTokenizer(rangeSetQuery, "\\");
-        
+
         if (tokenizer.hasMoreTokens())
             sb.append(tokenizer.nextToken());
         else
             throw new OAIInternalServerError("Invalid query");
-        
+
         while (tokenizer.hasMoreTokens()) {
             String token = tokenizer.nextToken();
             switch (token.charAt(0)) {
@@ -387,25 +391,25 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
         if (debug) System.out.println(sb.toString());
         return sb.toString();
     }
-    
+
     /**
      * Extend this class and override this method if necessary.
      */
     protected String formatFromDate(String date) {
         return formatDate(date);
     }
-    
+
     /**
      * Extend this class and override this method if necessary.
      */
     protected String formatUntilDate(String date) {
         return formatDate(date);
     }
-    
+
     /**
      * Change the String from UTC to SQL format
      * If this method doesn't suit your needs, extend this class and override
-     * the method rather than change this code directly. 
+     * the method rather than change this code directly.
      */
     protected String formatDate(String date) {
         StringBuffer sb = new StringBuffer();
@@ -417,7 +421,7 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
         if (debug) System.out.println("ExtendedJDBCOAICatalog.formatDate: from " + date + " to " + sb.toString());
         return sb.toString();
     }
-    
+
     /**
      * insert actual from, until, and set parameters into the identifierQuery String
      *
@@ -434,7 +438,7 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
             sb.append(tokenizer.nextToken());
         else
             throw new OAIInternalServerError("Invalid identifierQuery");
-        
+
         while (tokenizer.hasMoreTokens()) {
             String token = tokenizer.nextToken();
             switch (token.charAt(0)) {
@@ -453,7 +457,7 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
         if (debug) System.out.println(sb.toString());
         return sb.toString();
     }
-    
+
     /**
      * insert actual from, until, and set parameters into the identifierQuery String
      *
@@ -470,7 +474,7 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
             sb.append(tokenizer.nextToken());
         else
             throw new OAIInternalServerError("Invalid identifierQuery");
-        
+
         while (tokenizer.hasMoreTokens()) {
             String token = tokenizer.nextToken();
             switch (token.charAt(0)) {
@@ -489,7 +493,7 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
         if (debug) System.out.println(sb.toString());
         return sb.toString();
     }
-    
+
     /**
      * insert actual from, until, and set parameters into the identifierQuery String
      *
@@ -506,7 +510,7 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
             sb.append(tokenizer.nextToken());
         else
             throw new OAIInternalServerError("Invalid identifierQuery");
-        
+
         while (tokenizer.hasMoreTokens()) {
             String token = tokenizer.nextToken();
             switch (token.charAt(0)) {
@@ -525,7 +529,7 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
         if (debug) System.out.println(sb.toString());
         return sb.toString();
     }
-    
+
     /**
      * Retrieve a list of identifiers that satisfy the specified criteria
      *
@@ -553,7 +557,7 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
         ArrayList headers = new ArrayList();
         ArrayList identifiers = new ArrayList();
         Connection con = null;
-        
+
         try {
             con = startConnection();
             /* Get some records from your database */
@@ -563,7 +567,7 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
 //          int numRows = rs.getRow();
 //          rs.beforeFirst();
             int count;
-            
+
             /* load the headers and identifiers ArrayLists. */
             for (count=0; count < maxListSize && rs.next(); ++count) {
                 HashMap nativeItem = new HashMap();
@@ -575,19 +579,19 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
                 headers.add(header[0]);
                 identifiers.add(header[1]);
             }
-            
+
             if (count == 0) {
                 stmt.close();
                 endConnection(con);
                 throw new NoItemsMatchException();
             }
-            
+
             /* decide if you're done */
 //          if (count == maxListSize) {
             if (rs.next()) {
 //              String resumptionId = getResumptionId();
 //              resumptionResults.put(resumptionId, rs);
-                
+
                 /*****************************************************************
                  * Construct the resumptionToken String however you see fit.
                  *****************************************************************/
@@ -606,7 +610,7 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
                 resumptionTokenSb.append(Integer.toString(count));
                 resumptionTokenSb.append("!");
                 resumptionTokenSb.append(metadataPrefix);
-                
+
                 /*****************************************************************
                  * Use the following line if you wish to include the optional
                  * resumptionToken attributes in the response. Otherwise, use the
@@ -631,12 +635,12 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
             e.printStackTrace();
             throw new OAIInternalServerError(e.getMessage());
         }
-        
+
         listIdentifiersMap.put("headers", headers.iterator());
         listIdentifiersMap.put("identifiers", identifiers.iterator());
         return listIdentifiersMap;
     }
-    
+
     /**
      * Retrieve the next set of identifiers associated with the resumptionToken
      *
@@ -654,7 +658,7 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
         Map listIdentifiersMap = new HashMap();
         ArrayList headers = new ArrayList();
         ArrayList identifiers = new ArrayList();
-        
+
         /****************************
          * parse your resumptionToken
          ****************************/
@@ -683,7 +687,7 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
         } catch (NoSuchElementException e) {
             throw new BadResumptionTokenException();
         }
-        
+
         Connection con = null;
         try {
             con = startConnection();
@@ -692,7 +696,7 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
             ResultSet rs = stmt.executeQuery(populateRangeQuery(from, until, set,
                     oldCount, maxListSize));
             int count;
-            
+
             /* load the headers and identifiers ArrayLists. */
             for (count = 0; count < maxListSize && rs.next(); ++count) {
                 HashMap nativeItem = new HashMap();
@@ -703,7 +707,7 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
                 headers.add(header[0]);
                 identifiers.add(header[1]);
             }
-            
+
             /* decide if you're done. */
 //          if (count == maxListSize) {
             if (rs.next()) {
@@ -725,7 +729,7 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
                 resumptionTokenSb.append(Integer.toString(oldCount + count));
                 resumptionTokenSb.append("!");
                 resumptionTokenSb.append(metadataPrefix);
-                
+
                 /*****************************************************************
                  * Use the following line if you wish to include the optional
                  * resumptionToken attributes in the response. Otherwise, use the
@@ -750,12 +754,12 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
             e.printStackTrace();
             throw new OAIInternalServerError(e.getMessage());
         }
-        
+
         listIdentifiersMap.put("headers", headers.iterator());
         listIdentifiersMap.put("identifiers", identifiers.iterator());
         return listIdentifiersMap;
     }
-    
+
     /**
      * Retrieve the specified metadata for the specified oaiIdentifier
      *
@@ -793,7 +797,7 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
             throw new OAIInternalServerError(e.getMessage());
         }
     }
-    
+
     /**
      * Retrieve a list of records that satisfy the specified criteria. Note, though,
      * that unlike the other OAI verb type methods implemented here, both of the
@@ -821,7 +825,7 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
         Map listRecordsMap = new HashMap();
         ArrayList records = new ArrayList();
         Connection con = null;
-        
+
         try {
             con = startConnection();
             /* Get some records from your database */
@@ -832,9 +836,9 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
 //          int numRows = rs.getRow();
 //          rs.beforeFirst();
             int count;
-            
+
 //          if (debug) System.out.println("ExtendedJDBCOAICatalog.listRecords: numRows=" + numRows);
-            
+
             /* load the records ArrayList */
             for (count=0; count < maxListSize && rs.next(); ++count) {
                 HashMap nativeItem = new HashMap();
@@ -843,18 +847,18 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
                 String record = constructRecord(nativeItem, metadataPrefix);
                 records.add(record);
             }
-            
+
             if (count == 0) {
                 endConnection(con);
                 throw new NoItemsMatchException();
             }
-            
+
             /* decide if you're done */
 //          if (count == maxListSize) {
             if (rs.next()) {
 //              String resumptionId = getResumptionId();
 //              resumptionResults.put(resumptionId, rs);
-                
+
                 /*****************************************************************
                  * Construct the resumptionToken String however you see fit.
                  *****************************************************************/
@@ -875,7 +879,7 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
 //              resumptionTokenSb.append(Integer.toString(numRows));
 //              resumptionTokenSb.append("!");
                 resumptionTokenSb.append(metadataPrefix);
-                
+
                 /*****************************************************************
                  * Use the following line if you wish to include the optional
                  * resumptionToken attributes in the response. Otherwise, use the
@@ -900,11 +904,11 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
             e.printStackTrace();
             throw new OAIInternalServerError(e.getMessage());
         }
-        
+
         listRecordsMap.put("records", records.iterator());
         return listRecordsMap;
     }
-    
+
     /**
      * Retrieve the next set of records associated with the resumptionToken
      *
@@ -921,7 +925,7 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
         Map listRecordsMap = new HashMap();
         ArrayList records = new ArrayList();
 //      purge(); // clean out old resumptionTokens
-        
+
         /****************************
          * parse your resumptionToken
          ****************************/
@@ -946,7 +950,7 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
         } catch (NoSuchElementException e) {
             throw new BadResumptionTokenException();
         }
-        
+
         Connection con = null;
         try {
             con = startConnection();
@@ -954,9 +958,9 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
             Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
             ResultSet rs = stmt.executeQuery(populateRangeQuery(from, until, set,
                     oldCount, maxListSize));
-            
+
             int count;
-            
+
             /* load the headers and identifiers ArrayLists. */
             for (count = 0; count < maxListSize && rs.next(); ++count) {
                 try {
@@ -971,7 +975,7 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
                     throw new BadResumptionTokenException();
                 }
             }
-            
+
             /* decide if you're done */
 //          if (count == maxListSize) {
             if (rs.next()) {
@@ -995,7 +999,7 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
 //              resumptionTokenSb.append(Integer.toString(numRows));
 //              resumptionTokenSb.append("!");
                 resumptionTokenSb.append(metadataPrefix);
-                
+
                 /*****************************************************************
                  * Use the following line if you wish to include the optional
                  * resumptionToken attributes in the response. Otherwise, use the
@@ -1020,11 +1024,11 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
             e.printStackTrace();
             throw new OAIInternalServerError(e.getMessage());
         }
-        
+
         listRecordsMap.put("records", records.iterator());
         return listRecordsMap;
     }
-    
+
     /**
      * Utility method to construct a Record object for a specified
      * metadataFormat from a native record
@@ -1040,14 +1044,14 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
         String schemaURL = null;
         Iterator setSpecs = getSetSpecs(nativeItem);
         Iterator abouts = getAbouts(nativeItem);
-        
+
         if (metadataPrefix != null) {
             if ((schemaURL = getCrosswalks().getSchemaURL(metadataPrefix)) == null)
                 throw new CannotDisseminateFormatException(metadataPrefix);
         }
         return getRecordFactory().create(nativeItem, schemaURL, metadataPrefix, setSpecs, abouts);
     }
-    
+
     /**
      * Retrieve a list of sets that satisfy the specified criteria
      *
@@ -1067,11 +1071,11 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
             purge(); // clean out old resumptionTokens
             Map listSetsMap = new HashMap();
             ArrayList sets = new ArrayList();
-            
+
             Connection con = null;
             try {
                 if (debug) System.out.println(setQuery);
-                
+
                 con = startConnection();
                 /* Get some records from your database */
                 Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
@@ -1080,9 +1084,9 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
                 int numRows = rs.getRow();
                 rs.beforeFirst();
                 int count;
-                
+
 //              if (debug) System.out.println("ExtendedJDBCOAICatalog.listSets: numRows=" + numRows);
-                
+
                 /* load the sets ArrayLists. */
                 for (count=0; count < maxListSize && rs.next(); ++count) {
                     /* Use the RecordFactory to extract header/set pairs for each item */
@@ -1090,12 +1094,12 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
                     sets.add(getSetXML(nativeItem));
                     if (debug) System.out.println("ExtendedJDBCOAICatalog.listSets: adding an entry");
                 }
-                
+
                 /* decide if you're done */
                 if (count < numRows) {
                     String resumptionId = getResumptionId();
                     resumptionResults.put(resumptionId, rs);
-                    
+
                     /*****************************************************************
                      * Construct the resumptionToken String however you see fit.
                      *****************************************************************/
@@ -1105,7 +1109,7 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
                     resumptionTokenSb.append(Integer.toString(count));
                     resumptionTokenSb.append("!");
                     resumptionTokenSb.append(Integer.toString(numRows));
-                    
+
                     /*****************************************************************
                      * Use the following line if you wish to include the optional
                      * resumptionToken attributes in the response. Otherwise, use the
@@ -1125,12 +1129,12 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
                 e.printStackTrace();
                 throw new OAIInternalServerError(e.getMessage());
             }
-            
+
             listSetsMap.put("sets", sets.iterator());
             return listSetsMap;
         }
     }
-    
+
     /**
      * Retrieve the next set of sets associated with the resumptionToken
      *
@@ -1150,7 +1154,7 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
             purge(); // clean out old resumptionTokens
             Map listSetsMap = new HashMap();
             ArrayList sets = new ArrayList();
-            
+
             /****************************
              * parse your resumptionToken
              ****************************/
@@ -1165,28 +1169,28 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
             } catch (NoSuchElementException e) {
                 throw new BadResumptionTokenException();
             }
-            
+
             try {
                 /* Get some more records from your database */
                 ResultSet rs = (ResultSet)resumptionResults.get(resumptionId);
                 if (rs == null) {
                     throw new BadResumptionTokenException();
                 }
-                
+
                 if (rs.getRow() != oldCount) {
 //                  System.out.println("ExtendedJDBCOAICatalog.listIdentifiers: reuse of old resumptionToken?");
                     rs.absolute(oldCount);
                 }
-                
+
                 int count;
-                
+
                 /* load the sets ArrayLists. */
                 for (count = 0; count < maxListSize && rs.next(); ++count) {
                     HashMap nativeItem = getColumnValues(rs);
                     /* Use the RecordFactory to extract set for each item */
                     sets.add(getSetXML(nativeItem));
                 }
-                
+
                 /* decide if you're done. */
                 if (oldCount+count < numRows) {
                     /*****************************************************************
@@ -1198,7 +1202,7 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
                     resumptionTokenSb.append(Integer.toString(oldCount + count));
                     resumptionTokenSb.append("!");
                     resumptionTokenSb.append(Integer.toString(numRows));
-                    
+
                     /*****************************************************************
                      * Use the following line if you wish to include the optional
                      * resumptionToken attributes in the response. Otherwise, use the
@@ -1214,12 +1218,12 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
                 e.printStackTrace();
                 throw new OAIInternalServerError(e.getMessage());
             }
-            
+
             listSetsMap.put("sets", sets.iterator());
             return listSetsMap;
         }
     }
-    
+
     /**
      * get an Iterator containing the setSpecs for the nativeItem
      *
@@ -1252,7 +1256,7 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
             throw new OAIInternalServerError(e.getMessage());
         }
     }
-    
+
     /**
      * get an Iterator containing the abouts for the nativeItem
      *
@@ -1285,7 +1289,7 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
             throw new OAIInternalServerError(e.getMessage());
         }
     }
-    
+
     /**
      * Extract &lt;set&gt; XML string from setItem object
      *
@@ -1298,7 +1302,7 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
         String setSpec = getSetSpec(setItem);
         String setName = getSetName(setItem);
         String setDescription = getSetDescription(setItem);
-        
+
         StringBuffer sb = new StringBuffer();
         sb.append("<set>");
         sb.append("<setSpec>");
@@ -1319,7 +1323,7 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
 //      throw new IllegalArgumentException(e.getMessage());
 //      }
     }
-    
+
     /**
      * get the setSpec XML string. Extend this class and override this method
      * if the setSpec can't be directly taken from the result set as a String
@@ -1335,7 +1339,7 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
             return "UnsupportedEncodingException";
         }
     }
-    
+
     /**
      * get the setName XML string. Extend this class and override this method
      * if the setName can't be directly taken from the result set as a String
@@ -1346,7 +1350,7 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
     protected String getSetName(HashMap setItem) {
         return (String)setItem.get(setNameLabel);
     }
-    
+
     /**
      * get the setDescription XML string. Extend this class and override this method
      * if the setDescription can't be directly taken from the result set as a String
@@ -1359,7 +1363,7 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
             return null;
         return (String)setItem.get(setDescriptionLabel);
     }
-    
+
     /**
      * close the repository
      */
@@ -1372,7 +1376,7 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
         }
         persistentConnection = null;
     }
-    
+
     /**
      * Purge tokens that are older than the configured time-to-live.
      */
@@ -1393,7 +1397,7 @@ public class ExtendedJDBCOAICatalog extends AbstractCatalog {
             resumptionResults.remove(key);
         }
     }
-    
+
     /**
      * Use the current date as the basis for the resumptiontoken
      *

programming_language: Java
filename: JDBCLimitedOAICatalog.java
change_type: ModificationType.MODIFY
diff: @@ -49,40 +49,40 @@ import ORG.oclc.oai.util.OAIUtil;
  */
 public class JDBCLimitedOAICatalog extends AbstractCatalog {
     private static final boolean debug = false;
-    
+
     /**
      * SQL identifier query (loaded from properties)
      * \\i -> localIdentifier, \\o -> oaiIdentifier
      */
     private String identifierQuery = null;
-    
+
     /**
      * SQL range query (loaded from properties)
      * \\f -> from, \\u -> until
      */
     private String rangeQuery = null;
-    
+
     /**
      * SQL range query (loaded from properties)
      * \\f -> from, \\u -> until, \\s -> set
      */
     private String rangeSetQuery = null;
-    
+
     /**
      * SQL query to get a list of available sets
      */
     private String setQuery = null;
-    
+
     /**
      * SQL query to get a list of available sets that apply to a particular identifier
      */
     private String setSpecQuery = null;
-    
+
     /**
      * SQL query to get a list of available abouts that apply to a particular identifier
      */
     private String aboutQuery = null;
-    
+
     /**
      * SQL column labels containing the values of particular interest
      */
@@ -91,26 +91,26 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
     private String setSpecListLabel = null;
     private String setNameLabel = null;
     private String setDescriptionLabel = null;
-    
+
     /**
      * maximum number of entries to return for ListRecords and ListIdentifiers
      * (loaded from properties)
      */
     private int maxListSize;
-    
+
     /**
      * The format required for dates in SQL queries
      * "UTC" = YYYY-MM-DD or YYYY-MM-DDTHH:MM:SSZ
      * other = YYYY/MM/DD
      */
     private String dateFormat = null;
-    
+
     /**
      * Set Strings to be loaded from the properties file
      * (if they are to be loaded from properties rather than queried from the database)
      */
     ArrayList sets = new ArrayList();
-    
+
     /**
      * The JDBC Connection
      */
@@ -119,12 +119,12 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
     private String jdbcURL = null;
     private String jdbcLogin = null;
     private String jdbcPasswd = null;
-    
+
     /**
      * pending resumption tokens
      */
     private HashMap resumptionResults = new HashMap();
-    
+
     /**
      * Construct a JDBCLimitedOAICatalog object
      *
@@ -139,7 +139,11 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
         } else {
             this.maxListSize = Integer.parseInt(maxListSize);
         }
-        
+
+        String paramRegex = properties.getProperty("AbstractCatalog.paramRegex");
+        if (paramRegex != null) {
+            setParamRegex(paramRegex);
+        }
         String jdbcDriverName = properties.getProperty("JDBCLimitedOAICatalog.jdbcDriverName");
         if (jdbcDriverName == null) {
             throw new IllegalArgumentException("JDBCLimitedOAICatalog.jdbcDriverName is missing from the properties file");
@@ -148,32 +152,32 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
         if (jdbcURL == null) {
             throw new IllegalArgumentException("JDBCLimitedOAICatalog.jdbcURL is missing from the properties file");
         }
-        
+
         jdbcLogin = properties.getProperty("JDBCLimitedOAICatalog.jdbcLogin");
         if (jdbcLogin == null) {
             throw new IllegalArgumentException("JDBCLimitedOAICatalog.jdbcLogin is missing from the properties file");
         }
-        
+
         jdbcPasswd = properties.getProperty("JDBCLimitedOAICatalog.jdbcPasswd");
         if (jdbcPasswd == null) {
             throw new IllegalArgumentException("JDBCLimitedOAICatalog.jdbcPasswd is missing from the properties file");
         }
-        
+
         rangeQuery = properties.getProperty("JDBCLimitedOAICatalog.rangeQuery");
         if (rangeQuery == null) {
             throw new IllegalArgumentException("JDBCLimitedOAICatalog.rangeQuery is missing from the properties file");
         }
-        
+
         rangeSetQuery = properties.getProperty("JDBCLimitedOAICatalog.rangeSetQuery");
         if (rangeSetQuery == null) {
             throw new IllegalArgumentException("JDBCLimitedOAICatalog.rangeSetQuery is missing from the properties file");
         }
-        
+
         identifierQuery = properties.getProperty("JDBCLimitedOAICatalog.identifierQuery");
         if (identifierQuery == null) {
             throw new IllegalArgumentException("JDBCLimitedOAICatalog.identifierQuery is missing from the properties file");
         }
-        
+
         aboutQuery = properties.getProperty("JDBCLimitedOAICatalog.aboutQuery");
         if (aboutQuery != null) {
             aboutValueLabel = properties.getProperty("JDBCLimitedOAICatalog.aboutValueLabel");
@@ -181,7 +185,7 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
                 throw new IllegalArgumentException("JDBCLimitedOAICatalog.aboutValueLabel is missing from the properties file");
             }
         }
-        
+
         setSpecQuery = properties.getProperty("JDBCLimitedOAICatalog.setSpecQuery");
         setSpecItemLabel = properties.getProperty("JDBCLimitedOAICatalog.setSpecItemLabel");
         if (setSpecQuery != null && setSpecItemLabel == null) {
@@ -191,7 +195,7 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
 //      if (setDescriptionLabel == null) {
 //      throw new IllegalArgumentException("JDBCLimitedOAICatalog.setDescriptionLabel is missing from the properties file");
 //      }
-        
+
         // See if a setQuery exists
         setQuery = properties.getProperty("JDBCLimitedOAICatalog.setQuery");
         if (setQuery == null) {
@@ -214,11 +218,11 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
                 throw new IllegalArgumentException("JDBCLimitedOAICatalog.setNameLabel is missing from the properties file");
             }
         }
-        
+
         String temp = properties.getProperty("JDBCLimitedOAICatalog.isPersistentConnection");
         if ("false".equalsIgnoreCase(temp))
             isPersistentConnection = false;
-        
+
         // open the connection
         try {
             Class.forName(jdbcDriverName);
@@ -226,7 +230,7 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
             throw new IllegalArgumentException("JDBCLimitedOAICatalog.jdbcDriverName is invalid: "
                     + jdbcDriverName);
         }
-        
+
         if (isPersistentConnection) {
             try {
                 persistentConnection = getNewConnection();
@@ -236,12 +240,12 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
             }
         }
     }
-    
+
     private Connection getNewConnection() throws SQLException {
         // open the connection
         return DriverManager.getConnection(jdbcURL, jdbcLogin, jdbcPasswd);
     }
-    
+
     private Connection startConnection() throws SQLException {
         if (persistentConnection != null) {
             if (persistentConnection.isClosed())
@@ -251,7 +255,7 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
             return getNewConnection();
         }
     }
-    
+
     private void endConnection(Connection con) throws OAIInternalServerError {
         try {
             if (persistentConnection == null)
@@ -260,7 +264,7 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
             throw new OAIInternalServerError(e.getMessage());
         }
     }
-    
+
     /**
      * Retrieve a list of schemaLocation values associated with the specified
      * oaiIdentifier.
@@ -305,7 +309,7 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
             throw new OAIInternalServerError(e.getMessage());
         }
     }
-    
+
     /**
      * Since the columns should only be read once, copy them into a
      * HashMap and consider that to be the "record"
@@ -332,7 +336,7 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
         }
         return nativeItem;
     }
-    
+
     /**
      * insert actual from, until, and set parameters into the rangeQuery String
      * NOTE! This retrieves an extra record so we can decide if EOF has been reached.
@@ -350,12 +354,12 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
             tokenizer = new StringTokenizer(rangeQuery, "\\");
         else
             tokenizer = new StringTokenizer(rangeSetQuery, "\\");
-        
+
         if (tokenizer.hasMoreTokens())
             sb.append(tokenizer.nextToken());
         else
             throw new OAIInternalServerError("Invalid query");
-        
+
         while (tokenizer.hasMoreTokens()) {
             String token = tokenizer.nextToken();
             switch (token.charAt(0)) {
@@ -384,25 +388,25 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
         if (debug) System.out.println(sb.toString());
         return sb.toString();
     }
-    
+
     /**
      * Extend this class and override this method if necessary.
      */
     protected String formatFromDate(String date) {
         return formatDate(date);
     }
-    
+
     /**
      * Extend this class and override this method if necessary.
      */
     protected String formatUntilDate(String date) {
         return formatDate(date);
     }
-    
+
     /**
      * Change the String from UTC to SQL format
      * If this method doesn't suit your needs, extend this class and override
-     * the method rather than change this code directly. 
+     * the method rather than change this code directly.
      */
     protected String formatDate(String date) {
         if ("UTC".equals(dateFormat)) {
@@ -418,7 +422,7 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
             return sb.toString();
         }
     }
-    
+
     /**
      * insert actual from, until, and set parameters into the identifierQuery String
      *
@@ -435,7 +439,7 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
             sb.append(tokenizer.nextToken());
         else
             throw new OAIInternalServerError("Invalid identifierQuery");
-        
+
         while (tokenizer.hasMoreTokens()) {
             String token = tokenizer.nextToken();
             switch (token.charAt(0)) {
@@ -454,7 +458,7 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
         if (debug) System.out.println(sb.toString());
         return sb.toString();
     }
-    
+
     /**
      * insert actual from, until, and set parameters into the identifierQuery String
      *
@@ -471,7 +475,7 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
             sb.append(tokenizer.nextToken());
         else
             throw new OAIInternalServerError("Invalid identifierQuery");
-        
+
         while (tokenizer.hasMoreTokens()) {
             String token = tokenizer.nextToken();
             switch (token.charAt(0)) {
@@ -490,7 +494,7 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
         if (debug) System.out.println(sb.toString());
         return sb.toString();
     }
-    
+
     /**
      * insert actual from, until, and set parameters into the identifierQuery String
      *
@@ -507,7 +511,7 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
             sb.append(tokenizer.nextToken());
         else
             throw new OAIInternalServerError("Invalid identifierQuery");
-        
+
         while (tokenizer.hasMoreTokens()) {
             String token = tokenizer.nextToken();
             switch (token.charAt(0)) {
@@ -526,7 +530,7 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
         if (debug) System.out.println(sb.toString());
         return sb.toString();
     }
-    
+
     /**
      * Retrieve a list of identifiers that satisfy the specified criteria
      *
@@ -554,7 +558,7 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
         ArrayList headers = new ArrayList();
         ArrayList identifiers = new ArrayList();
         Connection con = null;
-        
+
         try {
             con = startConnection();
             /* Get some records from your database */
@@ -564,7 +568,7 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
 //          int numRows = rs.getRow();
 //          rs.beforeFirst();
             int count;
-            
+
             /* load the headers and identifiers ArrayLists. */
             for (count=0; count < maxListSize && rs.next(); ++count) {
                 HashMap nativeItem = getColumnValues(rs);
@@ -575,18 +579,18 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
                 headers.add(header[0]);
                 identifiers.add(header[1]);
             }
-            
+
             if (count == 0) {
                 endConnection(con);
                 throw new NoItemsMatchException();
             }
-            
+
             /* decide if you're done */
 //          if (count == maxListSize) {
             if (rs.next()) {
 //              String resumptionId = getResumptionId();
 //              resumptionResults.put(resumptionId, rs);
-                
+
                 /*****************************************************************
                  * Construct the resumptionToken String however you see fit.
                  *****************************************************************/
@@ -605,7 +609,7 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
                 resumptionTokenSb.append(Integer.toString(count));
                 resumptionTokenSb.append(":");
                 resumptionTokenSb.append(metadataPrefix);
-                
+
                 /*****************************************************************
                  * Use the following line if you wish to include the optional
                  * resumptionToken attributes in the response. Otherwise, use the
@@ -629,12 +633,12 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
             e.printStackTrace();
             throw new OAIInternalServerError(e.getMessage());
         }
-        
+
         listIdentifiersMap.put("headers", headers.iterator());
         listIdentifiersMap.put("identifiers", identifiers.iterator());
         return listIdentifiersMap;
     }
-    
+
     /**
      * Retrieve the next set of identifiers associated with the resumptionToken
      *
@@ -652,7 +656,7 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
         Map listIdentifiersMap = new HashMap();
         ArrayList headers = new ArrayList();
         ArrayList identifiers = new ArrayList();
-        
+
         /****************************
          * parse your resumptionToken
          ****************************/
@@ -681,7 +685,7 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
         } catch (NoSuchElementException e) {
             throw new BadResumptionTokenException();
         }
-        
+
         Connection con = null;
         try {
             con = startConnection();
@@ -690,7 +694,7 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
             ResultSet rs = stmt.executeQuery(populateRangeQuery(from, until, set,
                     oldCount, maxListSize));
             int count;
-            
+
             /* load the headers and identifiers ArrayLists. */
             for (count = 0; count < maxListSize && rs.next(); ++count) {
                 HashMap nativeItem = getColumnValues(rs);
@@ -700,7 +704,7 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
                 headers.add(header[0]);
                 identifiers.add(header[1]);
             }
-            
+
             /* decide if you're done. */
 //          if (count == maxListSize) {
             if (rs.next()) {
@@ -722,7 +726,7 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
                 resumptionTokenSb.append(Integer.toString(oldCount + count));
                 resumptionTokenSb.append(":");
                 resumptionTokenSb.append(metadataPrefix);
-                
+
                 /*****************************************************************
                  * Use the following line if you wish to include the optional
                  * resumptionToken attributes in the response. Otherwise, use the
@@ -746,12 +750,12 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
             e.printStackTrace();
             throw new OAIInternalServerError(e.getMessage());
         }
-        
+
         listIdentifiersMap.put("headers", headers.iterator());
         listIdentifiersMap.put("identifiers", identifiers.iterator());
         return listIdentifiersMap;
     }
-    
+
     /**
      * Retrieve the specified metadata for the specified oaiIdentifier
      *
@@ -786,7 +790,7 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
             throw new OAIInternalServerError(e.getMessage());
         }
     }
-    
+
     /**
      * Retrieve a list of records that satisfy the specified criteria. Note, though,
      * that unlike the other OAI verb type methods implemented here, both of the
@@ -814,7 +818,7 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
         Map listRecordsMap = new HashMap();
         ArrayList records = new ArrayList();
         Connection con = null;
-        
+
         try {
             con = startConnection();
             /* Get some records from your database */
@@ -825,27 +829,27 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
 //          int numRows = rs.getRow();
 //          rs.beforeFirst();
             int count;
-            
+
 //          if (debug) System.out.println("JDBCLimitedOAICatalog.listRecords: numRows=" + numRows);
-            
+
             /* load the records ArrayList */
             for (count=0; count < maxListSize && rs.next(); ++count) {
                 HashMap nativeItem = getColumnValues(rs);
                 String record = constructRecord(nativeItem, metadataPrefix);
                 records.add(record);
             }
-            
+
             if (count == 0) {
                 endConnection(con);
                 throw new NoItemsMatchException();
             }
-            
+
             /* decide if you're done */
 //          if (count == maxListSize) {
             if (rs.next()) {
 //              String resumptionId = getResumptionId();
 //              resumptionResults.put(resumptionId, rs);
-                
+
                 /*****************************************************************
                  * Construct the resumptionToken String however you see fit.
                  *****************************************************************/
@@ -866,7 +870,7 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
 //              resumptionTokenSb.append(Integer.toString(numRows));
 //              resumptionTokenSb.append(":");
                 resumptionTokenSb.append(metadataPrefix);
-                
+
                 /*****************************************************************
                  * Use the following line if you wish to include the optional
                  * resumptionToken attributes in the response. Otherwise, use the
@@ -890,11 +894,11 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
             e.printStackTrace();
             throw new OAIInternalServerError(e.getMessage());
         }
-        
+
         listRecordsMap.put("records", records.iterator());
         return listRecordsMap;
     }
-    
+
     /**
      * Retrieve the next set of records associated with the resumptionToken
      *
@@ -911,7 +915,7 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
         Map listRecordsMap = new HashMap();
         ArrayList records = new ArrayList();
 //      purge(); // clean out old resumptionTokens
-        
+
         /****************************
          * parse your resumptionToken
          ****************************/
@@ -936,7 +940,7 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
         } catch (NoSuchElementException e) {
             throw new BadResumptionTokenException();
         }
-        
+
         Connection con = null;
         try {
             con = startConnection();
@@ -944,9 +948,9 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
             Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
             ResultSet rs = stmt.executeQuery(populateRangeQuery(from, until, set,
                     oldCount, maxListSize));
-            
+
             int count;
-            
+
             /* load the headers and identifiers ArrayLists. */
             for (count = 0; count < maxListSize && rs.next(); ++count) {
                 try {
@@ -959,7 +963,7 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
                     throw new BadResumptionTokenException();
                 }
             }
-            
+
             /* decide if you're done */
 //          if (count == maxListSize) {
             if (rs.next()) {
@@ -983,7 +987,7 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
 //              resumptionTokenSb.append(Integer.toString(numRows));
 //              resumptionTokenSb.append(":");
                 resumptionTokenSb.append(metadataPrefix);
-                
+
                 /*****************************************************************
                  * Use the following line if you wish to include the optional
                  * resumptionToken attributes in the response. Otherwise, use the
@@ -1007,11 +1011,11 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
             e.printStackTrace();
             throw new OAIInternalServerError(e.getMessage());
         }
-        
+
         listRecordsMap.put("records", records.iterator());
         return listRecordsMap;
     }
-    
+
     /**
      * Utility method to construct a Record object for a specified
      * metadataFormat from a native record
@@ -1027,14 +1031,14 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
         String schemaURL = null;
         Iterator setSpecs = getSetSpecs(nativeItem);
         Iterator abouts = getAbouts(nativeItem);
-        
+
         if (metadataPrefix != null) {
             if ((schemaURL = getCrosswalks().getSchemaURL(metadataPrefix)) == null)
                 throw new CannotDisseminateFormatException(metadataPrefix);
         }
         return getRecordFactory().create(nativeItem, schemaURL, metadataPrefix, setSpecs, abouts);
     }
-    
+
     /**
      * Retrieve a list of sets that satisfy the specified criteria
      *
@@ -1054,11 +1058,11 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
             purge(); // clean out old resumptionTokens
             Map listSetsMap = new HashMap();
             ArrayList sets = new ArrayList();
-            
+
             Connection con = null;
             try {
                 if (debug) System.out.println(setQuery);
-                
+
                 con = startConnection();
                 /* Get some records from your database */
                 Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
@@ -1067,9 +1071,9 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
                 int numRows = rs.getRow();
                 rs.beforeFirst();
                 int count;
-                
+
 //              if (debug) System.out.println("JDBCLimitedOAICatalog.listSets: numRows=" + numRows);
-                
+
                 /* load the sets ArrayLists. */
                 for (count=0; count < maxListSize && rs.next(); ++count) {
                     /* Use the RecordFactory to extract header/set pairs for each item */
@@ -1077,12 +1081,12 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
                     sets.add(getSetXML(nativeItem));
                     if (debug) System.out.println("JDBCLimitedOAICatalog.listSets: adding an entry");
                 }
-                
+
                 /* decide if you're done */
                 if (count < numRows) {
                     String resumptionId = getResumptionId();
                     resumptionResults.put(resumptionId, rs);
-                    
+
                     /*****************************************************************
                      * Construct the resumptionToken String however you see fit.
                      *****************************************************************/
@@ -1092,7 +1096,7 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
                     resumptionTokenSb.append(Integer.toString(count));
                     resumptionTokenSb.append(":");
                     resumptionTokenSb.append(Integer.toString(numRows));
-                    
+
                     /*****************************************************************
                      * Use the following line if you wish to include the optional
                      * resumptionToken attributes in the response. Otherwise, use the
@@ -1111,12 +1115,12 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
                 e.printStackTrace();
                 throw new OAIInternalServerError(e.getMessage());
             }
-            
+
             listSetsMap.put("sets", sets.iterator());
             return listSetsMap;
         }
     }
-    
+
     /**
      * Retrieve the next set of sets associated with the resumptionToken
      *
@@ -1136,7 +1140,7 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
             purge(); // clean out old resumptionTokens
             Map listSetsMap = new HashMap();
             ArrayList sets = new ArrayList();
-            
+
             /****************************
              * parse your resumptionToken
              ****************************/
@@ -1151,28 +1155,28 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
             } catch (NoSuchElementException e) {
                 throw new BadResumptionTokenException();
             }
-            
+
             try {
                 /* Get some more records from your database */
                 ResultSet rs = (ResultSet)resumptionResults.get(resumptionId);
                 if (rs == null) {
                     throw new BadResumptionTokenException();
                 }
-                
+
                 if (rs.getRow() != oldCount) {
 //                  System.out.println("JDBCLimitedOAICatalog.listIdentifiers: reuse of old resumptionToken?");
                     rs.absolute(oldCount);
                 }
-                
+
                 int count;
-                
+
                 /* load the sets ArrayLists. */
                 for (count = 0; count < maxListSize && rs.next(); ++count) {
                     HashMap nativeItem = getColumnValues(rs);
                     /* Use the RecordFactory to extract set for each item */
                     sets.add(getSetXML(nativeItem));
                 }
-                
+
                 /* decide if you're done. */
                 if (oldCount+count < numRows) {
                     /*****************************************************************
@@ -1184,7 +1188,7 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
                     resumptionTokenSb.append(Integer.toString(oldCount + count));
                     resumptionTokenSb.append(":");
                     resumptionTokenSb.append(Integer.toString(numRows));
-                    
+
                     /*****************************************************************
                      * Use the following line if you wish to include the optional
                      * resumptionToken attributes in the response. Otherwise, use the
@@ -1200,12 +1204,12 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
                 e.printStackTrace();
                 throw new OAIInternalServerError(e.getMessage());
             }
-            
+
             listSetsMap.put("sets", sets.iterator());
             return listSetsMap;
         }
     }
-    
+
     /**
      * get an Iterator containing the setSpecs for the nativeItem
      *
@@ -1237,7 +1241,7 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
             throw new OAIInternalServerError(e.getMessage());
         }
     }
-    
+
     /**
      * get an Iterator containing the abouts for the nativeItem
      *
@@ -1269,7 +1273,7 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
             throw new OAIInternalServerError(e.getMessage());
         }
     }
-    
+
     /**
      * Extract &lt;set&gt; XML string from setItem object
      *
@@ -1282,7 +1286,7 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
         String setSpec = getSetSpec(setItem);
         String setName = getSetName(setItem);
         String setDescription = getSetDescription(setItem);
-        
+
         StringBuffer sb = new StringBuffer();
         sb.append("<set>");
         sb.append("<setSpec>");
@@ -1303,7 +1307,7 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
 //      throw new IllegalArgumentException(e.getMessage());
 //      }
     }
-    
+
     /**
      * get the setSpec XML string. Extend this class and override this method
      * if the setSpec can't be directly taken from the result set as a String
@@ -1319,7 +1323,7 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
             return "UnsupportedEncodingException";
         }
     }
-    
+
     /**
      * get the setName XML string. Extend this class and override this method
      * if the setName can't be directly taken from the result set as a String
@@ -1330,7 +1334,7 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
     protected String getSetName(HashMap setItem) {
         return (String)setItem.get(setNameLabel);
     }
-    
+
     /**
      * get the setDescription XML string. Extend this class and override this method
      * if the setDescription can't be directly taken from the result set as a String
@@ -1343,7 +1347,7 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
             return null;
         return (String)setItem.get(setDescriptionLabel);
     }
-    
+
     /**
      * close the repository
      */
@@ -1356,7 +1360,7 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
         }
         persistentConnection = null;
     }
-    
+
     /**
      * Purge tokens that are older than the configured time-to-live.
      */
@@ -1377,7 +1381,7 @@ public class JDBCLimitedOAICatalog extends AbstractCatalog {
             resumptionResults.remove(key);
         }
     }
-    
+
     /**
      * Use the current date as the basis for the resumptiontoken
      *

programming_language: Java
filename: JDBCOAICatalog.java
change_type: ModificationType.MODIFY
diff: @@ -50,40 +50,40 @@ import ORG.oclc.oai.util.OAIUtil;
  */
 public class JDBCOAICatalog extends AbstractCatalog {
     private static final boolean debug = false;
-    
+
     /**
      * SQL identifier query (loaded from properties)
      * \\i -> localIdentifier, \\o -> oaiIdentifier
      */
     private String identifierQuery = null;
-    
+
     /**
      * SQL range query (loaded from properties)
      * \\f -> from, \\u -> until
      */
     private String rangeQuery = null;
-    
+
     /**
      * SQL range query (loaded from properties)
      * \\f -> from, \\u -> until, \\s -> set
      */
     private String rangeSetQuery = null;
-    
+
     /**
      * SQL query to get a list of available sets
      */
     private String setQuery = null;
-    
+
     /**
      * SQL query to get a list of available sets that apply to a particular identifier
      */
     private String setSpecQuery = null;
-    
+
     /**
      * SQL query to get a list of available abouts that apply to a particular identifier
      */
     private String aboutQuery = null;
-    
+
     /**
      * SQL column labels containing the values of particular interest
      */
@@ -92,36 +92,36 @@ public class JDBCOAICatalog extends AbstractCatalog {
     private String setSpecListLabel = null;
     private String setNameLabel = null;
     private String setDescriptionLabel = null;
-    
+
     /**
      * maximum number of entries to return for ListRecords and ListIdentifiers
      * (loaded from properties)
      */
     private int maxListSize;
-    
+
     /**
      * The format required for dates in SQL queries
      * "UTC" = YYYY-MM-DD or YYYY-MM-DDTHH:MM:SSZ
      * other = YYYY/MM/DD
      */
     private String dateFormat = null;
-    
+
     /**
      * Set Strings to be loaded from the properties file
      * (if they are to be loaded from properties rather than queried from the database)
      */
     ArrayList sets = new ArrayList();
-    
+
     /**
      * Assume the connection will be persistent unless configured otherwise
      */
     private boolean isPersistentConnection = true;
-    
+
     /**
      * The JDBC Connection
      */
     private Connection persistentConnection = null;
-    
+
     /**
      * pending resumption tokens
      */
@@ -129,7 +129,7 @@ public class JDBCOAICatalog extends AbstractCatalog {
     private String jdbcURL = null;
     private String jdbcLogin = null;
     private String jdbcPasswd = null;
-    
+
     /**
      * Construct a JDBCOAICatalog object
      *
@@ -144,7 +144,11 @@ public class JDBCOAICatalog extends AbstractCatalog {
         } else {
             this.maxListSize = Integer.parseInt(maxListSize);
         }
-        
+
+        String paramRegex = properties.getProperty("AbstractCatalog.paramRegex");
+        if (paramRegex != null) {
+            setParamRegex(paramRegex);
+        }
         String jdbcDriverName = properties.getProperty("JDBCOAICatalog.jdbcDriverName");
         if (jdbcDriverName == null) {
             throw new IllegalArgumentException("JDBCOAICatalog.jdbcDriverName is missing from the properties file");
@@ -153,32 +157,32 @@ public class JDBCOAICatalog extends AbstractCatalog {
         if (jdbcURL == null) {
             throw new IllegalArgumentException("JDBCOAICatalog.jdbcURL is missing from the properties file");
         }
-        
+
         jdbcLogin = properties.getProperty("JDBCOAICatalog.jdbcLogin");
         if (jdbcLogin == null) {
             throw new IllegalArgumentException("JDBCOAICatalog.jdbcLogin is missing from the properties file");
         }
-        
+
         jdbcPasswd = properties.getProperty("JDBCOAICatalog.jdbcPasswd");
         if (jdbcPasswd == null) {
             throw new IllegalArgumentException("JDBCOAICatalog.jdbcPasswd is missing from the properties file");
         }
-        
+
         rangeQuery = properties.getProperty("JDBCOAICatalog.rangeQuery");
         if (rangeQuery == null) {
             throw new IllegalArgumentException("JDBCOAICatalog.rangeQuery is missing from the properties file");
         }
-        
+
         rangeSetQuery = properties.getProperty("JDBCOAICatalog.rangeSetQuery");
         if (rangeSetQuery == null) {
             throw new IllegalArgumentException("JDBCOAICatalog.rangeSetQuery is missing from the properties file");
         }
-        
+
         identifierQuery = properties.getProperty("JDBCOAICatalog.identifierQuery");
         if (identifierQuery == null) {
             throw new IllegalArgumentException("JDBCOAICatalog.identifierQuery is missing from the properties file");
         }
-        
+
         aboutQuery = properties.getProperty("JDBCOAICatalog.aboutQuery");
         if (aboutQuery != null) {
             aboutValueLabel = properties.getProperty("JDBCOAICatalog.aboutValueLabel");
@@ -186,7 +190,7 @@ public class JDBCOAICatalog extends AbstractCatalog {
                 throw new IllegalArgumentException("JDBCOAICatalog.aboutValueLabel is missing from the properties file");
             }
         }
-        
+
         setSpecQuery = properties.getProperty("JDBCOAICatalog.setSpecQuery");
         setSpecItemLabel = properties.getProperty("JDBCOAICatalog.setSpecItemLabel");
         if (setSpecItemLabel == null) {
@@ -200,17 +204,17 @@ public class JDBCOAICatalog extends AbstractCatalog {
         if (setNameLabel == null) {
             throw new IllegalArgumentException("JDBCOAICatalog.setNameLabel is missing from the properties file");
         }
-        
+
         String temp = properties.getProperty("JDBCOAICatalog.isPersistentConnection");
         if ("false".equalsIgnoreCase(temp)) {
             isPersistentConnection = false;
         }
-        
+
         setDescriptionLabel = properties.getProperty("JDBCOAICatalog.setDescriptionLabel");
 //      if (setDescriptionLabel == null) {
 //      throw new IllegalArgumentException("JDBCOAICatalog.setDescriptionLabel is missing from the properties file");
 //      }
-        
+
         // See if a setQuery exists
         setQuery = properties.getProperty("JDBCOAICatalog.setQuery");
         if (setQuery == null) {
@@ -224,14 +228,14 @@ public class JDBCOAICatalog extends AbstractCatalog {
                 }
             }
         }
-        
+
         try {
             Class.forName(jdbcDriverName);
         } catch (ClassNotFoundException e) {
             throw new IllegalArgumentException("JDBCOAICatalog.jdbcDriverName is invalid: "
                     + jdbcDriverName);
         }
-        
+
         if (isPersistentConnection) {
             try {
                 persistentConnection = getNewConnection();
@@ -241,12 +245,12 @@ public class JDBCOAICatalog extends AbstractCatalog {
             }
         }
     }
-    
+
     private Connection getNewConnection() throws SQLException {
         // open the connection
         return DriverManager.getConnection(jdbcURL, jdbcLogin, jdbcPasswd);
     }
-    
+
     private Connection startConnection() throws SQLException {
         if (persistentConnection != null) {
             if (persistentConnection.isClosed()) {
@@ -258,7 +262,7 @@ public class JDBCOAICatalog extends AbstractCatalog {
             return getNewConnection();
         }
     }
-    
+
     private void endConnection(Connection con) throws OAIInternalServerError {
         if (persistentConnection == null) {
             try {
@@ -269,7 +273,7 @@ public class JDBCOAICatalog extends AbstractCatalog {
             }
         }
     }
-    
+
     /**
      * Retrieve a list of schemaLocation values associated with the specified
      * oaiIdentifier.
@@ -314,7 +318,7 @@ public class JDBCOAICatalog extends AbstractCatalog {
             throw new OAIInternalServerError(e.getMessage());
         }
     }
-    
+
     /**
      * Since the columns should only be read once, copy them into a
      * HashMap and consider that to be the "record"
@@ -341,7 +345,7 @@ public class JDBCOAICatalog extends AbstractCatalog {
         }
         return nativeItem;
     }
-    
+
     /**
      * insert actual from, until, and set parameters into the rangeQuery String
      *
@@ -358,12 +362,12 @@ public class JDBCOAICatalog extends AbstractCatalog {
             tokenizer = new StringTokenizer(rangeQuery, "\\");
         else
             tokenizer = new StringTokenizer(rangeSetQuery, "\\");
-        
+
         if (tokenizer.hasMoreTokens())
             sb.append(tokenizer.nextToken());
         else
             throw new OAIInternalServerError("Invalid query");
-        
+
         while (tokenizer.hasMoreTokens()) {
             String token = tokenizer.nextToken();
             switch (token.charAt(0)) {
@@ -385,25 +389,25 @@ public class JDBCOAICatalog extends AbstractCatalog {
         if (debug) System.out.println(sb.toString());
         return sb.toString();
     }
-    
+
     /**
      * Extend this class and override this method if necessary.
      */
     protected String formatFromDate(String date) {
         return formatDate(date);
     }
-    
+
     /**
      * Extend this class and override this method if necessary.
      */
     protected String formatUntilDate(String date) {
         return formatDate(date);
     }
-    
+
     /**
      * Change the String from UTC to SQL format
      * If this method doesn't suit your needs, extend this class and override
-     * the method rather than change this code directly. 
+     * the method rather than change this code directly.
      */
     protected String formatDate(String date) {
         if ("UTC".equals(dateFormat)) {
@@ -419,7 +423,7 @@ public class JDBCOAICatalog extends AbstractCatalog {
             return sb.toString();
         }
     }
-    
+
     /**
      * insert actual from, until, and set parameters into the identifierQuery String
      *
@@ -436,7 +440,7 @@ public class JDBCOAICatalog extends AbstractCatalog {
             sb.append(tokenizer.nextToken());
         else
             throw new OAIInternalServerError("Invalid identifierQuery");
-        
+
         while (tokenizer.hasMoreTokens()) {
             String token = tokenizer.nextToken();
             switch (token.charAt(0)) {
@@ -455,7 +459,7 @@ public class JDBCOAICatalog extends AbstractCatalog {
         if (debug) System.out.println(sb.toString());
         return sb.toString();
     }
-    
+
     /**
      * insert actual from, until, and set parameters into the identifierQuery String
      *
@@ -472,7 +476,7 @@ public class JDBCOAICatalog extends AbstractCatalog {
             sb.append(tokenizer.nextToken());
         else
             throw new OAIInternalServerError("Invalid identifierQuery");
-        
+
         while (tokenizer.hasMoreTokens()) {
             String token = tokenizer.nextToken();
             switch (token.charAt(0)) {
@@ -491,7 +495,7 @@ public class JDBCOAICatalog extends AbstractCatalog {
         if (debug) System.out.println(sb.toString());
         return sb.toString();
     }
-    
+
     /**
      * insert actual from, until, and set parameters into the identifierQuery String
      *
@@ -508,7 +512,7 @@ public class JDBCOAICatalog extends AbstractCatalog {
             sb.append(tokenizer.nextToken());
         else
             throw new OAIInternalServerError("Invalid identifierQuery");
-        
+
         while (tokenizer.hasMoreTokens()) {
             String token = tokenizer.nextToken();
             switch (token.charAt(0)) {
@@ -527,7 +531,7 @@ public class JDBCOAICatalog extends AbstractCatalog {
         if (debug) System.out.println(sb.toString());
         return sb.toString();
     }
-    
+
     /**
      * Retrieve a list of identifiers that satisfy the specified criteria
      *
@@ -555,7 +559,7 @@ public class JDBCOAICatalog extends AbstractCatalog {
         ArrayList headers = new ArrayList();
         ArrayList identifiers = new ArrayList();
         Connection con = null;
-        
+
         try {
             con = startConnection();
             /* Get some records from your database */
@@ -569,7 +573,7 @@ public class JDBCOAICatalog extends AbstractCatalog {
             }
             rs.beforeFirst();
             int count;
-            
+
             /* load the headers and identifiers ArrayLists. */
             for (count=0; count < maxListSize && rs.next(); ++count) {
                 HashMap nativeItem = getColumnValues(rs);
@@ -580,12 +584,12 @@ public class JDBCOAICatalog extends AbstractCatalog {
                 headers.add(header[0]);
                 identifiers.add(header[1]);
             }
-            
+
             /* decide if you're done */
             if (count < numRows) {
                 String resumptionId = getResumptionId();
                 resumptionResults.put(resumptionId, rs);
-                
+
                 /*****************************************************************
                  * Construct the resumptionToken String however you see fit.
                  *****************************************************************/
@@ -597,7 +601,7 @@ public class JDBCOAICatalog extends AbstractCatalog {
                 resumptionTokenSb.append(Integer.toString(numRows));
                 resumptionTokenSb.append("!");
                 resumptionTokenSb.append(metadataPrefix);
-                
+
                 /*****************************************************************
                  * Use the following line if you wish to include the optional
                  * resumptionToken attributes in the response. Otherwise, use the
@@ -616,12 +620,12 @@ public class JDBCOAICatalog extends AbstractCatalog {
             e.printStackTrace();
             throw new OAIInternalServerError(e.getMessage());
         }
-        
+
         listIdentifiersMap.put("headers", headers.iterator());
         listIdentifiersMap.put("identifiers", identifiers.iterator());
         return listIdentifiersMap;
     }
-    
+
     /**
      * Retrieve the next set of identifiers associated with the resumptionToken
      *
@@ -639,7 +643,7 @@ public class JDBCOAICatalog extends AbstractCatalog {
         Map listIdentifiersMap = new HashMap();
         ArrayList headers = new ArrayList();
         ArrayList identifiers = new ArrayList();
-        
+
         /**********************************************************************
          * parse your resumptionToken and look it up in the resumptionResults,
          * if necessary
@@ -657,7 +661,7 @@ public class JDBCOAICatalog extends AbstractCatalog {
         } catch (NoSuchElementException e) {
             throw new BadResumptionTokenException();
         }
-        
+
         try {
             /* Get some more records from your database */
             ResultSet rs = (ResultSet)resumptionResults.get(resumptionId);
@@ -665,12 +669,12 @@ public class JDBCOAICatalog extends AbstractCatalog {
                 throw new BadResumptionTokenException();
             }
             int count;
-            
+
             if (rs.getRow() != oldCount) {
 //              System.out.println("JDBCOAICatalog.listIdentifiers: reuse of old resumptionToken?");
                 rs.absolute(oldCount);
             }
-            
+
             /* load the headers and identifiers ArrayLists. */
             for (count = 0; count < maxListSize && rs.next(); ++count) {
                 HashMap nativeItem = getColumnValues(rs);
@@ -680,7 +684,7 @@ public class JDBCOAICatalog extends AbstractCatalog {
                 headers.add(header[0]);
                 identifiers.add(header[1]);
             }
-            
+
             /* decide if you're done. */
             if (oldCount+count < numRows) {
                 /*****************************************************************
@@ -694,7 +698,7 @@ public class JDBCOAICatalog extends AbstractCatalog {
                 resumptionTokenSb.append(Integer.toString(numRows));
                 resumptionTokenSb.append("!");
                 resumptionTokenSb.append(metadataPrefix);
-                
+
                 /*****************************************************************
                  * Use the following line if you wish to include the optional
                  * resumptionToken attributes in the response. Otherwise, use the
@@ -710,12 +714,12 @@ public class JDBCOAICatalog extends AbstractCatalog {
             e.printStackTrace();
             throw new OAIInternalServerError(e.getMessage());
         }
-        
+
         listIdentifiersMap.put("headers", headers.iterator());
         listIdentifiersMap.put("identifiers", identifiers.iterator());
         return listIdentifiersMap;
     }
-    
+
     /**
      * Retrieve the specified metadata for the specified oaiIdentifier
      *
@@ -750,7 +754,7 @@ public class JDBCOAICatalog extends AbstractCatalog {
             throw new OAIInternalServerError(e.getMessage());
         }
     }
-    
+
     /**
      * Retrieve a list of records that satisfy the specified criteria. Note, though,
      * that unlike the other OAI verb type methods implemented here, both of the
@@ -778,7 +782,7 @@ public class JDBCOAICatalog extends AbstractCatalog {
         Map listRecordsMap = new HashMap();
         ArrayList records = new ArrayList();
         Connection con = null;
-        
+
         try {
             con = startConnection();
             /* Get some records from your database */
@@ -793,21 +797,21 @@ public class JDBCOAICatalog extends AbstractCatalog {
             }
             rs.beforeFirst();
             int count;
-            
+
 //          if (debug) System.out.println("JDBCOAICatalog.listRecords: numRows=" + numRows);
-            
+
             /* load the records ArrayList */
             for (count=0; count < maxListSize && rs.next(); ++count) {
                 HashMap nativeItem = getColumnValues(rs);
                 String record = constructRecord(nativeItem, metadataPrefix);
                 records.add(record);
             }
-            
+
             /* decide if you're done */
             if (count < numRows) {
                 String resumptionId = getResumptionId();
                 resumptionResults.put(resumptionId, rs);
-                
+
                 /*****************************************************************
                  * Construct the resumptionToken String however you see fit.
                  *****************************************************************/
@@ -819,7 +823,7 @@ public class JDBCOAICatalog extends AbstractCatalog {
                 resumptionTokenSb.append(Integer.toString(numRows));
                 resumptionTokenSb.append("!");
                 resumptionTokenSb.append(metadataPrefix);
-                
+
                 /*****************************************************************
                  * Use the following line if you wish to include the optional
                  * resumptionToken attributes in the response. Otherwise, use the
@@ -838,11 +842,11 @@ public class JDBCOAICatalog extends AbstractCatalog {
             e.printStackTrace();
             throw new OAIInternalServerError(e.getMessage());
         }
-        
+
         listRecordsMap.put("records", records.iterator());
         return listRecordsMap;
     }
-    
+
     /**
      * Retrieve the next set of records associated with the resumptionToken
      *
@@ -859,7 +863,7 @@ public class JDBCOAICatalog extends AbstractCatalog {
         Map listRecordsMap = new HashMap();
         ArrayList records = new ArrayList();
         purge(); // clean out old resumptionTokens
-        
+
         /**********************************************************************
          * parse your resumptionToken and look it up in the resumptionResults,
          * if necessary
@@ -877,21 +881,21 @@ public class JDBCOAICatalog extends AbstractCatalog {
         } catch (NoSuchElementException e) {
             throw new BadResumptionTokenException();
         }
-        
+
         try {
             /* Get some more records from your database */
             ResultSet rs = (ResultSet)resumptionResults.get(resumptionId);
             if (rs == null) {
                 throw new BadResumptionTokenException();
             }
-            
+
             if (rs.getRow() != oldCount) {
 //              System.out.println("JDBCOAICatalog.listIdentifiers: reuse of old resumptionToken?");
                 rs.absolute(oldCount);
             }
-            
+
             int count;
-            
+
             /* load the headers and identifiers ArrayLists. */
             for (count = 0; count < maxListSize && rs.next(); ++count) {
                 try {
@@ -903,7 +907,7 @@ public class JDBCOAICatalog extends AbstractCatalog {
                     throw new BadResumptionTokenException();
                 }
             }
-            
+
             /* decide if you're done */
             if (oldCount+count < numRows) {
                 /*****************************************************************
@@ -917,7 +921,7 @@ public class JDBCOAICatalog extends AbstractCatalog {
                 resumptionTokenSb.append(Integer.toString(numRows));
                 resumptionTokenSb.append("!");
                 resumptionTokenSb.append(metadataPrefix);
-                
+
                 /*****************************************************************
                  * Use the following line if you wish to include the optional
                  * resumptionToken attributes in the response. Otherwise, use the
@@ -933,11 +937,11 @@ public class JDBCOAICatalog extends AbstractCatalog {
             e.printStackTrace();
             throw new OAIInternalServerError(e.getMessage());
         }
-        
+
         listRecordsMap.put("records", records.iterator());
         return listRecordsMap;
     }
-    
+
     /**
      * Utility method to construct a Record object for a specified
      * metadataFormat from a native record
@@ -953,14 +957,14 @@ public class JDBCOAICatalog extends AbstractCatalog {
         String schemaURL = null;
         Iterator setSpecs = getSetSpecs(nativeItem);
         Iterator abouts = getAbouts(nativeItem);
-        
+
         if (metadataPrefix != null) {
             if ((schemaURL = getCrosswalks().getSchemaURL(metadataPrefix)) == null)
                 throw new CannotDisseminateFormatException(metadataPrefix);
         }
         return getRecordFactory().create(nativeItem, schemaURL, metadataPrefix, setSpecs, abouts);
     }
-    
+
     /**
      * Retrieve a list of sets that satisfy the specified criteria
      *
@@ -981,11 +985,11 @@ public class JDBCOAICatalog extends AbstractCatalog {
             purge(); // clean out old resumptionTokens
             Map listSetsMap = new HashMap();
             ArrayList sets = new ArrayList();
-            
+
             try {
                 con = startConnection();
                 if (debug) System.out.println(setQuery);
-                
+
                 /* Get some records from your database */
                 Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
                 ResultSet rs = stmt.executeQuery(setQuery);
@@ -993,9 +997,9 @@ public class JDBCOAICatalog extends AbstractCatalog {
                 int numRows = rs.getRow();
                 rs.beforeFirst();
                 int count;
-                
+
 //              if (debug) System.out.println("JDBCOAICatalog.listSets: numRows=" + numRows);
-                
+
                 /* load the sets ArrayLists. */
                 for (count=0; count < maxListSize && rs.next(); ++count) {
                     /* Use the RecordFactory to extract header/set pairs for each item */
@@ -1003,7 +1007,7 @@ public class JDBCOAICatalog extends AbstractCatalog {
                     sets.add(getSetXML(nativeItem));
                     if (debug) System.out.println("JDBCOAICatalog.listSets: adding an entry");
                 }
-                
+
                 /* decide if you're done */
                 if (count < numRows) {
                     String resumptionId = getResumptionId();
@@ -1012,7 +1016,7 @@ public class JDBCOAICatalog extends AbstractCatalog {
                      * means the token can't be reused.
                      *****************************************************************/
                     resumptionResults.put(resumptionId, rs);
-                    
+
                     /*****************************************************************
                      * Construct the resumptionToken String however you see fit.
                      *****************************************************************/
@@ -1022,7 +1026,7 @@ public class JDBCOAICatalog extends AbstractCatalog {
                     resumptionTokenSb.append(Integer.toString(count));
                     resumptionTokenSb.append("!");
                     resumptionTokenSb.append(Integer.toString(numRows));
-                    
+
                     /*****************************************************************
                      * Use the following line if you wish to include the optional
                      * resumptionToken attributes in the response. Otherwise, use the
@@ -1041,12 +1045,12 @@ public class JDBCOAICatalog extends AbstractCatalog {
                 e.printStackTrace();
                 throw new OAIInternalServerError(e.getMessage());
             }
-            
+
             listSetsMap.put("sets", sets.iterator());
             return listSetsMap;
         }
     }
-    
+
     /**
      * Retrieve the next set of sets associated with the resumptionToken
      *
@@ -1066,7 +1070,7 @@ public class JDBCOAICatalog extends AbstractCatalog {
             purge(); // clean out old resumptionTokens
             Map listSetsMap = new HashMap();
             ArrayList sets = new ArrayList();
-            
+
             /**********************************************************************
              * parse your resumptionToken and look it up in the resumptionResults,
              * if necessary
@@ -1082,28 +1086,28 @@ public class JDBCOAICatalog extends AbstractCatalog {
             } catch (NoSuchElementException e) {
                 throw new BadResumptionTokenException();
             }
-            
+
             try {
                 /* Get some more records from your database */
                 ResultSet rs = (ResultSet)resumptionResults.get(resumptionId);
                 if (rs == null) {
                     throw new BadResumptionTokenException();
                 }
-                
+
                 if (rs.getRow() != oldCount) {
 //                  System.out.println("JDBCOAICatalog.listIdentifiers: reuse of old resumptionToken?");
                     rs.absolute(oldCount);
                 }
-                
+
                 int count;
-                
+
                 /* load the sets ArrayLists. */
                 for (count = 0; count < maxListSize && rs.next(); ++count) {
                     HashMap nativeItem = getColumnValues(rs);
                     /* Use the RecordFactory to extract set for each item */
                     sets.add(getSetXML(nativeItem));
                 }
-                
+
                 /* decide if you're done. */
                 if (oldCount+count < numRows) {
                     /*****************************************************************
@@ -1115,7 +1119,7 @@ public class JDBCOAICatalog extends AbstractCatalog {
                     resumptionTokenSb.append(Integer.toString(oldCount + count));
                     resumptionTokenSb.append("!");
                     resumptionTokenSb.append(Integer.toString(numRows));
-                    
+
                     /*****************************************************************
                      * Use the following line if you wish to include the optional
                      * resumptionToken attributes in the response. Otherwise, use the
@@ -1131,12 +1135,12 @@ public class JDBCOAICatalog extends AbstractCatalog {
                 e.printStackTrace();
                 throw new OAIInternalServerError(e.getMessage());
             }
-            
+
             listSetsMap.put("sets", sets.iterator());
             return listSetsMap;
         }
     }
-    
+
     /**
      * get an Iterator containing the setSpecs for the nativeItem
      *
@@ -1168,7 +1172,7 @@ public class JDBCOAICatalog extends AbstractCatalog {
             throw new OAIInternalServerError(e.getMessage());
         }
     }
-    
+
     /**
      * get an Iterator containing the abouts for the nativeItem
      *
@@ -1200,7 +1204,7 @@ public class JDBCOAICatalog extends AbstractCatalog {
             throw new OAIInternalServerError(e.getMessage());
         }
     }
-    
+
     /**
      * Extract &lt;set&gt; XML string from setItem object
      *
@@ -1213,7 +1217,7 @@ public class JDBCOAICatalog extends AbstractCatalog {
         String setSpec = getSetSpec(setItem);
         String setName = getSetName(setItem);
         String setDescription = getSetDescription(setItem);
-        
+
         StringBuffer sb = new StringBuffer();
         sb.append("<set>");
         sb.append("<setSpec>");
@@ -1234,7 +1238,7 @@ public class JDBCOAICatalog extends AbstractCatalog {
 //      throw new IllegalArgumentException(e.getMessage());
 //      }
     }
-    
+
     /**
      * get the setSpec XML string. Extend this class and override this method
      * if the setSpec can't be directly taken from the result set as a String
@@ -1249,7 +1253,7 @@ public class JDBCOAICatalog extends AbstractCatalog {
             return "UnsupportedEncodingException";
         }
     }
-    
+
     /**
      * get the setName XML string. Extend this class and override this method
      * if the setName can't be directly taken from the result set as a String
@@ -1260,7 +1264,7 @@ public class JDBCOAICatalog extends AbstractCatalog {
     protected String getSetName(HashMap setItem) {
         return (String)setItem.get(setNameLabel);
     }
-    
+
     /**
      * get the setDescription XML string. Extend this class and override this method
      * if the setDescription can't be directly taken from the result set as a String
@@ -1273,7 +1277,7 @@ public class JDBCOAICatalog extends AbstractCatalog {
             return null;
         return (String)setItem.get(setDescriptionLabel);
     }
-    
+
     /**
      * close the repository
      */
@@ -1286,7 +1290,7 @@ public class JDBCOAICatalog extends AbstractCatalog {
         }
         persistentConnection = null;
     }
-    
+
     /**
      * Purge tokens that are older than the configured time-to-live.
      */
@@ -1307,7 +1311,7 @@ public class JDBCOAICatalog extends AbstractCatalog {
             resumptionResults.remove(key);
         }
     }
-    
+
     /**
      * Use the current date as the basis for the resumptiontoken
      *

programming_language: Java
filename: NewJDBCOAICatalog.java
change_type: ModificationType.MODIFY
diff: @@ -50,22 +50,22 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
      * The StatementResultSet inner class is used because Statement objects
      * and ResultSet objects are tightly coupled and need to persist across
      * multiple requests.
-     * 
+     *
      * @author Jeffrey A. Young
      */
     private class StatementResultSet {
         private Statement stmt = null;
         private ResultSet rs = null;
-        
+
         public StatementResultSet(String query) throws SQLException {
             Connection con = getConnection();
             stmt = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
             rs = stmt.executeQuery(query);
         }
-        
+
         public Statement getStatement() { return stmt; }
         public ResultSet getResultSet() { return rs; }
-        
+
         public void close() throws SQLException {
             if (rs != null) {
                 rs.close();
@@ -98,7 +98,7 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
         public boolean next() throws SQLException {
             return rs.next();
         }
-        
+
         public void last() throws SQLException {
             rs.last();
         }
@@ -115,47 +115,47 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
             return rs.absolute(oldCount);
         }
     }
-    
+
     /**
      * The JDBC Connection
      */
     private Connection persistentConnection = null;
-    
+
     private static final boolean debug = false;
-    
+
     /**
      * SQL identifier query (loaded from properties)
      * \\i -> localIdentifier, \\o -> oaiIdentifier
      */
     private String identifierQuery = null;
-    
+
     /**
      * SQL range query (loaded from properties)
      * \\f -> from, \\u -> until
      */
     private String rangeQuery = null;
-    
+
     /**
      * SQL range query (loaded from properties)
      * \\f -> from, \\u -> until, \\s -> set
      */
     private String rangeSetQuery = null;
-    
+
     /**
      * SQL query to get a list of available sets
      */
     private String setQuery = null;
-    
+
     /**
      * SQL query to get a list of available sets that apply to a particular identifier
      */
     private String setSpecQuery = null;
-    
+
     /**
      * SQL query to get a list of available abouts that apply to a particular identifier
      */
     private String aboutQuery = null;
-    
+
     /**
      * SQL column labels containing the values of particular interest
      */
@@ -164,26 +164,26 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
     private String setSpecListLabel = null;
     private String setNameLabel = null;
     private String setDescriptionLabel = null;
-    
+
     /**
      * maximum number of entries to return for ListRecords and ListIdentifiers
      * (loaded from properties)
      */
     private int maxListSize;
-    
+
     /**
      * The format required for dates in SQL queries
      * "UTC" = YYYY-MM-DD or YYYY-MM-DDTHH:MM:SSZ
      * other = YYYY/MM/DD
      */
     private String dateFormat = null;
-    
+
     /**
      * Set Strings to be loaded from the properties file
      * (if they are to be loaded from properties rather than queried from the database)
      */
     ArrayList sets = new ArrayList();
-    
+
     /**
      * pending resumption tokens
      */
@@ -191,7 +191,7 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
     private String jdbcURL = null;
     private String jdbcLogin = null;
     private String jdbcPasswd = null;
-    
+
     /**
      * Construct a JDBCOAICatalog object
      *
@@ -205,7 +205,11 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
         } else {
             this.maxListSize = Integer.parseInt(maxListSize);
         }
-        
+
+        String paramRegex = properties.getProperty("AbstractCatalog.paramRegex");
+        if (paramRegex != null) {
+            setParamRegex(paramRegex);
+        }
         String jdbcDriverName = properties.getProperty("JDBCOAICatalog.jdbcDriverName");
         if (jdbcDriverName == null) {
             throw new IllegalArgumentException("JDBCOAICatalog.jdbcDriverName is missing from the properties file");
@@ -214,32 +218,32 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
         if (jdbcURL == null) {
             throw new IllegalArgumentException("JDBCOAICatalog.jdbcURL is missing from the properties file");
         }
-        
+
         jdbcLogin = properties.getProperty("JDBCOAICatalog.jdbcLogin");
         if (jdbcLogin == null) {
             throw new IllegalArgumentException("JDBCOAICatalog.jdbcLogin is missing from the properties file");
         }
-        
+
         jdbcPasswd = properties.getProperty("JDBCOAICatalog.jdbcPasswd");
         if (jdbcPasswd == null) {
             throw new IllegalArgumentException("JDBCOAICatalog.jdbcPasswd is missing from the properties file");
         }
-        
+
         rangeQuery = properties.getProperty("JDBCOAICatalog.rangeQuery");
         if (rangeQuery == null) {
             throw new IllegalArgumentException("JDBCOAICatalog.rangeQuery is missing from the properties file");
         }
-        
+
         rangeSetQuery = properties.getProperty("JDBCOAICatalog.rangeSetQuery");
         if (rangeSetQuery == null) {
             throw new IllegalArgumentException("JDBCOAICatalog.rangeSetQuery is missing from the properties file");
         }
-        
+
         identifierQuery = properties.getProperty("JDBCOAICatalog.identifierQuery");
         if (identifierQuery == null) {
             throw new IllegalArgumentException("JDBCOAICatalog.identifierQuery is missing from the properties file");
         }
-        
+
         aboutQuery = properties.getProperty("JDBCOAICatalog.aboutQuery");
         if (aboutQuery != null) {
             aboutValueLabel = properties.getProperty("JDBCOAICatalog.aboutValueLabel");
@@ -247,7 +251,7 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
                 throw new IllegalArgumentException("JDBCOAICatalog.aboutValueLabel is missing from the properties file");
             }
         }
-        
+
         setSpecQuery = properties.getProperty("JDBCOAICatalog.setSpecQuery");
         setSpecItemLabel = properties.getProperty("JDBCOAICatalog.setSpecItemLabel");
         if (setSpecItemLabel == null) {
@@ -261,9 +265,9 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
         if (setNameLabel == null) {
             throw new IllegalArgumentException("JDBCOAICatalog.setNameLabel is missing from the properties file");
         }
-        
+
         setDescriptionLabel = properties.getProperty("JDBCOAICatalog.setDescriptionLabel");
-        
+
         // See if a setQuery exists
         setQuery = properties.getProperty("JDBCOAICatalog.setQuery");
         if (setQuery == null) {
@@ -277,7 +281,7 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
                 }
             }
         }
-        
+
         try {
             Class.forName(jdbcDriverName);
         } catch (ClassNotFoundException e) {
@@ -285,7 +289,7 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
                     + jdbcDriverName);
         }
     }
-    
+
     /**
      * Retrieve a list of schemaLocation values associated with the specified
      * oaiIdentifier.
@@ -331,7 +335,7 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
             }
         }
     }
-    
+
     /**
      * insert actual from, until, and set parameters into the rangeQuery String
      *
@@ -348,12 +352,12 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
             tokenizer = new StringTokenizer(rangeQuery, "\\");
         else
             tokenizer = new StringTokenizer(rangeSetQuery, "\\");
-        
+
         if (tokenizer.hasMoreTokens())
             sb.append(tokenizer.nextToken());
         else
             throw new OAIInternalServerError("Invalid query");
-        
+
         while (tokenizer.hasMoreTokens()) {
             String token = tokenizer.nextToken();
             switch (token.charAt(0)) {
@@ -375,25 +379,25 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
         if (debug) System.out.println(sb.toString());
         return sb.toString();
     }
-    
+
     /**
      * Extend this class and override this method if necessary.
      */
     protected String formatFromDate(String date) {
         return formatDate(date);
     }
-    
+
     /**
      * Extend this class and override this method if necessary.
      */
     protected String formatUntilDate(String date) {
         return formatDate(date);
     }
-    
+
     /**
      * Change the String from UTC to SQL format
      * If this method doesn't suit your needs, extend this class and override
-     * the method rather than change this code directly. 
+     * the method rather than change this code directly.
      */
     protected String formatDate(String date) {
         if ("UTC".equals(dateFormat)) {
@@ -409,7 +413,7 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
             return sb.toString();
         }
     }
-    
+
     /**
      * insert actual from, until, and set parameters into the identifierQuery String
      *
@@ -426,7 +430,7 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
             sb.append(tokenizer.nextToken());
         else
             throw new OAIInternalServerError("Invalid identifierQuery");
-        
+
         while (tokenizer.hasMoreTokens()) {
             String token = tokenizer.nextToken();
             switch (token.charAt(0)) {
@@ -445,7 +449,7 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
         if (debug) System.out.println(sb.toString());
         return sb.toString();
     }
-    
+
     /**
      * insert actual from, until, and set parameters into the identifierQuery String
      *
@@ -462,7 +466,7 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
             sb.append(tokenizer.nextToken());
         else
             throw new OAIInternalServerError("Invalid identifierQuery");
-        
+
         while (tokenizer.hasMoreTokens()) {
             String token = tokenizer.nextToken();
             switch (token.charAt(0)) {
@@ -481,7 +485,7 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
         if (debug) System.out.println(sb.toString());
         return sb.toString();
     }
-    
+
     /**
      * insert actual from, until, and set parameters into the identifierQuery String
      *
@@ -498,7 +502,7 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
             sb.append(tokenizer.nextToken());
         else
             throw new OAIInternalServerError("Invalid identifierQuery");
-        
+
         while (tokenizer.hasMoreTokens()) {
             String token = tokenizer.nextToken();
             switch (token.charAt(0)) {
@@ -517,7 +521,7 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
         if (debug) System.out.println(sb.toString());
         return sb.toString();
     }
-    
+
     /**
      * Retrieve a list of identifiers that satisfy the specified criteria
      *
@@ -556,7 +560,7 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
             }
             stmtRs.beforeFirst();
             int count;
-            
+
             /* load the headers and identifiers ArrayLists. */
             for (count=0; count < maxListSize && stmtRs.next(); ++count) {
                 HashMap nativeItem = stmtRs.getColumnValues();
@@ -565,12 +569,12 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
                 headers.add(header[0]);
                 identifiers.add(header[1]);
             }
-            
+
             /* decide if you're done */
             if (count < numRows) {
                 String resumptionId = getResumptionId();
                 resumptionResults.put(resumptionId, stmtRs);
-                
+
                 /*****************************************************************
                  * Construct the resumptionToken String however you see fit.
                  *****************************************************************/
@@ -582,7 +586,7 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
                 resumptionTokenSb.append(Integer.toString(numRows));
                 resumptionTokenSb.append("!");
                 resumptionTokenSb.append(metadataPrefix);
-                
+
                 /*****************************************************************
                  * Use the following line if you wish to include the optional
                  * resumptionToken attributes in the response. Otherwise, use the
@@ -606,12 +610,12 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
             e.printStackTrace();
             throw new OAIInternalServerError(e.getMessage());
         }
-        
+
         listIdentifiersMap.put("headers", headers.iterator());
         listIdentifiersMap.put("identifiers", identifiers.iterator());
         return listIdentifiersMap;
     }
-    
+
     /**
      * Retrieve the next set of identifiers associated with the resumptionToken
      *
@@ -629,7 +633,7 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
         Map listIdentifiersMap = new HashMap();
         ArrayList headers = new ArrayList();
         ArrayList identifiers = new ArrayList();
-        
+
         /**********************************************************************
          * parse your resumptionToken and look it up in the resumptionResults,
          * if necessary
@@ -648,7 +652,7 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
         } catch (NoSuchElementException e) {
             throw new BadResumptionTokenException();
         }
-        
+
         try {
             /* Get some more records from your database */
             stmtRs = (StatementResultSet)resumptionResults.get(resumptionId);
@@ -656,12 +660,12 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
                 throw new BadResumptionTokenException();
             }
             int count;
-            
+
             if (stmtRs.getRow() != oldCount) {
 //              System.out.println("JDBCOAICatalog.listIdentifiers: reuse of old resumptionToken?");
                 stmtRs.absolute(oldCount);
             }
-            
+
             /* load the headers and identifiers ArrayLists. */
             for (count = 0; count < maxListSize && stmtRs.next(); ++count) {
                 HashMap nativeItem = stmtRs.getColumnValues();
@@ -671,7 +675,7 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
                 headers.add(header[0]);
                 identifiers.add(header[1]);
             }
-            
+
             /* decide if you're done. */
             if (oldCount+count < numRows) {
                 /*****************************************************************
@@ -685,7 +689,7 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
                 resumptionTokenSb.append(Integer.toString(numRows));
                 resumptionTokenSb.append("!");
                 resumptionTokenSb.append(metadataPrefix);
-                
+
                 /*****************************************************************
                  * Use the following line if you wish to include the optional
                  * resumptionToken attributes in the response. Otherwise, use the
@@ -709,12 +713,12 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
             e.printStackTrace();
             throw new OAIInternalServerError(e.getMessage());
         }
-        
+
         listIdentifiersMap.put("headers", headers.iterator());
         listIdentifiersMap.put("identifiers", identifiers.iterator());
         return listIdentifiersMap;
     }
-    
+
     /**
      * Retrieve the specified metadata for the specified oaiIdentifier
      *
@@ -750,7 +754,7 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
             }
         }
     }
-    
+
     /**
      * Retrieve a list of records that satisfy the specified criteria. Note, though,
      * that unlike the other OAI verb type methods implemented here, both of the
@@ -778,7 +782,7 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
         Map listRecordsMap = new HashMap();
         ArrayList records = new ArrayList();
         StatementResultSet stmtRs = null;
-        
+
         try {
             stmtRs = new StatementResultSet(populateRangeQuery(from, until, set));
             stmtRs.last();
@@ -788,21 +792,21 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
             }
             stmtRs.beforeFirst();
             int count;
-            
+
 //          if (debug) System.out.println("JDBCOAICatalog.listRecords: numRows=" + numRows);
-            
+
             /* load the records ArrayList */
             for (count=0; count < maxListSize && stmtRs.next(); ++count) {
                 HashMap nativeItem = stmtRs.getColumnValues();
                 String record = constructRecord(nativeItem, metadataPrefix);
                 records.add(record);
             }
-            
+
             /* decide if you're done */
             if (count < numRows) {
                 String resumptionId = getResumptionId();
                 resumptionResults.put(resumptionId, stmtRs);
-                
+
                 /*****************************************************************
                  * Construct the resumptionToken String however you see fit.
                  *****************************************************************/
@@ -814,7 +818,7 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
                 resumptionTokenSb.append(Integer.toString(numRows));
                 resumptionTokenSb.append("!");
                 resumptionTokenSb.append(metadataPrefix);
-                
+
                 /*****************************************************************
                  * Use the following line if you wish to include the optional
                  * resumptionToken attributes in the response. Otherwise, use the
@@ -840,11 +844,11 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
             e.printStackTrace();
             throw new OAIInternalServerError(e.getMessage());
         }
-        
+
         listRecordsMap.put("records", records.iterator());
         return listRecordsMap;
     }
-    
+
     /**
      * Retrieve the next set of records associated with the resumptionToken
      *
@@ -861,7 +865,7 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
         Map listRecordsMap = new HashMap();
         ArrayList records = new ArrayList();
         purge(); // clean out old resumptionTokens
-        
+
         /**********************************************************************
          * parse your resumptionToken and look it up in the resumptionResults,
          * if necessary
@@ -880,21 +884,21 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
         } catch (NoSuchElementException e) {
             throw new BadResumptionTokenException();
         }
-        
+
         try {
             /* Get some more records from your database */
             stmtRs = (StatementResultSet) resumptionResults.get(resumptionId);
             if (stmtRs == null) {
                 throw new BadResumptionTokenException();
             }
-            
+
             if (stmtRs.getRow() != oldCount) {
 //              System.out.println("JDBCOAICatalog.listIdentifiers: reuse of old resumptionToken?");
                 stmtRs.absolute(oldCount);
             }
-            
+
             int count;
-            
+
             /* load the headers and identifiers ArrayLists. */
             for (count = 0; count < maxListSize && stmtRs.next(); ++count) {
                 try {
@@ -906,7 +910,7 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
                     throw new BadResumptionTokenException();
                 }
             }
-            
+
             /* decide if you're done */
             if (oldCount+count < numRows) {
                 /*****************************************************************
@@ -920,7 +924,7 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
                 resumptionTokenSb.append(Integer.toString(numRows));
                 resumptionTokenSb.append("!");
                 resumptionTokenSb.append(metadataPrefix);
-                
+
                 /*****************************************************************
                  * Use the following line if you wish to include the optional
                  * resumptionToken attributes in the response. Otherwise, use the
@@ -946,11 +950,11 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
             e.printStackTrace();
             throw new OAIInternalServerError(e.getMessage());
         }
-        
+
         listRecordsMap.put("records", records.iterator());
         return listRecordsMap;
     }
-    
+
     /**
      * Utility method to construct a Record object for a specified
      * metadataFormat from a native record
@@ -966,14 +970,14 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
         String schemaURL = null;
         Iterator setSpecs = getSetSpecs(nativeItem);
         Iterator abouts = getAbouts(nativeItem);
-        
+
         if (metadataPrefix != null) {
             if ((schemaURL = getCrosswalks().getSchemaURL(metadataPrefix)) == null)
                 throw new CannotDisseminateFormatException(metadataPrefix);
         }
         return getRecordFactory().create(nativeItem, schemaURL, metadataPrefix, setSpecs, abouts);
     }
-    
+
     /**
      * Retrieve a list of sets that satisfy the specified criteria
      *
@@ -994,19 +998,19 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
             purge(); // clean out old resumptionTokens
             Map listSetsMap = new HashMap();
             ArrayList sets = new ArrayList();
-            
+
             try {
                 if (debug) System.out.println(setQuery);
-                
+
                 /* Get some records from your database */
                 stmtRs = new StatementResultSet(setQuery);
                 stmtRs.last();
                 int numRows = stmtRs.getRow();
                 stmtRs.beforeFirst();
                 int count;
-                
+
 //              if (debug) System.out.println("JDBCOAICatalog.listSets: numRows=" + numRows);
-                
+
                 /* load the sets ArrayLists. */
                 for (count=0; count < maxListSize && stmtRs.next(); ++count) {
                     /* Use the RecordFactory to extract header/set pairs for each item */
@@ -1014,7 +1018,7 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
                     sets.add(getSetXML(nativeItem));
                     if (debug) System.out.println("JDBCOAICatalog.listSets: adding an entry");
                 }
-                
+
                 /* decide if you're done */
                 if (count < numRows) {
                     String resumptionId = getResumptionId();
@@ -1023,7 +1027,7 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
                      * means the token can't be reused.
                      *****************************************************************/
                     resumptionResults.put(resumptionId, stmtRs);
-                    
+
                     /*****************************************************************
                      * Construct the resumptionToken String however you see fit.
                      *****************************************************************/
@@ -1033,7 +1037,7 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
                     resumptionTokenSb.append(Integer.toString(count));
                     resumptionTokenSb.append("!");
                     resumptionTokenSb.append(Integer.toString(numRows));
-                    
+
                     /*****************************************************************
                      * Use the following line if you wish to include the optional
                      * resumptionToken attributes in the response. Otherwise, use the
@@ -1057,12 +1061,12 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
                 e.printStackTrace();
                 throw new OAIInternalServerError(e.getMessage());
             }
-            
+
             listSetsMap.put("sets", sets.iterator());
             return listSetsMap;
         }
     }
-    
+
     /**
      * Retrieve the next set of sets associated with the resumptionToken
      *
@@ -1077,14 +1081,14 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
     public Map listSets(String resumptionToken)
     throws OAIInternalServerError, BadResumptionTokenException {
         StatementResultSet stmtRs = null;
-        
+
         if (setQuery == null) {
             throw new BadResumptionTokenException();
         } else {
             purge(); // clean out old resumptionTokens
             Map listSetsMap = new HashMap();
             ArrayList sets = new ArrayList();
-            
+
             /**********************************************************************
              * parse your resumptionToken and look it up in the resumptionResults,
              * if necessary
@@ -1100,28 +1104,28 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
             } catch (NoSuchElementException e) {
                 throw new BadResumptionTokenException();
             }
-            
+
             try {
                 /* Get some more records from your database */
                 stmtRs = (StatementResultSet)resumptionResults.get(resumptionId);
                 if (stmtRs == null) {
                     throw new BadResumptionTokenException();
                 }
-                
+
                 if (stmtRs.getRow() != oldCount) {
 //                  System.out.println("JDBCOAICatalog.listIdentifiers: reuse of old resumptionToken?");
                     stmtRs.absolute(oldCount);
                 }
-                
+
                 int count;
-                
+
                 /* load the sets ArrayLists. */
                 for (count = 0; count < maxListSize && stmtRs.next(); ++count) {
                     HashMap nativeItem = stmtRs.getColumnValues();
                     /* Use the RecordFactory to extract set for each item */
                     sets.add(getSetXML(nativeItem));
                 }
-                
+
                 /* decide if you're done. */
                 if (oldCount+count < numRows) {
                     /*****************************************************************
@@ -1133,7 +1137,7 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
                     resumptionTokenSb.append(Integer.toString(oldCount + count));
                     resumptionTokenSb.append("!");
                     resumptionTokenSb.append(Integer.toString(numRows));
-                    
+
                     /*****************************************************************
                      * Use the following line if you wish to include the optional
                      * resumptionToken attributes in the response. Otherwise, use the
@@ -1157,12 +1161,12 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
                 e.printStackTrace();
                 throw new OAIInternalServerError(e.getMessage());
             }
-            
+
             listSetsMap.put("sets", sets.iterator());
             return listSetsMap;
         }
     }
-    
+
     /**
      * get an Iterator containing the setSpecs for the nativeItem
      *
@@ -1196,7 +1200,7 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
             }
         }
     }
-    
+
     /**
      * get an Iterator containing the abouts for the nativeItem
      *
@@ -1230,7 +1234,7 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
             }
         }
     }
-    
+
     /**
      * Extract &lt;set&gt; XML string from setItem object
      *
@@ -1242,7 +1246,7 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
         String setSpec = getSetSpec(setItem);
         String setName = getSetName(setItem);
         String setDescription = getSetDescription(setItem);
-        
+
         StringBuffer sb = new StringBuffer();
         sb.append("<set>");
         sb.append("<setSpec>");
@@ -1259,7 +1263,7 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
         sb.append("</set>");
         return sb.toString();
     }
-    
+
     /**
      * get the setSpec XML string. Extend this class and override this method
      * if the setSpec can't be directly taken from the result set as a String
@@ -1274,7 +1278,7 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
             return "UnsupportedEncodingException";
         }
     }
-    
+
     /**
      * get the setName XML string. Extend this class and override this method
      * if the setName can't be directly taken from the result set as a String
@@ -1285,7 +1289,7 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
     protected String getSetName(HashMap setItem) {
         return (String)setItem.get(setNameLabel);
     }
-    
+
     /**
      * get the setDescription XML string. Extend this class and override this method
      * if the setDescription can't be directly taken from the result set as a String
@@ -1298,12 +1302,12 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
             return null;
         return (String)setItem.get(setDescriptionLabel);
     }
-    
+
     private Connection getNewConnection() throws SQLException {
         // open the connection
         return DriverManager.getConnection(jdbcURL, jdbcLogin, jdbcPasswd);
     }
-    
+
     private Connection getConnection() throws SQLException {
         if (persistentConnection != null) {
             if (persistentConnection.isClosed()) {
@@ -1321,7 +1325,7 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
      */
     public void close() {
     }
-    
+
     /**
      * Purge tokens that are older than the configured time-to-live.
      */
@@ -1342,7 +1346,7 @@ public class NewJDBCOAICatalog extends AbstractCatalog {
             resumptionResults.remove(key);
         }
     }
-    
+
     /**
      * Use the current date as the basis for the resumptiontoken
      *

programming_language: Java
filename: GetRecord.java
change_type: ModificationType.MODIFY
diff: @@ -37,7 +37,7 @@ public class GetRecord extends ServerVerb {
 	validParamNames.add("identifier");
 	validParamNames.add("metadataPrefix");
     }
-    
+
     /**
      * Construct the xml response on the server-side.
      *
@@ -98,7 +98,7 @@ public class GetRecord extends ServerVerb {
 	try {
 	    if (metadataPrefix == null || metadataPrefix.length() == 0
 		|| identifier == null || identifier.length() == 0
-		|| hasBadArguments(request, validParamNames.iterator(), validParamNames)) {
+		|| hasBadArguments(request, validParamNames.iterator(), validParamNames, abstractCatalog)) {
 		throw new BadArgumentException();
 	    }
 	    else if (!crosswalks.containsValue(metadataPrefix)) {

programming_language: Java
filename: Identify.java
change_type: ModificationType.MODIFY
diff: @@ -35,7 +35,7 @@ public class Identify extends ServerVerb {
     static {
         validParamNames.add("verb");
     }
-    
+
     /**
      * Construct the xml response on the server side.
      *
@@ -80,7 +80,7 @@ public class Identify extends ServerVerb {
 //      sb.append(getRequestURL(request));
 //      sb.append("</requestURL>");
         sb.append(getRequestElement(request, validParamNames, baseURL));
-        if (hasBadArguments(request, validParamNames.iterator(), validParamNames)) {
+        if (hasBadArguments(request, validParamNames.iterator(), validParamNames, abstractCatalog)) {
             sb.append(new BadArgumentException().getMessage());
         } else {
             sb.append("<Identify>");

programming_language: Java
filename: ListIdentifiers.java
change_type: ModificationType.MODIFY
diff: @@ -82,7 +82,7 @@ public class ListIdentifiers extends ServerVerb {
 
 	if (metadataPrefix != null && metadataPrefix.length() == 0)
 	    metadataPrefix = null;
-	
+
 	sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>");
 	String styleSheet = properties.getProperty("OAIHandler.styleSheet");
 	if (styleSheet != null) {
@@ -100,7 +100,7 @@ public class ListIdentifiers extends ServerVerb {
 // 	sb.append("<requestURL>");
 // 	sb.append(getRequestURL(request));
 // 	sb.append("</requestURL>");
-            
+
 	if (!abstractCatalog.isHarvestable()) {
 	    sb.append("<request verb=\"ListIdentifiers\">");
 	    sb.append(baseURL);
@@ -144,7 +144,7 @@ public class ListIdentifiers extends ServerVerb {
 		    if (metadataPrefix == null) {
 			throw new BadArgumentException();
 		    }
-		    
+
 		    if (!crosswalks.containsValue(metadataPrefix)) {
 			throw new CannotDisseminateFormatException(metadataPrefix);
 		    } else {
@@ -173,7 +173,7 @@ public class ListIdentifiers extends ServerVerb {
 	    } else {
 		validParamNames = validParamNames2;
 		requiredParamNames = requiredParamNames2;
-		if (hasBadArguments(request, requiredParamNames.iterator(), validParamNames)) {
+		if (hasBadArguments(request, requiredParamNames.iterator(), validParamNames, abstractCatalog)) {
 		    sb.append(getRequestElement(request, validParamNames, baseURL, xmlEncodeSetSpec));
 		    sb.append(new BadArgumentException().getMessage());
 		} else {
@@ -189,7 +189,7 @@ public class ListIdentifiers extends ServerVerb {
 	    if (listIdentifiersMap != null) {
 		sb.append(getRequestElement(request, validParamNames, baseURL, xmlEncodeSetSpec));
 		if (hasBadArguments(request, requiredParamNames.iterator(),
-				    validParamNames)) {
+				    validParamNames, abstractCatalog)) {
 		    sb.append(new BadArgumentException().getMessage());
 		} else {
 		    sb.append("<ListIdentifiers>");
@@ -197,7 +197,7 @@ public class ListIdentifiers extends ServerVerb {
 		    while (identifiers.hasNext()) {
 			sb.append((String)identifiers.next());
 		    }
-		    
+
 		    Map newResumptionMap = (Map)listIdentifiersMap.get("resumptionMap");
 		    if (newResumptionMap != null) {
 			String newResumptionToken = (String)newResumptionMap.get("resumptionToken");

programming_language: Java
filename: ListMetadataFormats.java
change_type: ModificationType.MODIFY
diff: @@ -92,7 +92,7 @@ public class ListMetadataFormats extends ServerVerb {
 //      sb.append("</requestURL>");
         sb.append(getRequestElement(request, validParamNames, baseURL));
         if (hasBadArguments(request, requiredParamNames.iterator(),
-                validParamNames)) {
+                validParamNames, abstractCatalog)) {
             sb.append(new BadArgumentException().getMessage());
         } else {
             Crosswalks crosswalks = abstractCatalog.getCrosswalks();

programming_language: Java
filename: ListRecords.java
change_type: ModificationType.MODIFY
diff: @@ -56,7 +56,7 @@ public class ListRecords extends ServerVerb {
 	requiredParamNames2.add("verb");
 	requiredParamNames2.add("resumptionToken");
     }
-    
+
     /**
      * Server-side method to construct an xml response to a ListRecords verb.
      */
@@ -65,7 +65,7 @@ public class ListRecords extends ServerVerb {
                                    Transformer serverTransformer)
         throws OAIInternalServerError, TransformerException {
         if (debug) System.out.println("ListRecords.construct: entered");
-	
+
         Properties properties = (Properties)context.get("OAIHandler.properties");
         AbstractCatalog abstractCatalog = (AbstractCatalog)context.get("OAIHandler.catalog");
 	boolean xmlEncodeSetSpec = "true".equalsIgnoreCase(properties.getProperty("OAIHandler.xmlEncodeSetSpec"));
@@ -81,10 +81,10 @@ public class ListRecords extends ServerVerb {
         StringBuffer sb = new StringBuffer();
         String oldResumptionToken = request.getParameter("resumptionToken");
 	String metadataPrefix = request.getParameter("metadataPrefix");
-	
+
 	if (metadataPrefix != null && metadataPrefix.length() == 0)
 	    metadataPrefix = null;
-	
+
         sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>");
 	String styleSheet = properties.getProperty("OAIHandler.styleSheet");
 	if (styleSheet != null) {
@@ -105,7 +105,7 @@ public class ListRecords extends ServerVerb {
 //         sb.append("<requestURL>");
 //         sb.append(getRequestURL(request));
 //         sb.append("</requestURL>");
-	
+
 	if (!abstractCatalog.isHarvestable()) {
 	    sb.append("<request verb=\"ListRecords\">");
 	    sb.append(baseURL);
@@ -123,9 +123,9 @@ public class ListRecords extends ServerVerb {
 // 		System.out.print(" of " + totalMemoryK / 1024.0 + "M ");
 // 		System.out.println("(" + (100 * freeMemoryK) / totalMemoryK + "%)");
 // 	    }
-	
+
 	    Map listRecordsMap = null;
-	    
+
 	    ArrayList validParamNames = null;
 	    ArrayList requiredParamNames = null;
 	    if (oldResumptionToken == null) {
@@ -189,7 +189,7 @@ public class ListRecords extends ServerVerb {
 	    } else {
 		validParamNames = validParamNames2;
 		requiredParamNames = requiredParamNames2;
-		if (hasBadArguments(request, requiredParamNames.iterator(), validParamNames)) {
+		if (hasBadArguments(request, requiredParamNames.iterator(), validParamNames, abstractCatalog)) {
 		    sb.append(getRequestElement(request, validParamNames, baseURL, xmlEncodeSetSpec));
 		    sb.append(new BadArgumentException().getMessage());
 		} else {
@@ -204,7 +204,7 @@ public class ListRecords extends ServerVerb {
 	    if (listRecordsMap != null) {
 		sb.append(getRequestElement(request, validParamNames, baseURL, xmlEncodeSetSpec));
 		if (hasBadArguments(request, requiredParamNames.iterator(),
-				    validParamNames)) {
+				    validParamNames, abstractCatalog)) {
 		    sb.append(new BadArgumentException().getMessage());
 		} else {
 		    sb.append("<ListRecords>\n");

programming_language: Java
filename: ListSets.java
change_type: ModificationType.MODIFY
diff: @@ -48,7 +48,7 @@ public class ListSets extends ServerVerb {
      * @exception OAIInternalServerError
      */
     public static String construct(HashMap context, HttpServletRequest request,
-                                   HttpServletResponse response, Transformer serverTransformer) 
+                                   HttpServletResponse response, Transformer serverTransformer)
 	throws OAIInternalServerError, TransformerException {
         Properties properties =
 	    (Properties)context.get("OAIHandler.properties");
@@ -84,7 +84,7 @@ public class ListSets extends ServerVerb {
 	sb.append(getRequestElement(request, validParamNames, baseURL));
 	Map listSetsMap = null;
 	if (hasBadArguments(request, requiredParamNames.iterator(),
-			    validParamNames)) {
+			    validParamNames, abstractCatalog)) {
 	    sb.append(new BadArgumentException().getMessage());
 	} else {
 	    try {

programming_language: Java
filename: ServerVerb.java
change_type: ModificationType.MODIFY
diff: @@ -33,6 +33,7 @@ import javax.xml.transform.TransformerException;
 import javax.xml.transform.stream.StreamResult;
 import javax.xml.transform.stream.StreamSource;
 
+import ORG.oclc.oai.server.catalog.AbstractCatalog;
 import ORG.oclc.oai.util.OAIUtil;
 //import javax.servlet.http.HttpUtils;
 
@@ -164,7 +165,8 @@ public abstract class ServerVerb {
 
     protected static boolean hasBadArguments(HttpServletRequest request,
             Iterator requiredParamNames,
-            List validParamNames) {
+            List validParamNames,
+            AbstractCatalog catalog) {
         while (requiredParamNames.hasNext()) {
             String name = (String)requiredParamNames.next();
             String value = request.getParameter(name);
@@ -175,10 +177,13 @@ public abstract class ServerVerb {
         Enumeration params = request.getParameterNames();
         while (params.hasMoreElements()) {
             String name = (String)params.nextElement();
+            String[] values = request.getParameterValues(name);
             if (!validParamNames.contains(name)) {
                 return true;
-            } else if (request.getParameterValues(name).length > 1) {
+            } else if (values.length > 1) {
                 return true;
+            } else if (values.length == 1 && !catalog.isValidParam(name, values[0])) {
+            	return true;
             }
         }
         String identifier = request.getParameter("identifier");

programming_language: Java