/* * Collection.java * Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ package org.greenstone.gsdl3.collection; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; import java.util.ArrayList; import java.util.HashMap; import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; import org.greenstone.gsdl3.core.ModuleInterface; import org.greenstone.gsdl3.service.Authentication; import org.greenstone.gsdl3.util.CustomClassLoader; import org.greenstone.gsdl3.util.Dictionary; import org.greenstone.gsdl3.util.GSFile; import org.greenstone.gsdl3.util.GSXML; import org.greenstone.gsdl3.util.GSXSLT; import org.greenstone.gsdl3.util.OAIXML; import org.greenstone.gsdl3.util.SimpleMacroResolver; import org.greenstone.gsdl3.util.UserContext; import org.greenstone.gsdl3.util.XMLConverter; import org.greenstone.gsdl3.util.XMLTransformer; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; /** * Represents a collection in Greenstone. A collection is an extension of a * ServiceCluster - it has local data that the services use. * * @author Katherine Don * @see ModuleInterface */ public class Collection extends ServiceCluster { static Logger logger = Logger.getLogger(org.greenstone.gsdl3.collection.Collection.class.getName()); /** is this collection being tidied and therefore can support realistic book view? */ protected boolean useBook = false; /** * is this collection public or private - public collections will * appear on the home page, whereas private collections won't */ protected boolean is_public = true; /** collection type : mg, mgpp or lucene */ protected String col_type = ""; /** database type : gdbm, jdbm or sqlite */ protected String db_type = ""; /** time when this collection was built Used by RSS */ protected long lastmodified = 0; /** earliestDatestamp of this collection. Used by RSS. No longer used as fallback by OAI */ protected long earliestDatestamp = 0; /** Stores the default accessibility of guest users */ protected boolean _publicAccess = true; /** Stores the scope of any security rules (either collection or document) */ protected boolean _securityScopeCollection = true; protected boolean _humanVerify = false; protected boolean _useRecaptcha = false; // for human verify protected String _siteKey = null; // for recaptcha protected String _secretKey = null; // for recaptcha protected HashMap> _documentSets = new HashMap>(); protected ArrayList>> _securityExceptions = new ArrayList>>(); protected XMLTransformer transformer = null; /** same as setClusterName */ public void setCollectionName(String name) { setClusterName(name); } public Collection() { super(); this.description = this.desc_doc.createElement(GSXML.COLLECTION_ELEM); } /** * Configures the collection. * * gsdlHome and collectionName must be set before configure is called. * * the file buildcfg.xml is located in gsdlHome/collect/collectionName * collection metadata is obtained, and services loaded. * * @return true/false on success/fail */ public boolean configure() { if (this.site_home == null || this.cluster_name == null) { logger.error("Collection: site_home and collection_name must be set before configure called!"); return false; } // set up the class loader this.class_loader = new CustomClassLoader(this.getClass().getClassLoader(), GSFile.collectionResourceDir(this.site_home, this.cluster_name)); macro_resolver.addMacro("_httpcollection_", this.site_http_address + "/collect/" + this.cluster_name); Element coll_config_xml = loadCollConfigFile(); if (coll_config_xml == null) { logger.error("Collection: couldn't configure collection: " + this.cluster_name + ", " + "Couldn't load collection config file"); return false; } Element build_config_xml = loadBuildConfigFile(); if (build_config_xml == null) { logger.error("Collection: couldn't configure collection: " + this.cluster_name + ", " + "Couldn't load build config file"); return false; } GSXSLT.modifyCollectionConfigForDebug(coll_config_xml); // get the collection type attribute Element search = (Element) GSXML.getChildByTagName(coll_config_xml, GSXML.SEARCH_ELEM); if (search != null) { col_type = search.getAttribute(GSXML.TYPE_ATT); } Element browse = (Element) GSXML.getChildByTagName(coll_config_xml, GSXML.INFODB_ELEM); if (browse != null) { db_type = browse.getAttribute(GSXML.TYPE_ATT); } else { db_type = "gdbm"; //Default database type } this.description.setAttribute(GSXML.TYPE_ATT, col_type); this.description.setAttribute(GSXML.DB_TYPE_ATT, db_type); _globalFormat = (Element) GSXML.getChildByTagName(coll_config_xml, GSXML.FORMAT_ELEM); // process the metadata and display items and default library params super.configureLocalData(coll_config_xml); super.configureLocalData(build_config_xml); // get extra collection specific stuff findAndLoadInfo(coll_config_xml, build_config_xml); loadSecurityInformation(coll_config_xml); // do we have archives folder? File archives_folder = new File(GSFile.collectionArchiveDir(this.site_home, this.cluster_name)); if (!archives_folder.exists()) { this.description.setAttribute(GSXML.NO_ARCHIVES_ATT, "true"); } // now do the services configureServiceRacks(coll_config_xml, build_config_xml); return true; } public boolean useBook() { return useBook; } public boolean isPublic() { return is_public; } // Used by RSSRetrieve. No longer used by OAI Receptionist (as second fallback) public long getLastmodified() { return lastmodified; } // used by RSSRetrieve, no longer used as fallback by the OAIReceptionist public long getEarliestDatestamp() { return earliestDatestamp; } /** * load in the collection config file into a DOM Element */ protected Element loadCollConfigFile() { File coll_config_file = new File(GSFile.collectionConfigFile(this.site_home, this.cluster_name)); if (!coll_config_file.exists()) { return null; } // get the xml Document coll_config_doc = this.converter.getDOM(coll_config_file, CONFIG_ENCODING); Element coll_config_elem = null; if (coll_config_doc != null) { coll_config_elem = coll_config_doc.getDocumentElement(); } return coll_config_elem; } /** * load in the collection build config file into a DOM Element */ protected Element loadBuildConfigFile() { File build_config_file = new File(GSFile.collectionBuildConfigFile(this.site_home, this.cluster_name)); if (!build_config_file.exists()) { logger.error("Collection: couldn't configure collection: " + this.cluster_name + ", " + build_config_file + " does not exist"); return null; } Document build_config_doc = this.converter.getDOM(build_config_file, CONFIG_ENCODING); Element build_config_elem = null; if (build_config_doc != null) { build_config_elem = build_config_doc.getDocumentElement(); } lastmodified = build_config_file.lastModified(); return build_config_elem; } /** * find the metadata and display elems from the two config files and add it * to the appropriate lists */ protected boolean findAndLoadInfo(Element coll_config_xml, Element build_config_xml) { addMetadata("httpPath", this.site_http_address + "/collect/" + this.cluster_name); //check whether the html are tidy or not Element import_list = (Element) GSXML.getChildByTagName(coll_config_xml, GSXML.IMPORT_ELEM); if (import_list != null) { Element plugin_list = (Element) GSXML.getChildByTagName(import_list, GSXML.PLUGIN_ELEM + GSXML.LIST_MODIFIER); //addPlugins(plugin_list); if (plugin_list != null) { Element plugin_elem = (Element) GSXML.getNamedElement(plugin_list, GSXML.PLUGIN_ELEM, GSXML.NAME_ATT, "HTMLPlugin"); if (plugin_elem != null) { //get the option Element option_elem = (Element) GSXML.getNamedElement(plugin_elem, GSXML.PARAM_OPTION_ELEM, GSXML.NAME_ATT, "-use_realistic_book"); if (option_elem != null) { useBook = true; } } } } String tidy = (useBook == true ? "tidy" : "untidy"); addMetadata("tidyoption", tidy); if (this.metadata_list != null) { // check whether we are public or not Element meta_elem = (Element) GSXML.getNamedElement(this.metadata_list, GSXML.METADATA_ELEM, GSXML.NAME_ATT, "public"); if (meta_elem != null) { String value = GSXML.getValue(meta_elem).toLowerCase().trim(); if (value.equals("false")) { is_public = false; } } // earliest datestamp is the time the collection was created. meta_elem = (Element) GSXML.getNamedElement(this.metadata_list, GSXML.METADATA_ELEM, GSXML.NAME_ATT, OAIXML.EARLIEST_DATESTAMP); if (meta_elem != null) { String earliestDatestampStr = GSXML.getValue(meta_elem); if (!earliestDatestampStr.equals("")) { earliestDatestamp = Long.parseLong(earliestDatestampStr) * 1000; // stored in seconds, convert to milliseconds } } } return true; } protected void loadSecurityInformation(Element coll_config_xml) { Element securityBlock = (Element) GSXML.getChildByTagName(coll_config_xml, GSXML.SECURITY_ELEM); if (securityBlock == null) { return; } String disabled = securityBlock.getAttribute(GSXML.DISABLED_ATT); if (!disabled.equals("")) { // security block has been disabled. logger.warn("Security block has been disabled. Not implementing any security for collection "+this.cluster_name); return; } String scope = securityBlock.getAttribute(GSXML.SCOPE_ATT); String defaultAccess = securityBlock.getAttribute(GSXML.DEFAULT_ACCESS_ATT); if (defaultAccess.toLowerCase().equals(GSXML.ACCESS_PUBLIC)) { _publicAccess = true; } else if (defaultAccess.toLowerCase().equals(GSXML.ACCESS_PRIVATE)) { _publicAccess = false; } else { logger.warn("Default access for collection " + this.cluster_name + " is neither public nor private, assuming public"); } String humanVerify = securityBlock.getAttribute(GSXML.VERIFY_ATT); if (humanVerify.equals("true")) { _humanVerify = true; } String useRecaptcha = securityBlock.getAttribute(GSXML.USE_RECAPTCHA_ATT); if (useRecaptcha.equals("true")) { Authentication authen_services =(Authentication) this.router.getModuleMap().get(Authentication.AUTHENTICATION_SERVICE); if (authen_services != null) { String siteKey = authen_services.getRecaptchaSiteKey(); String secretKey = authen_services.getRecaptchaSecretKey(); if (siteKey != null && secretKey != null) { _useRecaptcha = true; _siteKey = siteKey; _secretKey = secretKey; } else { logger.warn("use_recaptcha was set to true, but couldn't find recaptcha site and secret keys from the siteConfig Authentication service. Setting use_recaptcha to false!"); } } } if (scope.toLowerCase().equals(GSXML.SCOPE_COLLECTION)) { _securityScopeCollection = true; } else if (scope.toLowerCase().equals(GSXML.SCOPE_DOCUMENT)) { _securityScopeCollection = false; } else { logger.warn("Security scope is neither collection nor document, assuming collection"); } NodeList exceptions = GSXML.getChildrenByTagName(securityBlock, GSXML.EXCEPTION_ELEM); if (exceptions.getLength() > 0) { if (!_securityScopeCollection) { NodeList documentSetElems = GSXML.getChildrenByTagName(securityBlock, GSXML.DOCUMENT_SET_ELEM); for (int i = 0; i < documentSetElems.getLength(); i++) { Element documentSet = (Element) documentSetElems.item(i); String setName = documentSet.getAttribute(GSXML.NAME_ATT); NodeList matchStatements = GSXML.getChildrenByTagName(documentSet, GSXML.MATCH_ELEM); ArrayList matchStatementList = new ArrayList(); for (int j = 0; j < matchStatements.getLength(); j++) { matchStatementList.add((Element) matchStatements.item(j)); } _documentSets.put(setName, matchStatementList); } } for (int i = 0; i < exceptions.getLength(); i++) { HashMap> securityException = new HashMap>(); ArrayList exceptionGroups = new ArrayList(); ArrayList exceptionSets = new ArrayList(); Element exception = (Element) exceptions.item(i); NodeList groups = GSXML.getChildrenByTagName(exception, GSXML.GROUP_ELEM); for (int j = 0; j < groups.getLength(); j++) { Element group = (Element) groups.item(j); String groupName = group.getAttribute(GSXML.NAME_ATT); exceptionGroups.add(groupName); } NodeList docSets = GSXML.getChildrenByTagName(exception, GSXML.DOCUMENT_SET_ELEM); for (int j = 0; j < docSets.getLength(); j++) { Element docSet = (Element) docSets.item(j); String docSetName = docSet.getAttribute(GSXML.NAME_ATT); exceptionSets.add(docSetName); } if (_securityScopeCollection) { // we don't add in any exceptions that have document sets if (!exceptionSets.isEmpty()) { continue; } } securityException.put("groups", exceptionGroups); securityException.put("sets", exceptionSets); _securityExceptions.add(securityException); } } } protected boolean configureServiceRacks(Element coll_config_xml, Element build_config_xml) { clearServices(); Element service_list = (Element) GSXML.getChildByTagName(build_config_xml, GSXML.SERVICE_CLASS_ELEM + GSXML.LIST_MODIFIER); if (service_list != null) { configureServiceRackList(service_list, coll_config_xml); } // collection Config may also contain manually added service racks service_list = (Element) GSXML.getChildByTagName(coll_config_xml, GSXML.SERVICE_CLASS_ELEM + GSXML.LIST_MODIFIER); if (service_list != null) { configureServiceRackList(service_list, build_config_xml); } return true; } /** * do a configure on only part of the collection */ protected boolean configureSubset(String subset) { // need the coll config files Element coll_config_elem = loadCollConfigFile(); Element build_config_elem = loadBuildConfigFile(); if (coll_config_elem == null || build_config_elem == null) { // wont be able to do any of the requests return false; } if (subset.equals(GSXML.SERVICE_ELEM + GSXML.LIST_MODIFIER)) { return configureServiceRacks(coll_config_elem, build_config_elem); } if (subset.equals(GSXML.METADATA_ELEM + GSXML.LIST_MODIFIER) || subset.equals(GSXML.DISPLAY_TEXT_ELEM + GSXML.LIST_MODIFIER) || subset.equals(GSXML.LIBRARY_PARAM_ELEM+GSXML.LIST_MODIFIER)) { configureLocalData(coll_config_elem); configureLocalData(build_config_elem); return findAndLoadInfo(coll_config_elem, build_config_elem); } logger.error("Collection: cant process system request, configure " + subset); return false; } /** * handles requests made to the ServiceCluster itself * * @param req * - the request Element- * @return the result Element - should be */ protected Element processMessage(Document result_doc, Element request) { String type = request.getAttribute(GSXML.TYPE_ATT); if (type.equals(GSXML.REQUEST_TYPE_FORMAT_STRING)) { return processFormatStringRequest(result_doc, request); } else if (type.equals(GSXML.REQUEST_TYPE_SECURITY)) { return processSecurityRequest(result_doc, request); } else if (type.equals(GSXML.REQUEST_TYPE_FORMAT)) { Element response = result_doc.createElement(GSXML.RESPONSE_ELEM); response.setAttribute(GSXML.FROM_ATT, this.cluster_name); response.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_FORMAT); if (_globalFormat != null) { response.appendChild(result_doc.importNode(_globalFormat, true)); } return response; } // unknown type return super.processMessage(result_doc, request); } protected Element processSecurityRequest(Document result_doc, Element request) { Element response = result_doc.createElement(GSXML.RESPONSE_ELEM); response.setAttribute(GSXML.FROM_ATT, this.cluster_name); response.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_SECURITY); if (_humanVerify) { response.setAttribute("humanVerify", "true"); if (_useRecaptcha) { response.setAttribute("siteKey", _siteKey); response.setAttribute("secretKey", _secretKey); } } String oid = request.getAttribute("oid"); if (oid.contains(".")) { oid = oid.substring(0, oid.indexOf(".")); } ArrayList groups = getPermittedGroups(oid); Element groupList = result_doc.createElement(GSXML.GROUP_ELEM + GSXML.LIST_MODIFIER); response.appendChild(groupList); for (String groupName : groups) { Element group = result_doc.createElement(GSXML.GROUP_ELEM); groupList.appendChild(group); group.setAttribute(GSXML.NAME_ATT, groupName); } return response; } protected ArrayList getPermittedGroups(String oid) { ArrayList groups = new ArrayList(); if (_securityScopeCollection) { if (_publicAccess) { groups.add(""); } else { for (HashMap> exception : _securityExceptions) { for (String group : exception.get("groups")) { groups.add(group); } } } } else { if (oid != null && !oid.equals("")) { boolean inSet = false; for (HashMap> exception : _securityExceptions) { ArrayList exceptionSets = exception.get("sets"); if (exceptionSets.size() == 0) { inSet = true; for (String group : exception.get("groups")) { groups.add(group); } } else { for (String setName : exception.get("sets")) { if (documentIsInSet(oid, setName)) { inSet = true; for (String group : exception.get("groups")) { groups.add(group); } break; } } } } if (!inSet && _publicAccess) {// our doc was not part of any exception, so it must be public groups.add(""); } } else // if we are not doing a request with an oid, then free to access { groups.add(""); } } return groups; } protected boolean documentIsInSet(String oid, String setName) { ArrayList matchStatements = _documentSets.get(setName); if (matchStatements == null || matchStatements.size() == 0) { return false; } for (Element currentMatchStatement : matchStatements) { String fieldName = currentMatchStatement.getAttribute(GSXML.FIELD_ATT); if (fieldName == null || fieldName.equals("")) { fieldName = "oid"; } String type = currentMatchStatement.getAttribute(GSXML.TYPE_ATT); if (type == null || type.equals("")) { type = "match"; } //String fieldValue = ""; String[] fieldValues = null; if (!fieldName.equals("oid")) { //fieldValue = getFieldValue(oid, fieldName); fieldValues = getFieldValues(oid, fieldName); if (fieldValues == null) { return false; } } else { //fieldValue = oid; //fieldValues = new String[0]; //fieldValues[0] = oid; fieldValues = new String[]{oid}; // not allowed to do fieldValues = {oid}; after SEPARATE declaration. } String matchValue = GSXML.getNodeText(currentMatchStatement); if (type.equals("match")) { for(int i = 0; i < fieldValues.length; i++) { String fieldValue = fieldValues[i]; if (matchValue.equals(fieldValue)) { return true; } } } else if (type.equals("regex")) { for(int i = 0; i < fieldValues.length; i++) { String fieldValue = fieldValues[i]; if (fieldValue.matches(matchValue)) { return true; } } } else { logger.warn("Unknown type of match specified in security block of collection " + this.cluster_name + "."); } } return false; } protected String old_getFieldValue(String oid, String fieldName) { Document msg_doc = XMLConverter.newDOM(); Element metadataMessage = msg_doc.createElement(GSXML.MESSAGE_ELEM); Element metadataRequest = GSXML.createBasicRequest(msg_doc, GSXML.REQUEST_TYPE_PROCESS, this.cluster_name + "/DocumentMetadataRetrieve", new UserContext()); metadataMessage.appendChild(metadataRequest); Element paramList = msg_doc.createElement(GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER); metadataRequest.appendChild(paramList); Element param = msg_doc.createElement(GSXML.PARAM_ELEM); paramList.appendChild(param); param.setAttribute(GSXML.NAME_ATT, "metadata"); param.setAttribute(GSXML.VALUE_ATT, fieldName); Element docList = msg_doc.createElement(GSXML.DOC_NODE_ELEM + GSXML.LIST_MODIFIER); metadataRequest.appendChild(docList); Element doc = msg_doc.createElement(GSXML.DOC_NODE_ELEM); docList.appendChild(doc); doc.setAttribute(GSXML.NODE_ID_ATT, oid); Element response = (Element) this.router.process(metadataMessage); NodeList metadataElems = response.getElementsByTagName(GSXML.METADATA_ELEM); if (metadataElems.getLength() > 0) { Element metadata = (Element) metadataElems.item(0); return GSXML.getNodeText(metadata); } return null; } protected String[] getFieldValues(String oid, String fieldName) { Document msg_doc = XMLConverter.newDOM(); Element metadataMessage = msg_doc.createElement(GSXML.MESSAGE_ELEM); Element metadataRequest = GSXML.createBasicRequest(msg_doc, GSXML.REQUEST_TYPE_PROCESS, this.cluster_name + "/DocumentMetadataRetrieve", new UserContext()); metadataMessage.appendChild(metadataRequest); Element paramList = msg_doc.createElement(GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER); metadataRequest.appendChild(paramList); Element param = msg_doc.createElement(GSXML.PARAM_ELEM); paramList.appendChild(param); param.setAttribute(GSXML.NAME_ATT, "metadata"); param.setAttribute(GSXML.VALUE_ATT, fieldName); Element docList = msg_doc.createElement(GSXML.DOC_NODE_ELEM + GSXML.LIST_MODIFIER); metadataRequest.appendChild(docList); Element doc = msg_doc.createElement(GSXML.DOC_NODE_ELEM); docList.appendChild(doc); doc.setAttribute(GSXML.NODE_ID_ATT, oid); Element response = (Element) this.router.process(metadataMessage); NodeList metadataElems = response.getElementsByTagName(GSXML.METADATA_ELEM); if (metadataElems.getLength() <= 0) { return null; } // else String[] fieldValues = new String[metadataElems.getLength()]; for(int i = 0; i < metadataElems.getLength(); i++) { Element metadata = (Element) metadataElems.item(i); fieldValues[i] = GSXML.getNodeText(metadata); } return fieldValues; } protected Element processFormatStringRequest(Document result_doc, Element request) { Element response = result_doc.createElement(GSXML.RESPONSE_ELEM); response.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_FORMAT_STRING); response.setAttribute(GSXML.FROM_ATT, this.cluster_name); String subaction = request.getAttribute("subaction"); String service = request.getAttribute("service"); String classifier = null; if (service.equals("ClassifierBrowse")) { classifier = request.getAttribute("classifier"); } // check for version file String directory = new File(GSFile.collectionConfigFile(this.site_home, this.cluster_name)).getParent() + File.separator; String version_filename = ""; if (service.equals("ClassifierBrowse")) version_filename = directory + "browse_" + classifier + "_format_statement_version.txt"; else version_filename = directory + "query_format_statement_version.txt"; File version_file = new File(version_filename); if (subaction.equals("update")) { Element format_element = (Element) GSXML.getChildByTagName(request, GSXML.FORMAT_STRING_ELEM); //String format_string = GSXML.getNodeText(format_element); Element format_statement = (Element) format_element.getFirstChild(); String version_number = "1"; BufferedWriter writer; try { if (version_file.exists()) { // Read version BufferedReader reader = new BufferedReader(new FileReader(version_filename)); version_number = reader.readLine(); int aInt = Integer.parseInt(version_number) + 1; version_number = Integer.toString(aInt); reader.close(); } else { // Create version_file.createNewFile(); writer = new BufferedWriter(new FileWriter(version_filename)); writer.write(version_number); writer.close(); } // Write version file String format_statement_filename = ""; if (service.equals("ClassifierBrowse")) format_statement_filename = directory + "browse_" + classifier + "_format_statement_v" + version_number + ".txt"; else format_statement_filename = directory + "query_format_statement_v" + version_number + ".txt"; // Write format statement String format_string = this.converter.getString(format_statement); //GSXML.xmlNodeToString(format_statement); writer = new BufferedWriter(new FileWriter(format_statement_filename)); writer.write(format_string); writer.close(); // Update version number writer = new BufferedWriter(new FileWriter(version_filename)); writer.write(version_number); writer.close(); } catch (IOException e) { logger.error("IO Exception " + e); } } if (subaction.equals("saveDocument")) { Element format_element = (Element) GSXML.getChildByTagName(request, GSXML.FORMAT_STRING_ELEM); //String format_string = GSXML.getNodeText(format_element); // Get display tag Element display_format = (Element) format_element.getFirstChild(); String collection_config = directory + "collectionConfig.xml"; Document config = this.converter.getDOM(new File(collection_config), "UTF-8"); Node current_node = GSXML.getChildByTagName(config, "CollectionConfig"); // Get display child if (GSXML.getChildByTagName(current_node, "display") == null) { // well then create a format tag Element display_tag = config.createElement("display"); current_node = (Node) current_node.appendChild(display_tag); } else { current_node = GSXML.getChildByTagName(current_node, "display"); } if (GSXML.getChildByTagName(current_node, "format") == null) { // well then create a format tag Element format_tag = config.createElement("format"); current_node.appendChild(format_tag); } current_node.replaceChild(config.importNode(display_format, true), GSXML.getChildByTagName(current_node, "format")); String new_config = this.converter.getString(config); new_config = StringUtils.replace(new_config, "<", "<"); new_config = StringUtils.replace(new_config, ">", ">"); new_config = StringUtils.replace(new_config, """, "\""); try { // Write to file (not original! for now) BufferedWriter writer = new BufferedWriter(new FileWriter(collection_config + ".new")); writer.write(new_config); writer.close(); } catch (IOException e) { logger.error("IO Exception " + e); } } if (subaction.equals("save")) { Element format_element = (Element) GSXML.getChildByTagName(request, GSXML.FORMAT_STRING_ELEM); Element format_statement = (Element) format_element.getFirstChild(); try { // open collectionConfig.xml and read in to w3 Document String collection_config = directory + "collectionConfig.xml"; Document config = this.converter.getDOM(new File(collection_config), "UTF-8"); //String tag_name = ""; int k; int index; Element elem; Node current_node = GSXML.getChildByTagName(config, "CollectionConfig"); NodeList current_node_list; if (service.equals("ClassifierBrowse")) { //tag_name = "browse"; // if CLX then need to look in X then // default is current_node = GSXML.getChildByTagName(current_node, "browse"); // find CLX if (classifier != null) { current_node_list = GSXML.getChildrenByTagName(current_node, "classifier"); index = Integer.parseInt(classifier.substring(2)) - 1; // index should be given by X-1 current_node = current_node_list.item(index); // what if classifier does not have a format tag? if (GSXML.getChildByTagName(current_node, "format") == null) { // well then create a format tag Element format_tag = config.createElement("format"); current_node.appendChild(format_tag); } } else { // To support all classifiers, set classifier to null? There is the chance here that the format tag does not exist if (GSXML.getChildByTagName(current_node, "format") == null) { // well then create a format tag Element format_tag = config.createElement("format"); current_node.appendChild(format_tag); } } } else if (service.equals("AllClassifierBrowse")) { current_node = GSXML.getChildByTagName(current_node, "browse"); if (GSXML.getChildByTagName(current_node, "format") == null) { // well then create a format tag Element format_tag = config.createElement("format"); current_node.appendChild(format_tag); } } else { // look in with no attributes current_node_list = GSXML.getChildrenByTagName(current_node, "search"); for (k = 0; k < current_node_list.getLength(); k++) { current_node = current_node_list.item(k); // if current_node has no attributes then break elem = (Element) current_node; if (elem.hasAttribute("name") == false) break; } } current_node.replaceChild(config.importNode(format_statement, true), GSXML.getChildByTagName(current_node, "format")); // Now convert config document to string for writing to file String new_config = this.converter.getString(config); new_config = StringUtils.replace(new_config, "<", "<"); new_config = StringUtils.replace(new_config, ">", ">"); new_config = StringUtils.replace(new_config, """, "\""); // Write to file (not original! for now) BufferedWriter writer = new BufferedWriter(new FileWriter(collection_config + ".new")); writer.write(new_config); writer.close(); } catch (Exception ex) { logger.error("There was an exception " + ex); StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw, true); ex.printStackTrace(pw); pw.flush(); sw.flush(); logger.error(sw.toString()); } } return response; } }