Changeset 28846

Show
Ignore:
Timestamp:
27.02.2014 10:35:07 (6 years ago)
Author:
kjdon
Message:

indented file in preparation for major changes

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • main/trunk/greenstone3/src/java/org/greenstone/gsdl3/util/OAIXML.java

    r27671 r28846  
    5050public class OAIXML { 
    5151   
    52     static Logger logger = Logger.getLogger(org.greenstone.gsdl3.util.GSXML.class.getName()); 
    53  
    54     // the leading keyword of oai protocol 
    55     public static final String VERB = "verb"; 
    56  
    57     // six valid oai verbs 
    58     public static final String GET_RECORD = "GetRecord"; 
    59     public static final String LIST_RECORDS = "ListRecords"; 
    60     public static final String LIST_IDENTIFIERS = "ListIdentifiers"; 
    61     public static final String LIST_SETS = "ListSets"; 
    62     public static final String LIST_METADATA_FORMATS = "ListMetadataFormats"; 
    63     public static final String IDENTIFY = "Identify"; 
    64  
    65     // other valid oai parameters 
    66     public static final String OAI_METADATAFORMAT = "OAIMetadataFormat"; 
    67     public static final String METADATA_NAMESPACE = "metadataNamespace"; 
    68     public static final String OAI_DC = "oai_dc"; 
    69     public static final String DC = "dc"; 
    70     public static final String METADATA_PREFIX = "metadataPrefix"; 
    71     public static final String FROM = "from"; 
    72     public static final String UNTIL = "until"; 
    73     public static final String SET = "set"; 
    74     public static final String RESUMPTION_TOKEN = "resumptionToken"; 
    75     public static final String RESUMPTION_TOKEN_EXPIRATION = "resumptionTokenExpiration"; 
    76     public static final String IDENTIFIER = "identifier"; 
    77  
    78     public static final String USE_STYLESHEET = "useOAIStylesheet"; 
    79     public static final String STYLESHEET = "OAIStylesheet"; 
     52  static Logger logger = Logger.getLogger(org.greenstone.gsdl3.util.GSXML.class.getName()); 
     53 
     54  // the leading keyword of oai protocol 
     55  public static final String VERB = "verb"; 
     56 
     57  // six valid oai verbs 
     58  public static final String GET_RECORD = "GetRecord"; 
     59  public static final String LIST_RECORDS = "ListRecords"; 
     60  public static final String LIST_IDENTIFIERS = "ListIdentifiers"; 
     61  public static final String LIST_SETS = "ListSets"; 
     62  public static final String LIST_METADATA_FORMATS = "ListMetadataFormats"; 
     63  public static final String IDENTIFY = "Identify"; 
     64 
     65  // other valid oai parameters 
     66  public static final String OAI_METADATAFORMAT = "OAIMetadataFormat"; 
     67  public static final String METADATA_NAMESPACE = "metadataNamespace"; 
     68  public static final String OAI_DC = "oai_dc"; 
     69  public static final String DC = "dc"; 
     70  public static final String METADATA_PREFIX = "metadataPrefix"; 
     71  public static final String FROM = "from"; 
     72  public static final String UNTIL = "until"; 
     73  public static final String SET = "set"; 
     74  public static final String RESUMPTION_TOKEN = "resumptionToken"; 
     75  public static final String RESUMPTION_TOKEN_EXPIRATION = "resumptionTokenExpiration"; 
     76  public static final String IDENTIFIER = "identifier"; 
     77 
     78  public static final String USE_STYLESHEET = "useOAIStylesheet"; 
     79  public static final String STYLESHEET = "OAIStylesheet"; 
    8080   
    81     // words used to compose oai responses and read in OAIConfig.xml 
    82     public static final String ADMIN_EMAIL = "adminEmail"; 
    83     public static final String BAD_ARGUMENT = "badArgument"; 
    84     public static final String BAD_RESUMPTION_TOKEN = "badResumptionToken"; 
    85     public static final String BAD_VERB = "badVerb"; 
    86     public static final String BASE_URL = "baseURL"; 
    87     public static final String CANNOT_DISSEMINATE_FORMAT = "cannotDisseminateFormat"; 
    88     public static final String CODE = "code"; 
    89     public static final String COLLECTION = "collection"; 
    90     public static final String COLLECTION_LIST = "collectionList"; 
    91     public static final String COMPLETE_LIST_SIZE = "completeListSize"; 
    92     public static final String COMPRESSION = "compression"; 
    93     public static final String CURSOR = "cursor"; 
    94     public static final String DATESTAMP = "datestamp"; 
    95     public static final String DELETED_RECORD = "deletedRecord"; 
    96     public static final String DESCRIPTION = "description"; 
    97     public static final String EARLIEST_DATESTAMP = "earliestDatestamp"; 
    98     public static final String ERROR = "error"; 
    99     public static final String EXPIRATION_DATE = "expirationDate"; 
    100     public static final String GRANULARITY = "granularity"; 
    101     public static final String GS3OAI = "GS3OAI"; 
    102     public static final String GS_OAI_RESOURCE_URL = "gs.OAIResourceURL"; 
    103     public static final String HAS_OAI = "hasOAI"; 
    104     public static final String HEADER = "header"; 
    105     public static final String ILLEGAL_OAI_VERB = "Illegal OAI verb"; 
    106     public static final String INDEX_STEM = "indexStem"; 
     81  // words used to compose oai responses and read in OAIConfig.xml 
     82  public static final String ADMIN_EMAIL = "adminEmail"; 
     83  public static final String BAD_ARGUMENT = "badArgument"; 
     84  public static final String BAD_RESUMPTION_TOKEN = "badResumptionToken"; 
     85  public static final String BAD_VERB = "badVerb"; 
     86  public static final String BASE_URL = "baseURL"; 
     87  public static final String CANNOT_DISSEMINATE_FORMAT = "cannotDisseminateFormat"; 
     88  public static final String CODE = "code"; 
     89  public static final String COLLECTION = "collection"; 
     90  public static final String COLLECTION_LIST = "collectionList"; 
     91  public static final String COMPLETE_LIST_SIZE = "completeListSize"; 
     92  public static final String COMPRESSION = "compression"; 
     93  public static final String CURSOR = "cursor"; 
     94  public static final String DATESTAMP = "datestamp"; 
     95  public static final String DELETED_RECORD = "deletedRecord"; 
     96  public static final String DESCRIPTION = "description"; 
     97  public static final String EARLIEST_DATESTAMP = "earliestDatestamp"; 
     98  public static final String ERROR = "error"; 
     99  public static final String EXPIRATION_DATE = "expirationDate"; 
     100  public static final String GRANULARITY = "granularity"; 
     101  public static final String GS3OAI = "GS3OAI"; 
     102  public static final String GS_OAI_RESOURCE_URL = "gs.OAIResourceURL"; 
     103  public static final String HAS_OAI = "hasOAI"; 
     104  public static final String HEADER = "header"; 
     105  public static final String ILLEGAL_OAI_VERB = "Illegal OAI verb"; 
     106  public static final String INDEX_STEM = "indexStem"; 
    107107  public static final String INFO_METADATA = "Metadata"; // this has capital M 
    108     public static final String LASTMODIFIED = "lastmodified"; 
    109     public static final String MAPPING = "mapping"; 
    110     public static final String MAPPING_LIST = "mappingList"; 
    111     public static final String MESSAGE = "message"; 
    112     public static final String METADATA = "metadata"; 
    113     public static final String METADATA_FORMAT = "metadataFormat"; 
    114     public static final String NAME = "name"; 
    115     public static final String NO_RECORDS_MATCH = "noRecordsMatch"; 
    116     public static final String OAI = "OAI"; 
    117     public static final String OAI_DASH_PMH = "OAI-PMH"; 
    118     public static final String OAI_LASTMODIFIED = "oailastmodified"; 
    119     public static final String OAIPMH = "OAIPMH"; 
    120     public static final String OAI_RESUMPTION_TOKENS = "OAIResumptionTokens"; 
    121     public static final String OAI_INFO = "oaiInfo"; 
    122     public static final String OAI_SERVICE = "oaiService"; 
    123     public static final String OAI_SET_LIST = "oaiSetList"; 
    124     public static final String OAI_SERVICE_UNAVAILABLE = "OAI service unavailable"; 
    125     public static final String OID = "OID"; 
    126     public static final String PARAM = "param"; 
    127     public static final String PARAM_LIST = "paramList"; 
    128     public static final String PROTOCOL_VERSION = "protocolVersion"; 
    129     public static final String RECORD = "record"; 
    130     public static final String REQUEST = "request"; 
    131     public static final String REPOSITORY_NAME = "repositoryName"; 
    132     public static final String REPOSITORY_ID = "repositoryId"; 
    133     public static final String RESPONSE = "response"; 
    134     public static final String RESPONSE_DATE = "responseDate"; 
    135     public static final String RESUME_AFTER = "resumeAfter"; 
    136     public static final String SCHEMA = "schema"; 
    137     public static final String SERVICE = "service"; 
    138     public static final String SERVICE_UNAVAILABLE = "service unavailable"; 
    139     public static final String SET_SPEC = "setSpec"; 
    140     public static final String SET_NAME = "setName"; 
    141     public static final String SET_DESCRIPTION = "setDescription"; 
    142     public static final String SITE = "site"; 
    143     public static final String TO = "to"; 
    144     public static final String TYPE = "type"; 
    145     public static final String VALUE = "value"; 
    146      
    147     //Two error and exception conditions for the verb 'ListMetadataFormats' 
    148     public static final String ID_DOES_NOT_EXIST = "idDoesNotExist"; 
    149     public static final String NO_METADATA_FORMATS = "noMetadataFormats"; 
    150      
    151     // The node id in the collection database, which contains all the OIDs in the database 
    152     public static final String BROWSELIST = "browselist"; 
     108  public static final String LASTMODIFIED = "lastmodified"; 
     109  public static final String MAPPING = "mapping"; 
     110  public static final String MAPPING_LIST = "mappingList"; 
     111  public static final String MESSAGE = "message"; 
     112  public static final String METADATA = "metadata"; 
     113  public static final String METADATA_FORMAT = "metadataFormat"; 
     114  public static final String NAME = "name"; 
     115  public static final String NO_RECORDS_MATCH = "noRecordsMatch"; 
     116  public static final String OAI = "OAI"; 
     117  public static final String OAI_DASH_PMH = "OAI-PMH"; 
     118  public static final String OAI_LASTMODIFIED = "oailastmodified"; 
     119  public static final String OAIPMH = "OAIPMH"; 
     120  public static final String OAI_RESUMPTION_TOKENS = "OAIResumptionTokens"; 
     121  public static final String OAI_INFO = "oaiInfo"; 
     122  public static final String OAI_SERVICE = "oaiService"; 
     123  public static final String OAI_SET_LIST = "oaiSetList"; 
     124  public static final String OAI_SERVICE_UNAVAILABLE = "OAI service unavailable"; 
     125  public static final String OID = "OID"; 
     126  public static final String PARAM = "param"; 
     127  public static final String PARAM_LIST = "paramList"; 
     128  public static final String PROTOCOL_VERSION = "protocolVersion"; 
     129  public static final String RECORD = "record"; 
     130  public static final String REQUEST = "request"; 
     131  public static final String REPOSITORY_NAME = "repositoryName"; 
     132  public static final String REPOSITORY_ID = "repositoryId"; 
     133  public static final String RESPONSE = "response"; 
     134  public static final String RESPONSE_DATE = "responseDate"; 
     135  public static final String RESUME_AFTER = "resumeAfter"; 
     136  public static final String SCHEMA = "schema"; 
     137  public static final String SERVICE = "service"; 
     138  public static final String SERVICE_UNAVAILABLE = "service unavailable"; 
     139  public static final String SET_SPEC = "setSpec"; 
     140  public static final String SET_NAME = "setName"; 
     141  public static final String SET_DESCRIPTION = "setDescription"; 
     142  public static final String SITE = "site"; 
     143  public static final String TO = "to"; 
     144  public static final String TYPE = "type"; 
     145  public static final String VALUE = "value"; 
     146     
     147  //Two error and exception conditions for the verb 'ListMetadataFormats' 
     148  public static final String ID_DOES_NOT_EXIST = "idDoesNotExist"; 
     149  public static final String NO_METADATA_FORMATS = "noMetadataFormats"; 
     150     
     151  // The node id in the collection database, which contains all the OIDs in the database 
     152  public static final String BROWSELIST = "browselist"; 
    153153         
    154     //system-dependent file separator, maybe '/' or '\' 
    155     public static final String FILE_SEPARATOR = File.separator; 
    156     public static final String OAI_VERSION1 = "1.0"; 
    157     public static final String OAI_VERSION2 = "2.0"; 
    158     /*************************above are final values****************************/ 
    159      
    160     public static Element resumption_token_elem = null; 
    161     //used when saving the token file 
    162     public static File resumption_token_file = null; 
    163     //public static ArrayList token_list = new ArrayList(); 
    164      
    165     //initialized in getOAIConfigXML() 
    166     public static Element oai_config_elem = null; 
    167      
    168     //stores the date format "yyyy-MM-ddTHH:mm:ssZ" 
    169     public static String granularity = ""; 
    170  
    171     // http://www.openarchives.org/OAI/openarchivesprotocol.html#DatestampsRequests  
    172     // specifies that all repositories must support YYYY-MM-DD (yyyy-MM-dd in Java) 
    173     // this would be in addition to the other (optional) granularity of above that  
    174     // a repository may additionally choose to support. 
    175     public static final String default_granularity = "yyyy-MM-dd"; 
    176  
    177     //this value is overriden in getOAIConfigXML() 
    178     public static long token_expiration = 7200; 
    179      
    180     /** which version of oai that this oaiserver supports; default is 2.0  
    181      *  initialized in getOAIConfigXML() 
    182      */ 
    183     public static String oai_version = "2.0"; 
    184     public static String baseURL = ""; 
    185      
    186     /**response owner document */ 
    187     public static Document response_doc = new XMLConverter().newDOM();  
    188      
    189     public static String[] special_char = {"/", "?", "#", "=", "&", ":", ";", " ", "%", "+"}; 
    190     public static String[] escape_sequence = {"%2F", "%3F", "%23", "%3D", "%26", "%3A", "%3B", "%20", "%25", "%2B"}; 
    191 //    /** key=special character; value=escaped sequence */ 
    192 //    public static HashMap encode_map = new HashMap(); 
    193 //    /** key=escaped sequence; value=special character */ 
    194 //    public static HashMap decode_map = new HashMap(); 
    195  
    196     public static void init() { 
    197       resumption_token_elem = getOAIResumptionTokenXML(); 
    198     } 
    199     public static String getOAIVersion() { 
    200       return oai_version; 
    201     } 
     154  //system-dependent file separator, maybe '/' or '\' 
     155  public static final String FILE_SEPARATOR = File.separator; 
     156  public static final String OAI_VERSION1 = "1.0"; 
     157  public static final String OAI_VERSION2 = "2.0"; 
     158  /*************************above are final values****************************/ 
     159     
     160  public static Element resumption_token_elem = null; 
     161  //used when saving the token file 
     162  public static File resumption_token_file = null; 
     163  //public static ArrayList token_list = new ArrayList(); 
     164     
     165  //initialized in getOAIConfigXML() 
     166  public static Element oai_config_elem = null; 
     167     
     168  //stores the date format "yyyy-MM-ddTHH:mm:ssZ" 
     169  public static String granularity = ""; 
     170 
     171  // http://www.openarchives.org/OAI/openarchivesprotocol.html#DatestampsRequests  
     172  // specifies that all repositories must support YYYY-MM-DD (yyyy-MM-dd in Java) 
     173  // this would be in addition to the other (optional) granularity of above that  
     174  // a repository may additionally choose to support. 
     175  public static final String default_granularity = "yyyy-MM-dd"; 
     176 
     177  //this value is overriden in getOAIConfigXML() 
     178  public static long token_expiration = 7200; 
     179     
     180  /** which version of oai that this oaiserver supports; default is 2.0  
     181   *  initialized in getOAIConfigXML() 
     182   */ 
     183  public static String oai_version = "2.0"; 
     184  public static String baseURL = ""; 
     185     
     186  /**response owner document */ 
     187  public static Document response_doc = new XMLConverter().newDOM();  
     188     
     189  public static String[] special_char = {"/", "?", "#", "=", "&", ":", ";", " ", "%", "+"}; 
     190  public static String[] escape_sequence = {"%2F", "%3F", "%23", "%3D", "%26", "%3A", "%3B", "%20", "%25", "%2B"}; 
     191  //    /** key=special character; value=escaped sequence */ 
     192  //    public static HashMap encode_map = new HashMap(); 
     193  //    /** key=escaped sequence; value=special character */ 
     194  //    public static HashMap decode_map = new HashMap(); 
     195 
     196  public static void init() { 
     197    resumption_token_elem = getOAIResumptionTokenXML(); 
     198  } 
     199  public static String getOAIVersion() { 
     200    return oai_version; 
     201  } 
    202202     
    203     public static String getBaseURL() { 
    204         return baseURL; 
    205     } 
     203  public static String getBaseURL() { 
     204    return baseURL; 
     205  } 
    206206     
    207     public static Element createElement(String tag_name) { 
    208       return response_doc.createElement(tag_name); 
    209     } 
    210     /**Compose a response element used when OAIPMH service sending responses thru  
    211      * ServiceCluster and MessageRouter, as they automatically wrap a message element 
    212      * on this response element 
    213      */ 
    214     public static Element getResponse(Element core_msg) { 
    215       Element res = createElement(RESPONSE); 
    216       res.appendChild(response_doc.importNode(core_msg, true)); 
    217       return res; 
    218     } 
    219     /** Read in OAIResumptionToken.xml (residing web/WEB-INF/classes/) */  
    220     public static Element getOAIResumptionTokenXML() {      
    221        
    222       // The system environment variable $GSDL3HOME(ends ../web) does not contain the file separator  
    223       resumption_token_file = new File(GlobalProperties.getGSDL3Home() + FILE_SEPARATOR + 
    224           "WEB-INF" + FILE_SEPARATOR + "classes" +FILE_SEPARATOR + "OAIResumptionToken.xml"); 
    225       if (resumption_token_file.exists()) { 
    226         Document token_doc = parseXMLFile(resumption_token_file); 
    227         if (token_doc != null) { 
    228           resumption_token_elem = token_doc.getDocumentElement(); 
    229         } else { 
    230           logger.error("Fail to parse resumption token file OAIReceptionToken.xml."); 
    231           return null; 
    232         } 
    233         //remove all expired tokens 
    234         clearExpiredTokens(); 
    235         return resumption_token_elem;   
    236       } 
    237       //if resumption_token_file does not exist         
    238       logger.info("resumption token file: "+ resumption_token_file.getPath()+" not found! create an empty one."); 
    239       resumption_token_elem = createElement(OAI_RESUMPTION_TOKENS); 
     207  public static Element createElement(String tag_name) { 
     208    return response_doc.createElement(tag_name); 
     209  } 
     210  /**Compose a response element used when OAIPMH service sending responses thru  
     211   * ServiceCluster and MessageRouter, as they automatically wrap a message element 
     212   * on this response element 
     213   */ 
     214  public static Element getResponse(Element core_msg) { 
     215    Element res = createElement(RESPONSE); 
     216    res.appendChild(response_doc.importNode(core_msg, true)); 
     217    return res; 
     218  } 
     219  /** Read in OAIResumptionToken.xml (residing web/WEB-INF/classes/) */  
     220  public static Element getOAIResumptionTokenXML() {      
     221       
     222    // The system environment variable $GSDL3HOME(ends ../web) does not contain the file separator  
     223    resumption_token_file = new File(GlobalProperties.getGSDL3Home() + FILE_SEPARATOR + 
     224                     "WEB-INF" + FILE_SEPARATOR + "classes" +FILE_SEPARATOR + "OAIResumptionToken.xml"); 
     225    if (resumption_token_file.exists()) { 
     226      Document token_doc = parseXMLFile(resumption_token_file); 
     227      if (token_doc != null) { 
     228    resumption_token_elem = token_doc.getDocumentElement(); 
     229      } else { 
     230    logger.error("Fail to parse resumption token file OAIReceptionToken.xml."); 
     231    return null; 
     232      } 
     233      //remove all expired tokens 
     234      clearExpiredTokens(); 
     235      return resumption_token_elem;   
     236    } 
     237    //if resumption_token_file does not exist         
     238    logger.info("resumption token file: "+ resumption_token_file.getPath()+" not found! create an empty one."); 
     239    resumption_token_elem = createElement(OAI_RESUMPTION_TOKENS); 
     240    saveOAIResumptionTokenXML(resumption_token_elem); 
     241    return resumption_token_elem; 
     242  } 
     243  public static void saveOAIResumptionTokenXML(Element token_elem) {      
     244    if(writeXMLFile(resumption_token_file, token_elem.getOwnerDocument()) == false) { 
     245      logger.error("Fail to save the resumption token file"); 
     246    } 
     247  } 
     248  public static void clearExpiredTokens() { 
     249    boolean token_deleted = false; 
     250    NodeList tokens = GSXML.getChildrenByTagName(resumption_token_elem, RESUMPTION_TOKEN); 
     251    for (int i=0; i<tokens.getLength(); i++) { 
     252      Element token_elem = (Element)tokens.item(i); 
     253      String expire_str = token_elem.getAttribute(EXPIRATION_DATE); 
     254      long datestamp = getTime(expire_str); // expire_str is in milliseconds 
     255      if(datestamp < System.currentTimeMillis()) { 
     256    resumption_token_elem.removeChild(token_elem); 
     257    token_elem = null; 
     258    token_deleted = true; 
     259      } 
     260    }  
     261       
     262    if(token_deleted) { 
    240263      saveOAIResumptionTokenXML(resumption_token_elem); 
    241       return resumption_token_elem; 
    242     } 
    243     public static void saveOAIResumptionTokenXML(Element token_elem) {      
    244       if(writeXMLFile(resumption_token_file, token_elem.getOwnerDocument()) == false) { 
    245         logger.error("Fail to save the resumption token file"); 
    246       } 
    247     } 
    248     public static void clearExpiredTokens() { 
    249       boolean token_deleted = false; 
    250       NodeList tokens = GSXML.getChildrenByTagName(resumption_token_elem, RESUMPTION_TOKEN); 
    251       for (int i=0; i<tokens.getLength(); i++) { 
    252         Element token_elem = (Element)tokens.item(i); 
    253         String expire_str = token_elem.getAttribute(EXPIRATION_DATE); 
    254         long datestamp = getTime(expire_str); // expire_str is in milliseconds 
    255         if(datestamp < System.currentTimeMillis()) { 
    256           resumption_token_elem.removeChild(token_elem); 
    257           token_elem = null; 
    258           token_deleted = true; 
    259         } 
    260       }  
    261        
    262       if(token_deleted) { 
    263         saveOAIResumptionTokenXML(resumption_token_elem); 
    264       } 
    265     } 
    266     public static boolean containsToken(String token) { 
    267       NodeList tokens = GSXML.getChildrenByTagName(resumption_token_elem, OAIXML.RESUMPTION_TOKEN); 
    268       for (int i=0; i<tokens.getLength(); i++) { 
    269         if(token.equals(GSXML.getNodeText((Element)tokens.item(i)).trim() )) 
    270           return true; 
    271       } 
    272       return false; 
    273     } 
    274     public static void addToken(Element token) { 
    275       Document doc = resumption_token_elem.getOwnerDocument(); 
    276       resumption_token_elem.appendChild(duplicateElement(doc, token, true)); 
    277       saveOAIResumptionTokenXML(resumption_token_elem); 
    278     } 
    279     public static void addToken(String token) { 
    280       Element te = resumption_token_elem.getOwnerDocument().createElement(OAIXML.RESUMPTION_TOKEN); 
    281       //add expiration att 
    282       resumption_token_elem.appendChild(te); 
    283       saveOAIResumptionTokenXML(resumption_token_elem); 
    284     } 
    285     public static boolean removeToken(String token) { 
    286       NodeList tokens = GSXML.getChildrenByTagName(resumption_token_elem, OAIXML.RESUMPTION_TOKEN); 
    287       int num_tokens = tokens.getLength(); 
    288       for (int i=0; i<num_tokens; i++) { 
    289           Element e = (Element)(tokens.item(i)); 
    290           if(token.equals(GSXML.getNodeText(e))) { 
    291             resumption_token_elem.removeChild(e); 
    292             saveOAIResumptionTokenXML(resumption_token_elem); 
    293             return true; 
    294           } 
    295       } 
    296       return false;       
    297     } 
    298     /** Read in OAIConfig.xml (residing web/WEB-INF/classes/) and use it to configure the receptionist etc. 
    299      *  the oai_version and baseURL variables are also set in here.  
    300      *  The init() method is also called in here. */  
    301     public static Element getOAIConfigXML() { 
    302       init(); 
     264    } 
     265  } 
     266  public static boolean containsToken(String token) { 
     267    NodeList tokens = GSXML.getChildrenByTagName(resumption_token_elem, OAIXML.RESUMPTION_TOKEN); 
     268    for (int i=0; i<tokens.getLength(); i++) { 
     269      if(token.equals(GSXML.getNodeText((Element)tokens.item(i)).trim() )) 
     270    return true; 
     271    } 
     272    return false; 
     273  } 
     274  public static void addToken(Element token) { 
     275    Document doc = resumption_token_elem.getOwnerDocument(); 
     276    resumption_token_elem.appendChild(duplicateElement(doc, token, true)); 
     277    saveOAIResumptionTokenXML(resumption_token_elem); 
     278  } 
     279  public static void addToken(String token) { 
     280    Element te = resumption_token_elem.getOwnerDocument().createElement(OAIXML.RESUMPTION_TOKEN); 
     281    //add expiration att 
     282    resumption_token_elem.appendChild(te); 
     283    saveOAIResumptionTokenXML(resumption_token_elem); 
     284  } 
     285  public static boolean removeToken(String token) { 
     286    NodeList tokens = GSXML.getChildrenByTagName(resumption_token_elem, OAIXML.RESUMPTION_TOKEN); 
     287    int num_tokens = tokens.getLength(); 
     288    for (int i=0; i<num_tokens; i++) { 
     289      Element e = (Element)(tokens.item(i)); 
     290      if(token.equals(GSXML.getNodeText(e))) { 
     291    resumption_token_elem.removeChild(e); 
     292    saveOAIResumptionTokenXML(resumption_token_elem); 
     293    return true; 
     294      } 
     295    } 
     296    return false;       
     297  } 
     298  /** Read in OAIConfig.xml (residing web/WEB-INF/classes/) and use it to configure the receptionist etc. 
     299   *  the oai_version and baseURL variables are also set in here.  
     300   *  The init() method is also called in here. */  
     301  public static Element getOAIConfigXML() { 
     302    init(); 
    303303      
    304       // The system environment variable $GSDL3HOME(ends ../web) does not contain the file separator  
    305       File oai_config_file = new File(GlobalProperties.getGSDL3Home() + FILE_SEPARATOR + 
    306           "WEB-INF" + FILE_SEPARATOR + "classes" +FILE_SEPARATOR + "OAIConfig.xml"); 
    307       if (!oai_config_file.exists()) { 
    308         logger.error(" oai config file: "+oai_config_file.getPath()+" not found!"); 
    309         return null; 
    310       } 
    311       Document oai_config_doc = parseXMLFile(oai_config_file); 
    312       if (oai_config_doc != null) { 
    313         oai_config_elem = oai_config_doc.getDocumentElement(); 
    314       } else { 
    315         logger.error("Fail to parse oai config file OAIConfig.xml."); 
    316         return null; 
    317       } 
    318        
    319       //initialize oai_version 
    320       Element protocol_version = (Element)GSXML.getChildByTagName(oai_config_elem, PROTOCOL_VERSION); 
    321       oai_version = GSXML.getNodeText(protocol_version).trim(); 
    322  
    323       // initialize baseURL 
    324       Element base_url_elem = (Element)GSXML.getChildByTagName(oai_config_elem, BASE_URL); 
    325       baseURL = GSXML.getNodeText(base_url_elem); 
     304    // The system environment variable $GSDL3HOME(ends ../web) does not contain the file separator  
     305    File oai_config_file = new File(GlobalProperties.getGSDL3Home() + FILE_SEPARATOR + 
     306                    "WEB-INF" + FILE_SEPARATOR + "classes" +FILE_SEPARATOR + "OAIConfig.xml"); 
     307    if (!oai_config_file.exists()) { 
     308      logger.error(" oai config file: "+oai_config_file.getPath()+" not found!"); 
     309      return null; 
     310    } 
     311    Document oai_config_doc = parseXMLFile(oai_config_file); 
     312    if (oai_config_doc != null) { 
     313      oai_config_elem = oai_config_doc.getDocumentElement(); 
     314    } else { 
     315      logger.error("Fail to parse oai config file OAIConfig.xml."); 
     316      return null; 
     317    } 
     318       
     319    //initialize oai_version 
     320    Element protocol_version = (Element)GSXML.getChildByTagName(oai_config_elem, PROTOCOL_VERSION); 
     321    oai_version = GSXML.getNodeText(protocol_version).trim(); 
     322 
     323    // initialize baseURL 
     324    Element base_url_elem = (Element)GSXML.getChildByTagName(oai_config_elem, BASE_URL); 
     325    baseURL = GSXML.getNodeText(base_url_elem); 
    326326       
    327       //initialize token_expiration 
    328       Element expiration = (Element)GSXML.getChildByTagName(oai_config_elem, RESUMPTION_TOKEN_EXPIRATION); 
    329       String expire_str = GSXML.getNodeText(expiration).trim(); 
    330       if (expiration != null && !expire_str.equals("")) { 
    331         token_expiration = Long.parseLong(expire_str); 
    332       } 
    333        
    334       // read granularity from the config file 
    335       Element granu_elem = (Element)GSXML.getChildByTagName(oai_config_elem, GRANULARITY); 
    336       //initialize the granu_str which might be used by other methods (eg, getDate()) 
    337       granularity = GSXML.getNodeText(granu_elem).trim(); 
    338  
    339       //change "yyyy-MM-ddTHH:mm:ssZ" to "yyyy-MM-dd'T'HH:mm:ss'Z'" 
    340       granularity = granularity.replaceAll("T", "'T'"); 
    341       granularity = granularity.replaceAll("Z", "'Z'"); 
    342       granularity = granularity.replaceAll("YYYY", "yyyy").replaceAll("DD", "dd").replaceAll("hh", "HH"); 
    343       return oai_config_elem; 
    344     } 
     327    //initialize token_expiration 
     328    Element expiration = (Element)GSXML.getChildByTagName(oai_config_elem, RESUMPTION_TOKEN_EXPIRATION); 
     329    String expire_str = GSXML.getNodeText(expiration).trim(); 
     330    if (expiration != null && !expire_str.equals("")) { 
     331      token_expiration = Long.parseLong(expire_str); 
     332    } 
     333       
     334    // read granularity from the config file 
     335    Element granu_elem = (Element)GSXML.getChildByTagName(oai_config_elem, GRANULARITY); 
     336    //initialize the granu_str which might be used by other methods (eg, getDate()) 
     337    granularity = GSXML.getNodeText(granu_elem).trim(); 
     338 
     339    //change "yyyy-MM-ddTHH:mm:ssZ" to "yyyy-MM-dd'T'HH:mm:ss'Z'" 
     340    granularity = granularity.replaceAll("T", "'T'"); 
     341    granularity = granularity.replaceAll("Z", "'Z'"); 
     342    granularity = granularity.replaceAll("YYYY", "yyyy").replaceAll("DD", "dd").replaceAll("hh", "HH"); 
     343    return oai_config_elem; 
     344  } 
    345345 
    346346  public static String[] getMetadataMapping(Element metadata_format) { 
     
    363363  } 
    364364   
    365     public static String[] getGlobalMetadataMapping(String prefix) { 
    366       Element list_meta_formats = (Element)GSXML.getChildByTagName(oai_config_elem, LIST_METADATA_FORMATS); 
    367       if(list_meta_formats == null) { 
    368         return null; 
    369       } 
    370       Element metadata_format = GSXML.getNamedElement(list_meta_formats, METADATA_FORMAT, METADATA_PREFIX, prefix); 
    371       if(metadata_format == null) { 
    372         return null; 
    373       } 
    374       return getMetadataMapping(metadata_format); 
    375     } 
    376  
    377      
    378     public static long getTokenExpiration() { 
    379     return token_expiration*1000; // in milliseconds 
    380     } 
    381  
    382     /** TODO: returns a basic response for appropriate oai version 
    383      *   
    384      */ 
    385     public static  Element createBasicResponse(String verb, String[] pairs) { 
    386  
    387       Element response = createResponseHeader(verb); 
    388        
    389       //set the responseDate and request elements accordingly 
    390       Element request_elem = (Element)GSXML.getChildByTagName(response, REQUEST); 
    391       if (verb.equals("")) { 
    392         request_elem.setAttribute(VERB, verb); 
    393       } 
    394       int num_pairs = (pairs==null)? 0 : pairs.length; 
    395       for (int i=num_pairs - 1; i>=0; i--) { 
    396         int index = pairs[i].indexOf("="); 
    397         if (index != -1) { 
    398           String[] strs = pairs[i].split("="); 
    399           if(strs != null && strs.length == 2) { 
    400             request_elem.setAttribute(strs[0], oaiDecode(strs[1])); 
    401           } 
    402         } 
    403       }//end of for() 
    404        
    405       GSXML.setNodeText(request_elem, baseURL); 
    406        
    407       Node resp_date = GSXML.getChildByTagName(response, RESPONSE_DATE); 
    408       if (resp_date != null) { 
    409         GSXML.setNodeText((Element)resp_date, getCurrentUTCTime()); 
    410       } 
    411  
    412       return response; 
    413     } 
    414     /** @param error_code the value of the code attribute 
    415      *  @param error_text the node text of the error element 
    416      *  @return an oai error element  
    417      *  Used by receptionist 
    418      */ 
    419     public static Element createErrorElement(String error_code, String error_text) { 
    420       Element error = createElement(ERROR); 
    421       error.setAttribute(CODE, error_code); 
    422       GSXML.setNodeText(error, error_text); 
    423       return error; 
    424     } 
    425  
    426     /** convert the escaped sequences (eg, '%3A') of those special characters back to their 
    427      *  original form (eg, ':').  
    428      */ 
    429     public static String oaiDecode(String escaped_str) { 
    430       logger.info("oaiDecode() " +escaped_str); 
    431       for (int i=0; i<special_char.length; i++) { 
    432         if (escaped_str.indexOf(escape_sequence[i]) != -1) { 
    433           escaped_str = escaped_str.replaceAll(escape_sequence[i], special_char[i]); 
    434         } 
    435       } 
    436       //escaped_str = escaped_str.replaceAll("%3A", ":"); 
    437       return escaped_str;         
    438     } 
    439     /** convert those special characters (eg, ':') to their 
    440      *  escaped sequences (eg, '%3A').  
    441      */ 
    442     public static String oaiEncode(String original_str) { 
    443       logger.info("oaiEncode() " + original_str);       
    444       for (int i=0; i<special_char.length; i++) { 
    445         if (original_str.indexOf(special_char[i]) != -1) { 
    446           original_str = original_str.replaceAll(special_char[i], escape_sequence[i]); 
    447         } 
    448       } 
    449       //original_str = original_str.replaceAll(":", "%3A"); 
    450       return original_str;   
    451     } 
    452     /** convert YYYY-MM_DDThh:mm:ssZ to yyyy-MM-ddTHH:mm:ssZ 
    453      */ 
    454     public static String convertToJava(String oai_format) { 
    455       oai_format = oai_format.replaceAll("YYYY", "yyyy").replaceAll("DD", "dd").replaceAll("hh", "HH"); 
    456       return oai_format; 
    457     } 
    458     /** convert yyyy-MM-ddTHH:mm:ssZ to YYYY-MM_DDThh:mm:ssZ 
    459      */ 
    460     public static String convertToOAI(String java_format) { 
    461       java_format = java_format.replaceAll("yyyy", "YYYY").replaceAll("dd", "DD").replaceAll("HH", "hh"); 
    462       return java_format;       
    463     } 
    464     public static String getCurrentUTCTime() { 
    465       Date current_utc = new Date(System.currentTimeMillis()); 
    466       //granularity is in the form: yyyy-MM-dd'T'HH:mm:ss'Z ' 
    467       DateFormat formatter = new SimpleDateFormat(granularity); 
    468       return formatter.format(current_utc); 
    469     } 
    470     /** get a Date object from a Date format pattern string 
    471      * 
    472      * @param pattern - in the form: 2007-06-14T16:48:25Z, for example. 
    473      * @return a Date object - null if the pattern is not in the specified form 
    474      */ 
    475  
    476     public static Date getDate(String pattern) { 
    477       if (pattern == null || pattern.equals("")) { 
    478         return null; 
    479       } 
    480       Date date = null; 
    481 //      String str = pattern.replaceAll("T", " "); 
    482 //      str = str.replaceAll("Z", ""); 
    483       SimpleDateFormat sdf = null; 
    484       try { 
    485         sdf = new SimpleDateFormat(granularity); 
    486         date = sdf.parse(pattern); 
    487       } catch(Exception e) { 
    488       if(!default_granularity.equals(granularity)) { // try validating against default granularity 
    489           try { 
    490           date = null; 
    491           sdf = null; 
    492           sdf = new SimpleDateFormat(default_granularity); 
    493           date = sdf.parse(pattern); 
    494           } catch(Exception ex) { 
    495           logger.error("invalid date format: " + pattern); 
    496           return null; 
    497           } 
    498       } else { 
    499           logger.error("invalid date format: " + pattern); 
    500           return null; 
    501       } 
    502       } 
    503       return date; 
    504     } 
    505     /** get the million second value from a string representing time in a pattern 
    506      * (eg, 2007-06-14T16:48:25Z) 
    507      */ 
    508     public static long getTime(String pattern) { 
    509       if (pattern == null || pattern.equals("")) { 
    510         return -1; 
    511       } 
    512       Date date = null; 
    513       SimpleDateFormat sdf = null; 
    514       try { 
    515         //granularity is a global variable in the form: yyyy-MM-ddTHH:mm:ssZ  
    516         sdf = new SimpleDateFormat(granularity); 
    517         date = sdf.parse(pattern); 
    518       } catch(Exception e) { 
    519       if(!default_granularity.equals(granularity)) { // try validating against default granularity 
    520           try { 
    521           date = null; 
    522           sdf = null; 
    523           sdf = new SimpleDateFormat(default_granularity); 
    524           date = sdf.parse(pattern); 
    525           } catch(Exception ex) { 
    526           logger.error("invalid date format: " + pattern); 
    527           return -1; 
    528           } 
    529       } else { 
    530           logger.error("invalid date format: " + pattern); 
    531           return -1; 
    532       }         
    533       } 
    534       return date.getTime(); 
    535     }     
    536     /** get the string representation of a time from a long value(long type) 
    537      */ 
    538     public static String getTime(long milliseconds) { 
    539       Date date = new Date(milliseconds); 
    540       SimpleDateFormat sdf = new SimpleDateFormat(granularity); 
    541       return sdf.format(date); 
    542     }     
    543     public static Element createResponseHeader(String verb) { 
    544       String tag_name = (oai_version.equals(OAI_VERSION2))? OAI_DASH_PMH : verb; 
    545       Element oai = response_doc.createElement(tag_name); 
    546       Element resp_date = response_doc.createElement(RESPONSE_DATE); 
    547       Element req = response_doc.createElement(REQUEST); 
    548       oai.appendChild(resp_date); 
    549       oai.appendChild(req); 
    550  
    551       if(oai_version.equals(OAI_VERSION2)) { 
    552         oai.setAttribute("xmlns", "http://www.openarchives.org/OAI/2.0/"); 
    553         oai.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); 
    554         oai.setAttribute("xsi:schemaLocation", "http://www.openarchives.org/OAI/2.0/ \n http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd"); 
     365  public static String[] getGlobalMetadataMapping(String prefix) { 
     366    Element list_meta_formats = (Element)GSXML.getChildByTagName(oai_config_elem, LIST_METADATA_FORMATS); 
     367    if(list_meta_formats == null) { 
     368      return null; 
     369    } 
     370    Element metadata_format = GSXML.getNamedElement(list_meta_formats, METADATA_FORMAT, METADATA_PREFIX, prefix); 
     371    if(metadata_format == null) { 
     372      return null; 
     373    } 
     374    return getMetadataMapping(metadata_format); 
     375  } 
     376 
     377     
     378  public static long getTokenExpiration() { 
     379    return token_expiration*1000; // in milliseconds 
     380  } 
     381 
     382  /** TODO: returns a basic response for appropriate oai version 
     383   *   
     384   */ 
     385  public static  Element createBasicResponse(String verb, String[] pairs) { 
     386 
     387    Element response = createResponseHeader(verb); 
     388       
     389    //set the responseDate and request elements accordingly 
     390    Element request_elem = (Element)GSXML.getChildByTagName(response, REQUEST); 
     391    if (verb.equals("")) { 
     392      request_elem.setAttribute(VERB, verb); 
     393    } 
     394    int num_pairs = (pairs==null)? 0 : pairs.length; 
     395    for (int i=num_pairs - 1; i>=0; i--) { 
     396      int index = pairs[i].indexOf("="); 
     397      if (index != -1) { 
     398    String[] strs = pairs[i].split("="); 
     399    if(strs != null && strs.length == 2) { 
     400      request_elem.setAttribute(strs[0], oaiDecode(strs[1])); 
     401    } 
     402      } 
     403    }//end of for() 
     404       
     405    GSXML.setNodeText(request_elem, baseURL); 
     406       
     407    Node resp_date = GSXML.getChildByTagName(response, RESPONSE_DATE); 
     408    if (resp_date != null) { 
     409      GSXML.setNodeText((Element)resp_date, getCurrentUTCTime()); 
     410    } 
     411 
     412    return response; 
     413  } 
     414  /** @param error_code the value of the code attribute 
     415   *  @param error_text the node text of the error element 
     416   *  @return an oai error element  
     417   *  Used by receptionist 
     418   */ 
     419  public static Element createErrorElement(String error_code, String error_text) { 
     420    Element error = createElement(ERROR); 
     421    error.setAttribute(CODE, error_code); 
     422    GSXML.setNodeText(error, error_text); 
     423    return error; 
     424  } 
     425 
     426  /** convert the escaped sequences (eg, '%3A') of those special characters back to their 
     427   *  original form (eg, ':').  
     428   */ 
     429  public static String oaiDecode(String escaped_str) { 
     430    logger.info("oaiDecode() " +escaped_str); 
     431    for (int i=0; i<special_char.length; i++) { 
     432      if (escaped_str.indexOf(escape_sequence[i]) != -1) { 
     433    escaped_str = escaped_str.replaceAll(escape_sequence[i], special_char[i]); 
     434      } 
     435    } 
     436    //escaped_str = escaped_str.replaceAll("%3A", ":"); 
     437    return escaped_str;         
     438  } 
     439  /** convert those special characters (eg, ':') to their 
     440   *  escaped sequences (eg, '%3A').  
     441   */ 
     442  public static String oaiEncode(String original_str) { 
     443    logger.info("oaiEncode() " + original_str);       
     444    for (int i=0; i<special_char.length; i++) { 
     445      if (original_str.indexOf(special_char[i]) != -1) { 
     446    original_str = original_str.replaceAll(special_char[i], escape_sequence[i]); 
     447      } 
     448    } 
     449    //original_str = original_str.replaceAll(":", "%3A"); 
     450    return original_str;   
     451  } 
     452  /** convert YYYY-MM_DDThh:mm:ssZ to yyyy-MM-ddTHH:mm:ssZ 
     453   */ 
     454  public static String convertToJava(String oai_format) { 
     455    oai_format = oai_format.replaceAll("YYYY", "yyyy").replaceAll("DD", "dd").replaceAll("hh", "HH"); 
     456    return oai_format; 
     457  } 
     458  /** convert yyyy-MM-ddTHH:mm:ssZ to YYYY-MM_DDThh:mm:ssZ 
     459   */ 
     460  public static String convertToOAI(String java_format) { 
     461    java_format = java_format.replaceAll("yyyy", "YYYY").replaceAll("dd", "DD").replaceAll("HH", "hh"); 
     462    return java_format;       
     463  } 
     464  public static String getCurrentUTCTime() { 
     465    Date current_utc = new Date(System.currentTimeMillis()); 
     466    //granularity is in the form: yyyy-MM-dd'T'HH:mm:ss'Z ' 
     467    DateFormat formatter = new SimpleDateFormat(granularity); 
     468    return formatter.format(current_utc); 
     469  } 
     470  /** get a Date object from a Date format pattern string 
     471   * 
     472   * @param pattern - in the form: 2007-06-14T16:48:25Z, for example. 
     473   * @return a Date object - null if the pattern is not in the specified form 
     474   */ 
     475 
     476  public static Date getDate(String pattern) { 
     477    if (pattern == null || pattern.equals("")) { 
     478      return null; 
     479    } 
     480    Date date = null; 
     481    //      String str = pattern.replaceAll("T", " "); 
     482    //      str = str.replaceAll("Z", ""); 
     483    SimpleDateFormat sdf = null; 
     484    try { 
     485      sdf = new SimpleDateFormat(granularity); 
     486      date = sdf.parse(pattern); 
     487    } catch(Exception e) { 
     488      if(!default_granularity.equals(granularity)) { // try validating against default granularity 
     489    try { 
     490      date = null; 
     491      sdf = null; 
     492      sdf = new SimpleDateFormat(default_granularity); 
     493      date = sdf.parse(pattern); 
     494    } catch(Exception ex) { 
     495      logger.error("invalid date format: " + pattern); 
     496      return null; 
     497    } 
    555498      } else { 
    556         oai.setAttribute("xmlns", "http://www.openarchives.com/OAI/1.1/OAI_" + verb); 
    557         oai.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); 
    558         oai.setAttribute("xsi:schemaLocation", "http://www.openarchives.org/OAI/1.1/OAI_" + verb + "\n http://www.openarchives.org/OAI/1.1/OAI_" + verb + ".xsd"); 
    559       } 
    560       return oai; 
    561     } 
    562     public static Element getMetadataPrefixElement(String tag_name, String version) { 
    563       //examples of tag_name: dc, oai_dc:dc, etc. 
    564       Element oai = response_doc.createElement(tag_name); 
    565       if (version.equals(OAI_VERSION2)) { 
    566         oai.setAttribute("xmlns:oai_dc", "http://www.openarchives.org/OAI/2.0/oai_dc/"); 
    567         oai.setAttribute("xmlns:dc", "http://purl.org/dc/elements/1.1/"); 
    568         oai.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); 
    569         oai.setAttribute("xsi:schemaLocation", "http://www.openarchives.org/OAI/2.0/oai_dc/ \n http://www.openarchives.org/OAI/2.0/oai_dc.xsd"); 
     499    logger.error("invalid date format: " + pattern); 
     500    return null; 
     501      } 
     502    } 
     503    return date; 
     504  } 
     505  /** get the million second value from a string representing time in a pattern 
     506   * (eg, 2007-06-14T16:48:25Z) 
     507   */ 
     508  public static long getTime(String pattern) { 
     509    if (pattern == null || pattern.equals("")) { 
     510      return -1; 
     511    } 
     512    Date date = null; 
     513    SimpleDateFormat sdf = null; 
     514    try { 
     515      //granularity is a global variable in the form: yyyy-MM-ddTHH:mm:ssZ  
     516      sdf = new SimpleDateFormat(granularity); 
     517      date = sdf.parse(pattern); 
     518    } catch(Exception e) { 
     519      if(!default_granularity.equals(granularity)) { // try validating against default granularity 
     520    try { 
     521      date = null; 
     522      sdf = null; 
     523      sdf = new SimpleDateFormat(default_granularity); 
     524      date = sdf.parse(pattern); 
     525    } catch(Exception ex) { 
     526      logger.error("invalid date format: " + pattern); 
     527      return -1; 
     528    } 
    570529      } else { 
    571         oai.setAttribute("xmlns", "ttp://www.openarchives.com/OAI/1.1/"); 
    572         oai.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); 
    573         oai.setAttribute("xsi:schemaLocation", "http://www.openarchives.org/OAI/1.1/" + tag_name + ".xsd");         
    574       } 
    575        
    576       return oai; 
    577     } 
    578     public static HashMap<String, Node> getChildrenMapByTagName(Node n, String tag_name) { 
     530    logger.error("invalid date format: " + pattern); 
     531    return -1; 
     532      }         
     533    } 
     534    return date.getTime(); 
     535  }     
     536  /** get the string representation of a time from a long value(long type) 
     537   */ 
     538  public static String getTime(long milliseconds) { 
     539    Date date = new Date(milliseconds); 
     540    SimpleDateFormat sdf = new SimpleDateFormat(granularity); 
     541    return sdf.format(date); 
     542  }     
     543  public static Element createResponseHeader(String verb) { 
     544    String tag_name = (oai_version.equals(OAI_VERSION2))? OAI_DASH_PMH : verb; 
     545    Element oai = response_doc.createElement(tag_name); 
     546    Element resp_date = response_doc.createElement(RESPONSE_DATE); 
     547    Element req = response_doc.createElement(REQUEST); 
     548    oai.appendChild(resp_date); 
     549    oai.appendChild(req); 
     550 
     551    if(oai_version.equals(OAI_VERSION2)) { 
     552      oai.setAttribute("xmlns", "http://www.openarchives.org/OAI/2.0/"); 
     553      oai.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); 
     554      oai.setAttribute("xsi:schemaLocation", "http://www.openarchives.org/OAI/2.0/ \n http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd"); 
     555    } else { 
     556      oai.setAttribute("xmlns", "http://www.openarchives.com/OAI/1.1/OAI_" + verb); 
     557      oai.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); 
     558      oai.setAttribute("xsi:schemaLocation", "http://www.openarchives.org/OAI/1.1/OAI_" + verb + "\n http://www.openarchives.org/OAI/1.1/OAI_" + verb + ".xsd"); 
     559    } 
     560    return oai; 
     561  } 
     562  public static Element getMetadataPrefixElement(String tag_name, String version) { 
     563    //examples of tag_name: dc, oai_dc:dc, etc. 
     564    Element oai = response_doc.createElement(tag_name); 
     565    if (version.equals(OAI_VERSION2)) { 
     566      oai.setAttribute("xmlns:oai_dc", "http://www.openarchives.org/OAI/2.0/oai_dc/"); 
     567      oai.setAttribute("xmlns:dc", "http://purl.org/dc/elements/1.1/"); 
     568      oai.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); 
     569      oai.setAttribute("xsi:schemaLocation", "http://www.openarchives.org/OAI/2.0/oai_dc/ \n http://www.openarchives.org/OAI/2.0/oai_dc.xsd"); 
     570    } else { 
     571      oai.setAttribute("xmlns", "ttp://www.openarchives.com/OAI/1.1/"); 
     572      oai.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); 
     573      oai.setAttribute("xsi:schemaLocation", "http://www.openarchives.org/OAI/1.1/" + tag_name + ".xsd");         
     574    } 
     575       
     576    return oai; 
     577  } 
     578  public static HashMap<String, Node> getChildrenMapByTagName(Node n, String tag_name) { 
    579579     
    580     HashMap<String, Node> map= new HashMap<String, Node>(); 
    581     Node child = n.getFirstChild(); 
    582     while (child!=null) { 
    583         String name = child.getNodeName(); 
     580    HashMap<String, Node> map= new HashMap<String, Node>(); 
     581    Node child = n.getFirstChild(); 
     582    while (child!=null) { 
     583      String name = child.getNodeName(); 
    584584      if(name.equals(tag_name)) { 
    585           map.put(name, child); 
    586       } 
    587         child = child.getNextSibling(); 
    588     } 
    589     return map; 
    590     } 
    591      
    592     /** Duplicates an element */ 
    593     public static Element duplicateElement (Document owner, Element element, boolean with_attributes) { 
    594         return duplicateElementNS (owner, element, null, with_attributes); 
    595     } 
    596      
    597     /** Duplicates an element */ 
    598     public static Element duplicateElementNS (Document owner, 
    599     Element element, 
    600     String namespace_uri, 
    601     boolean with_attributes) { 
    602         Element duplicate; 
    603         if (namespace_uri == null) { 
    604             duplicate = owner.createElement (element.getTagName ()); 
    605         } else { 
    606             duplicate = owner.createElementNS (namespace_uri, element.getTagName ()); 
    607         } 
    608         // Copy element attributes 
    609         if (with_attributes) { 
    610             NamedNodeMap attributes = element.getAttributes (); 
    611             for (int i = 0; i < attributes.getLength (); i++) { 
    612                 Node attribute = attributes.item (i); 
    613                 duplicate.setAttribute (attribute.getNodeName (), attribute.getNodeValue ()); 
    614             } 
    615         } 
     585    map.put(name, child); 
     586      } 
     587      child = child.getNextSibling(); 
     588    } 
     589    return map; 
     590  } 
     591     
     592  /** Duplicates an element */ 
     593  public static Element duplicateElement (Document owner, Element element, boolean with_attributes) { 
     594    return duplicateElementNS (owner, element, null, with_attributes); 
     595  } 
     596     
     597  /** Duplicates an element */ 
     598  public static Element duplicateElementNS (Document owner, 
     599                        Element element, 
     600                        String namespace_uri, 
     601                        boolean with_attributes) { 
     602    Element duplicate; 
     603    if (namespace_uri == null) { 
     604      duplicate = owner.createElement (element.getTagName ()); 
     605    } else { 
     606      duplicate = owner.createElementNS (namespace_uri, element.getTagName ()); 
     607    } 
     608    // Copy element attributes 
     609    if (with_attributes) { 
     610      NamedNodeMap attributes = element.getAttributes (); 
     611      for (int i = 0; i < attributes.getLength (); i++) { 
     612    Node attribute = attributes.item (i); 
     613    duplicate.setAttribute (attribute.getNodeName (), attribute.getNodeValue ()); 
     614      } 
     615    } 
    616616         
    617         // Copy element children 
    618         NodeList children = element.getChildNodes (); 
    619         for (int i = 0; i < children.getLength (); i++) { 
    620             Node child = children.item (i); 
    621             duplicate.appendChild (owner.importNode (child, true)); 
    622         } 
     617    // Copy element children 
     618    NodeList children = element.getChildNodes (); 
     619    for (int i = 0; i < children.getLength (); i++) { 
     620      Node child = children.item (i); 
     621      duplicate.appendChild (owner.importNode (child, true)); 
     622    } 
    623623         
    624         return duplicate; 
    625     } 
    626  
    627     public static void copyElement(Element to, Element from, String elem_name) { 
    628        
    629       Document to_doc = to.getOwnerDocument(); 
    630       Node child = from.getFirstChild(); 
    631       while (child != null) { 
    632         if (child.getNodeName().equals(elem_name)) { 
    633           to.appendChild(to_doc.importNode(child, true)); 
    634           return; 
    635         } 
    636         child = child.getNextSibling(); 
    637       } 
    638     } 
    639  
    640     public static HashMap<String, String> getParamMap(NodeList params) { 
    641       HashMap<String, String> map = new HashMap<String, String>(); 
    642       for(int i=0; i<params.getLength(); i++) { 
    643         Element param = (Element)params.item(i); 
    644         String param_name = param.getAttribute(OAIXML.NAME); 
    645         String param_value = param.getAttribute(OAIXML.VALUE); 
    646         map.put(param_name, param_value); 
    647       } 
    648       return map; 
    649     } 
    650  
    651  
    652     /** Parse an XML document from a given file */ 
    653     static public Document parseXMLFile (File xml_file) { 
    654         // No file? No point trying! 
    655         if (xml_file.exists () == false) { 
    656             return null; 
    657         } 
    658         Document doc = null; 
    659         try { 
    660             doc = parseXML (new FileInputStream (xml_file)); 
    661         } 
    662         catch (Exception exception) { 
    663             logger.error(exception.toString()); 
    664             return null; 
    665         } 
    666         return doc; 
    667     } 
    668      
    669      
    670     /** Parse an XML document from a given input stream */ 
    671     static public Document parseXML (InputStream xml_input_stream) { 
    672         Document document = null; 
     624    return duplicate; 
     625  } 
     626 
     627  public static void copyElement(Element to, Element from, String elem_name) { 
     628       
     629    Document to_doc = to.getOwnerDocument(); 
     630    Node child = from.getFirstChild(); 
     631    while (child != null) { 
     632      if (child.getNodeName().equals(elem_name)) { 
     633    to.appendChild(to_doc.importNode(child, true)); 
     634    return; 
     635      } 
     636      child = child.getNextSibling(); 
     637    } 
     638  } 
     639 
     640  public static HashMap<String, String> getParamMap(NodeList params) { 
     641    HashMap<String, String> map = new HashMap<String, String>(); 
     642    for(int i=0; i<params.getLength(); i++) { 
     643      Element param = (Element)params.item(i); 
     644      String param_name = param.getAttribute(OAIXML.NAME); 
     645      String param_value = param.getAttribute(OAIXML.VALUE); 
     646      map.put(param_name, param_value); 
     647    } 
     648    return map; 
     649  } 
     650 
     651 
     652  /** Parse an XML document from a given file */ 
     653  static public Document parseXMLFile (File xml_file) { 
     654    // No file? No point trying! 
     655    if (xml_file.exists () == false) { 
     656      return null; 
     657    } 
     658    Document doc = null; 
     659    try { 
     660      doc = parseXML (new FileInputStream (xml_file)); 
     661    } 
     662    catch (Exception exception) { 
     663      logger.error(exception.toString()); 
     664      return null; 
     665    } 
     666    return doc; 
     667  } 
     668     
     669     
     670  /** Parse an XML document from a given input stream */ 
     671  static public Document parseXML (InputStream xml_input_stream) { 
     672    Document document = null; 
    673673         
    674         try { 
    675             InputStreamReader isr = new InputStreamReader (xml_input_stream, "UTF-8"); 
    676             Reader xml_reader = new BufferedReader (isr); 
    677             document = parseXML (xml_reader); 
    678             isr.close (); 
    679             xml_input_stream.close (); 
    680         } 
    681         catch (Exception exception) { 
    682             logger.error(exception.toString()); 
    683         } 
     674    try { 
     675      InputStreamReader isr = new InputStreamReader (xml_input_stream, "UTF-8"); 
     676      Reader xml_reader = new BufferedReader (isr); 
     677      document = parseXML (xml_reader); 
     678      isr.close (); 
     679      xml_input_stream.close (); 
     680    } 
     681    catch (Exception exception) { 
     682      logger.error(exception.toString()); 
     683    } 
    684684         
    685         return document; 
    686     } 
    687  
    688     /** Parse an XML document from a given reader */ 
    689     static public Document parseXML (Reader xml_reader) { 
    690         Document document = null; 
     685    return document; 
     686  } 
     687 
     688  /** Parse an XML document from a given reader */ 
     689  static public Document parseXML (Reader xml_reader) { 
     690    Document document = null; 
    691691         
    692         try { 
    693             InputSource isc       = new InputSource (xml_reader); 
    694             DOMParser parser      = new DOMParser (); 
    695             parser.setFeature ("http://xml.org/sax/features/validation", false); 
    696             parser.setFeature ("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); 
    697             // May or may not be ignored, the documentation for Xerces is contradictory. If it works then parsing -should- be faster. 
    698             parser.setFeature ("http://apache.org/xml/features/dom/defer-node-expansion", true); 
    699             parser.setFeature ("http://apache.org/xml/features/dom/include-ignorable-whitespace", false); 
    700             parser.parse (isc); 
    701             document = parser.getDocument (); 
    702         } 
    703         catch (SAXException exception) { 
    704             System.err.println ("SAX exception: " + exception.getMessage ()); 
    705             logger.error(exception.toString()); 
    706         } 
    707         catch (Exception exception) { 
    708             logger.error(exception.toString()); 
    709         } 
     692    try { 
     693      InputSource isc       = new InputSource (xml_reader); 
     694      DOMParser parser      = new DOMParser (); 
     695      parser.setFeature ("http://xml.org/sax/features/validation", false); 
     696      parser.setFeature ("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); 
     697      // May or may not be ignored, the documentation for Xerces is contradictory. If it works then parsing -should- be faster. 
     698      parser.setFeature ("http://apache.org/xml/features/dom/defer-node-expansion", true); 
     699      parser.setFeature ("http://apache.org/xml/features/dom/include-ignorable-whitespace", false); 
     700      parser.parse (isc); 
     701      document = parser.getDocument (); 
     702    } 
     703    catch (SAXException exception) { 
     704      System.err.println ("SAX exception: " + exception.getMessage ()); 
     705      logger.error(exception.toString()); 
     706    } 
     707    catch (Exception exception) { 
     708      logger.error(exception.toString()); 
     709    } 
    710710         
    711         return document; 
    712     } 
    713     /** Write an XML document to a given file */ 
    714     static public boolean writeXMLFile (File xml_file, Document document) { 
    715         try { 
    716             OutputStream os = new FileOutputStream (xml_file); 
    717             // Create an output format for our document. 
    718             OutputFormat f = new OutputFormat (document); 
    719             f.setEncoding ("UTF-8"); 
    720             f.setIndenting (true); 
    721             f.setLineWidth (0); // Why isn't this working! 
    722             f.setPreserveSpace (false); 
    723             // Create the necessary writer stream for serialization. 
    724             OutputStreamWriter osw = new OutputStreamWriter (os, "UTF-8"); 
    725             Writer w               = new BufferedWriter (osw); 
    726             // Generate a new serializer from the above. 
    727             XMLSerializer s        = new XMLSerializer (w, f); 
    728             s.asDOMSerializer (); 
    729             // Finally serialize the document to file. 
    730             s.serialize (document); 
    731             // And close. 
    732             os.close (); 
    733             return true; 
    734         } 
    735         catch (Exception exception) { 
    736             logger.error(exception.toString()); 
    737             return false; 
    738         } 
    739     } 
     711    return document; 
     712  } 
     713  /** Write an XML document to a given file */ 
     714  static public boolean writeXMLFile (File xml_file, Document document) { 
     715    try { 
     716      OutputStream os = new FileOutputStream (xml_file); 
     717      // Create an output format for our document. 
     718      OutputFormat f = new OutputFormat (document); 
     719      f.setEncoding ("UTF-8"); 
     720      f.setIndenting (true); 
     721      f.setLineWidth (0); // Why isn't this working! 
     722      f.setPreserveSpace (false); 
     723      // Create the necessary writer stream for serialization. 
     724      OutputStreamWriter osw = new OutputStreamWriter (os, "UTF-8"); 
     725      Writer w               = new BufferedWriter (osw); 
     726      // Generate a new serializer from the above. 
     727      XMLSerializer s        = new XMLSerializer (w, f); 
     728      s.asDOMSerializer (); 
     729      // Finally serialize the document to file. 
     730      s.serialize (document); 
     731      // And close. 
     732      os.close (); 
     733      return true; 
     734    } 
     735    catch (Exception exception) { 
     736      logger.error(exception.toString()); 
     737      return false; 
     738    } 
     739  } 
    740740     
    741741