From cc0669cd975528ea2580e921dec3fe80479d56f6 Mon Sep 17 00:00:00 2001 From: Aron Roberts Date: Tue, 4 Mar 2014 20:22:40 -0800 Subject: [PATCH] CSPACE-6329: Now writes config files to the Nuxeo server config directory, albeit with mostly placeholder values. --- .../services/common/ServiceMain.java | 146 ++++++++++-------- .../services/common/XmlTools.java | 75 ++++++++- 2 files changed, 156 insertions(+), 65 deletions(-) diff --git a/services/common/src/main/java/org/collectionspace/services/common/ServiceMain.java b/services/common/src/main/java/org/collectionspace/services/common/ServiceMain.java index 1d32ede7e..67d065604 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/ServiceMain.java +++ b/services/common/src/main/java/org/collectionspace/services/common/ServiceMain.java @@ -163,76 +163,54 @@ public class ServiceMain { setDataSources(); propagateConfiguredProperties(); - // Ensure that Nuxeo config files exist for each repository - // specified in tenant bindings + // Ensure that Nuxeo repository config files exist for each repository + // specified in tenant bindings. + + // Get the prototype copy of the Nuxeo repository config file. + // This file will then be cloned, creating a separate config file + // for each repository. File prototypeNuxeoConfigFile = new File(getNuxeoConfigDir() + File.separator + getNuxeoProtoConfigFilename()); logger.warn("Prototype Nuxeo config file path=" + prototypeNuxeoConfigFile.getCanonicalPath()); - if (prototypeNuxeoConfigFile.canRead()) { - logger.warn("Can read prototype Nuxeo config file."); - Document prototypeDoc = XmlTools.fileToXMLDocument(prototypeNuxeoConfigFile); - // FIXME: Can the variable below reasonably be made a class variable? Its value - // is used in at least one other method in this class. - Hashtable tenantBindingTypeMap = tenantBindingConfigReader.getTenantBindings(); - for (TenantBindingType tbt : tenantBindingTypeMap.values()) { - List repositoryNameList = ConfigUtils.getRepositoryNameList(tbt); - if (repositoryNameList != null && repositoryNameList.isEmpty() == false) { - Document repoDoc = null; - final String PLACEHOLDER = "placeholder"; - for (String repositoryName : repositoryNameList) { - if (Tools.isBlank(repositoryName)) { - continue; - } - // FIXME: Remove this and other, similar log statements before merging. - logger.warn("Repository name=" + repositoryName); - repoDoc = (Document) prototypeDoc.clone(); - logger.warn("Before edits=\n" + repoDoc.asXML()); - // Text substitutions within first extension point - repoDoc = XmlTools.setAttributeValue(repoDoc, - REPOSITORY_EXTENSION_POINT_XPATH + "/repository", "name", repositoryName); - logger.warn("After edit=\n" + repoDoc.asXML()); - repoDoc = XmlTools.setAttributeValue(repoDoc, - REPOSITORY_EXTENSION_POINT_XPATH + "/repository/repository", "name", repositoryName); - logger.warn("After edit=\n" + repoDoc.asXML()); - repoDoc = XmlTools.setElementValue(repoDoc, - REPOSITORY_EXTENSION_POINT_XPATH + "/repository/repository/xa-datasource", PLACEHOLDER); - logger.warn("After edit=\n" + repoDoc.asXML()); - repoDoc = XmlTools.setElementValue(repoDoc, - REPOSITORY_EXTENSION_POINT_XPATH + "/repository/repository/property[@name='URL']", PLACEHOLDER); - logger.warn("After edit=\n" + repoDoc.asXML()); - repoDoc = XmlTools.setElementValue(repoDoc, - REPOSITORY_EXTENSION_POINT_XPATH + "/repository/repository/property[@name='ServerName']", PLACEHOLDER); - logger.warn("After edit=\n" + repoDoc.asXML()); - repoDoc = XmlTools.setElementValue(repoDoc, - REPOSITORY_EXTENSION_POINT_XPATH + "/repository/repository/property[@name='DatabaseName']", repositoryName); - logger.warn("After edit=\n" + repoDoc.asXML()); - repoDoc = XmlTools.setElementValue(repoDoc, - REPOSITORY_EXTENSION_POINT_XPATH + "/repository/repository/property[@name='User']", PLACEHOLDER); - logger.warn("After edit=\n" + repoDoc.asXML()); - repoDoc = XmlTools.setElementValue(repoDoc, - REPOSITORY_EXTENSION_POINT_XPATH + "/repository/repository/property[@name='Password']", PLACEHOLDER); - logger.warn("After edit=\n" + repoDoc.asXML()); - // Text substitutions within second extension point - repoDoc = XmlTools.setElementValue(repoDoc, - REPOSITORIES_EXTENSION_POINT_XPATH + "/documentation", PLACEHOLDER); - logger.warn("After edit=\n" + repoDoc.asXML()); - repoDoc = XmlTools.setAttributeValue(repoDoc, - REPOSITORIES_EXTENSION_POINT_XPATH + "/repository", "name", repositoryName); - logger.warn("After edit=\n" + repoDoc.asXML()); - repoDoc = XmlTools.setAttributeValue(repoDoc, - REPOSITORIES_EXTENSION_POINT_XPATH + "/repository", "label", PLACEHOLDER); - logger.warn("After edit=\n" + repoDoc.asXML()); - // FIXME: Edit additional element and/or attribute values. - // FIXME: Emit serialized XML and write it to an appropriately named file - // in the Nuxeo server config directory. - repoDoc = null; + if (! prototypeNuxeoConfigFile.canRead()) { + String msg = String.format("Could not find and/or read the prototype Nuxeo config file '%s'", + prototypeNuxeoConfigFile.getCanonicalPath()); + throw new RuntimeException(msg); + } + logger.warn("Can read prototype Nuxeo config file."); + Document prototypeConfigDoc = XmlTools.fileToXMLDocument(prototypeNuxeoConfigFile); + Document repositoryConfigDoc = null; + // FIXME: Can the variable below reasonably be made a class variable? Its value + // is used in at least one other method in this class. + Hashtable tenantBindingTypeMap = tenantBindingConfigReader.getTenantBindings(); + for (TenantBindingType tbt : tenantBindingTypeMap.values()) { + List repositoryNameList = ConfigUtils.getRepositoryNameList(tbt); + logger.warn("Getting repository name(s) for tenant " + tbt.getName()); + if (repositoryNameList == null || repositoryNameList.isEmpty() == true) { + logger.warn(String.format("Could not get repository name(s) for tenant %s", tbt.getName())); + continue; + } else { + for (String repositoryName : repositoryNameList) { + if (Tools.isBlank(repositoryName)) { + continue; } + logger.warn(String.format("Repository name is %s", repositoryName)); + repositoryConfigDoc = (Document) prototypeConfigDoc.clone(); + // Update the newly-cloned repository config file by inserting + // values specific to the current repo. + repositoryConfigDoc = updateRepositoryConfigDoc(repositoryConfigDoc, repositoryName); + logger.warn("repositoryConfigDoc=\n" + repositoryConfigDoc.asXML()); + // Write this repository config file to the Nuxeo server config directory. + File repofile = new File(getNuxeoConfigDir() + File.separator + + repositoryName + JEEServerDeployment.NUXEO_REPO_CONFIG_FILENAME_SUFFIX); + logger.warn(String.format("Repository config filepath is %s", repofile.getAbsolutePath())); + // FIXME: Remove the duplicate call here (likely the first) + XmlTools.xmlDocumentToFile(repositoryConfigDoc, repofile); + XmlTools.xmlDocumentToFile(repositoryConfigDoc, repofile, null); } } - } else { - logger.error(String.format("Could not either find, or read, the prototype Nuxeo config file '%s'", - prototypeNuxeoConfigFile.getCanonicalPath())); } + // // Start up and initialize our embedded Nuxeo server instance // @@ -825,5 +803,47 @@ public class ServiceMain { return uriTemplateRegistry; } + private Document updateRepositoryConfigDoc(Document repoConfigDoc, String repositoryName) { + // FIXME: Remove this temporary placeholder variable used only during development. + final String PLACEHOLDER = "placeholder"; + // logger.warn("Before edits=\n" + repoConfigDoc.asXML()); + // Text substitutions within first extension point + repoConfigDoc = XmlTools.setAttributeValue(repoConfigDoc, + REPOSITORY_EXTENSION_POINT_XPATH + "/repository", "name", repositoryName); + // logger.warn("After edit=\n" + repoConfigDoc.asXML()); + repoConfigDoc = XmlTools.setAttributeValue(repoConfigDoc, + REPOSITORY_EXTENSION_POINT_XPATH + "/repository/repository", "name", repositoryName); + // logger.warn("After edit=\n" + repoConfigDoc.asXML()); + repoConfigDoc = XmlTools.setElementValue(repoConfigDoc, + REPOSITORY_EXTENSION_POINT_XPATH + "/repository/repository/xa-datasource", PLACEHOLDER); + // logger.warn("After edit=\n" + repoConfigDoc.asXML()); + repoConfigDoc = XmlTools.setElementValue(repoConfigDoc, + REPOSITORY_EXTENSION_POINT_XPATH + "/repository/repository/property[@name='URL']", PLACEHOLDER); + // logger.warn("After edit=\n" + repoConfigDoc.asXML()); + repoConfigDoc = XmlTools.setElementValue(repoConfigDoc, + REPOSITORY_EXTENSION_POINT_XPATH + "/repository/repository/property[@name='ServerName']", PLACEHOLDER); + // logger.warn("After edit=\n" + repoConfigDoc.asXML()); + repoConfigDoc = XmlTools.setElementValue(repoConfigDoc, + REPOSITORY_EXTENSION_POINT_XPATH + "/repository/repository/property[@name='DatabaseName']", repositoryName); + // logger.warn("After edit=\n" + repoConfigDoc.asXML()); + repoConfigDoc = XmlTools.setElementValue(repoConfigDoc, + REPOSITORY_EXTENSION_POINT_XPATH + "/repository/repository/property[@name='User']", PLACEHOLDER); + // logger.warn("After edit=\n" + repoConfigDoc.asXML()); + repoConfigDoc = XmlTools.setElementValue(repoConfigDoc, + REPOSITORY_EXTENSION_POINT_XPATH + "/repository/repository/property[@name='Password']", PLACEHOLDER); + // logger.warn("After edit=\n" + repoConfigDoc.asXML()); + // Text substitutions within second extension point + repoConfigDoc = XmlTools.setElementValue(repoConfigDoc, + REPOSITORIES_EXTENSION_POINT_XPATH + "/documentation", PLACEHOLDER); + // logger.warn("After edit=\n" + repoConfigDoc.asXML()); + repoConfigDoc = XmlTools.setAttributeValue(repoConfigDoc, + REPOSITORIES_EXTENSION_POINT_XPATH + "/repository", "name", repositoryName); + // logger.warn("After edit=\n" + repoConfigDoc.asXML()); + repoConfigDoc = XmlTools.setAttributeValue(repoConfigDoc, + REPOSITORIES_EXTENSION_POINT_XPATH + "/repository", "label", PLACEHOLDER); + // logger.warn("After edit=\n" + repoConfigDoc.asXML()); + return repoConfigDoc; + } + } diff --git a/services/common/src/main/java/org/collectionspace/services/common/XmlTools.java b/services/common/src/main/java/org/collectionspace/services/common/XmlTools.java index baaa526b3..66a6b3bce 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/XmlTools.java +++ b/services/common/src/main/java/org/collectionspace/services/common/XmlTools.java @@ -1,6 +1,9 @@ package org.collectionspace.services.common; +import java.io.Closeable; import java.io.File; +import java.io.FileWriter; +import java.io.IOException; import java.io.StringWriter; import org.collectionspace.services.common.api.Tools; import org.dom4j.Document; @@ -121,6 +124,74 @@ public class XmlTools { return doc; } + /** + * Writes a dom4j XML document to a file on disk, using a default + * pretty-printed output format. Uses UTF-8 character encoding. + * @param doc A dom4j XML document. + * @param file A file. + */ + public static void xmlDocumentToFile(Document doc, File file) throws Exception { + xmlDocumentToFile(doc, file, PRETTY_PRINT_OUTPUT_FORMAT); + } + + /** + * Writes a dom4j XML document to a file on disk. Uses UTF-8 character + * encoding. + * @param doc A dom4j XML document. + * @param file A file. + * @param outputFormat An output format. + */ + public static void xmlDocumentToFile(Document doc, File file, OutputFormat outputFormat) throws Exception { + if (doc == null) { + System.out.println("Document is null"); + System.err.println("Document is null"); + return; + } + FileWriter filewriter = null; + XMLWriter writer = null; + try { + filewriter = new FileWriter(file); + filewriter.write(doc.asXML()); + filewriter.flush(); + filewriter.close(); +// XMLWriter writer = new XMLWriter(filewriter, outputFormat); +// writer.write(doc); +// writer.flush(); + } catch (Exception e) { + System.out.println(e.getStackTrace()); + System.err.println(e.getStackTrace()); + throw e; + } finally { + // XMLWriter doesn't implement Closeable, so + // we'll need to close it directly here, rather + // than invoking closeQuietly(). +// if (writer != null) { +// try { +// writer.close(); +// } catch (IOException e) { +// // Do nothing here +// } +// } + closeQuietly(filewriter); + } + } + + /** + * Attempt to close a resource, swallowing any Exceptions thrown. + * This method should only be called from within the 'finally' portion + * of a 'catch/try/finally' block. + * See http://stackoverflow.com/questions/2699209/java-io-ugly-try-finally-block + * and http://stackoverflow.com/questions/341971/what-is-the-execute-around-idiom + * @param c A closeable resource. + */ + public static void closeQuietly(Closeable c) { + if (c != null) try { + c.close(); + } catch(Exception e) { + // Do nothing here + } + } + /** * Sets the (text node) value of a specified element in a dom4j XML document. * @param doc A dom4j XML document. @@ -144,7 +215,7 @@ public class XmlTools { element.setText(elementValue == null ? "" : elementValue); return doc; } catch (Exception e) { - System.out.println(e.getStackTrace()); + System.err.println(e.getStackTrace()); } finally { return doc; } @@ -176,7 +247,7 @@ public class XmlTools { element.addAttribute(attributeName, attributeValue == null ? "" : attributeValue); return doc; } catch (Exception e) { - System.out.println(e.getStackTrace()); + System.err.println(e.getStackTrace()); } finally { return doc; } -- 2.47.3