setDataSources();\r
propagateConfiguredProperties();\r
\r
- // Ensure that Nuxeo config files exist for each repository\r
- // specified in tenant bindings\r
+ // Ensure that Nuxeo repository config files exist for each repository\r
+ // specified in tenant bindings.\r
+ \r
+ // Get the prototype copy of the Nuxeo repository config file.\r
+ // This file will then be cloned, creating a separate config file\r
+ // for each repository.\r
File prototypeNuxeoConfigFile =\r
new File(getNuxeoConfigDir() + File.separator + getNuxeoProtoConfigFilename());\r
logger.warn("Prototype Nuxeo config file path=" + prototypeNuxeoConfigFile.getCanonicalPath());\r
- if (prototypeNuxeoConfigFile.canRead()) {\r
- logger.warn("Can read prototype Nuxeo config file.");\r
- Document prototypeDoc = XmlTools.fileToXMLDocument(prototypeNuxeoConfigFile);\r
- // FIXME: Can the variable below reasonably be made a class variable? Its value\r
- // is used in at least one other method in this class.\r
- Hashtable<String, TenantBindingType> tenantBindingTypeMap = tenantBindingConfigReader.getTenantBindings();\r
- for (TenantBindingType tbt : tenantBindingTypeMap.values()) {\r
- List<String> repositoryNameList = ConfigUtils.getRepositoryNameList(tbt);\r
- if (repositoryNameList != null && repositoryNameList.isEmpty() == false) {\r
- Document repoDoc = null;\r
- final String PLACEHOLDER = "placeholder";\r
- for (String repositoryName : repositoryNameList) {\r
- if (Tools.isBlank(repositoryName)) {\r
- continue;\r
- }\r
- // FIXME: Remove this and other, similar log statements before merging. \r
- logger.warn("Repository name=" + repositoryName);\r
- repoDoc = (Document) prototypeDoc.clone();\r
- logger.warn("Before edits=\n" + repoDoc.asXML());\r
- // Text substitutions within first extension point\r
- repoDoc = XmlTools.setAttributeValue(repoDoc,\r
- REPOSITORY_EXTENSION_POINT_XPATH + "/repository", "name", repositoryName);\r
- logger.warn("After edit=\n" + repoDoc.asXML());\r
- repoDoc = XmlTools.setAttributeValue(repoDoc,\r
- REPOSITORY_EXTENSION_POINT_XPATH + "/repository/repository", "name", repositoryName);\r
- logger.warn("After edit=\n" + repoDoc.asXML());\r
- repoDoc = XmlTools.setElementValue(repoDoc,\r
- REPOSITORY_EXTENSION_POINT_XPATH + "/repository/repository/xa-datasource", PLACEHOLDER);\r
- logger.warn("After edit=\n" + repoDoc.asXML());\r
- repoDoc = XmlTools.setElementValue(repoDoc,\r
- REPOSITORY_EXTENSION_POINT_XPATH + "/repository/repository/property[@name='URL']", PLACEHOLDER);\r
- logger.warn("After edit=\n" + repoDoc.asXML());\r
- repoDoc = XmlTools.setElementValue(repoDoc,\r
- REPOSITORY_EXTENSION_POINT_XPATH + "/repository/repository/property[@name='ServerName']", PLACEHOLDER);\r
- logger.warn("After edit=\n" + repoDoc.asXML());\r
- repoDoc = XmlTools.setElementValue(repoDoc,\r
- REPOSITORY_EXTENSION_POINT_XPATH + "/repository/repository/property[@name='DatabaseName']", repositoryName);\r
- logger.warn("After edit=\n" + repoDoc.asXML());\r
- repoDoc = XmlTools.setElementValue(repoDoc,\r
- REPOSITORY_EXTENSION_POINT_XPATH + "/repository/repository/property[@name='User']", PLACEHOLDER);\r
- logger.warn("After edit=\n" + repoDoc.asXML());\r
- repoDoc = XmlTools.setElementValue(repoDoc,\r
- REPOSITORY_EXTENSION_POINT_XPATH + "/repository/repository/property[@name='Password']", PLACEHOLDER);\r
- logger.warn("After edit=\n" + repoDoc.asXML());\r
- // Text substitutions within second extension point\r
- repoDoc = XmlTools.setElementValue(repoDoc,\r
- REPOSITORIES_EXTENSION_POINT_XPATH + "/documentation", PLACEHOLDER);\r
- logger.warn("After edit=\n" + repoDoc.asXML());\r
- repoDoc = XmlTools.setAttributeValue(repoDoc,\r
- REPOSITORIES_EXTENSION_POINT_XPATH + "/repository", "name", repositoryName);\r
- logger.warn("After edit=\n" + repoDoc.asXML());\r
- repoDoc = XmlTools.setAttributeValue(repoDoc,\r
- REPOSITORIES_EXTENSION_POINT_XPATH + "/repository", "label", PLACEHOLDER);\r
- logger.warn("After edit=\n" + repoDoc.asXML());\r
- // FIXME: Edit additional element and/or attribute values.\r
- // FIXME: Emit serialized XML and write it to an appropriately named file\r
- // in the Nuxeo server config directory.\r
- repoDoc = null;\r
+ if (! prototypeNuxeoConfigFile.canRead()) {\r
+ String msg = String.format("Could not find and/or read the prototype Nuxeo config file '%s'",\r
+ prototypeNuxeoConfigFile.getCanonicalPath());\r
+ throw new RuntimeException(msg);\r
+ }\r
+ logger.warn("Can read prototype Nuxeo config file.");\r
+ Document prototypeConfigDoc = XmlTools.fileToXMLDocument(prototypeNuxeoConfigFile);\r
+ Document repositoryConfigDoc = null;\r
+ // FIXME: Can the variable below reasonably be made a class variable? Its value\r
+ // is used in at least one other method in this class.\r
+ Hashtable<String, TenantBindingType> tenantBindingTypeMap = tenantBindingConfigReader.getTenantBindings();\r
+ for (TenantBindingType tbt : tenantBindingTypeMap.values()) {\r
+ List<String> repositoryNameList = ConfigUtils.getRepositoryNameList(tbt);\r
+ logger.warn("Getting repository name(s) for tenant " + tbt.getName());\r
+ if (repositoryNameList == null || repositoryNameList.isEmpty() == true) {\r
+ logger.warn(String.format("Could not get repository name(s) for tenant %s", tbt.getName()));\r
+ continue;\r
+ } else {\r
+ for (String repositoryName : repositoryNameList) {\r
+ if (Tools.isBlank(repositoryName)) {\r
+ continue;\r
}\r
+ logger.warn(String.format("Repository name is %s", repositoryName));\r
+ repositoryConfigDoc = (Document) prototypeConfigDoc.clone();\r
+ // Update the newly-cloned repository config file by inserting\r
+ // values specific to the current repo.\r
+ repositoryConfigDoc = updateRepositoryConfigDoc(repositoryConfigDoc, repositoryName);\r
+ logger.warn("repositoryConfigDoc=\n" + repositoryConfigDoc.asXML());\r
+ // Write this repository config file to the Nuxeo server config directory.\r
+ File repofile = new File(getNuxeoConfigDir() + File.separator +\r
+ repositoryName + JEEServerDeployment.NUXEO_REPO_CONFIG_FILENAME_SUFFIX);\r
+ logger.warn(String.format("Repository config filepath is %s", repofile.getAbsolutePath()));\r
+ // FIXME: Remove the duplicate call here (likely the first)\r
+ XmlTools.xmlDocumentToFile(repositoryConfigDoc, repofile);\r
+ XmlTools.xmlDocumentToFile(repositoryConfigDoc, repofile, null);\r
}\r
}\r
- } else {\r
- logger.error(String.format("Could not either find, or read, the prototype Nuxeo config file '%s'",\r
- prototypeNuxeoConfigFile.getCanonicalPath()));\r
}\r
+ \r
//\r
// Start up and initialize our embedded Nuxeo server instance\r
//\r
return uriTemplateRegistry;\r
}\r
\r
+ private Document updateRepositoryConfigDoc(Document repoConfigDoc, String repositoryName) {\r
+ // FIXME: Remove this temporary placeholder variable used only during development.\r
+ final String PLACEHOLDER = "placeholder";\r
+ // logger.warn("Before edits=\n" + repoConfigDoc.asXML());\r
+ // Text substitutions within first extension point\r
+ repoConfigDoc = XmlTools.setAttributeValue(repoConfigDoc,\r
+ REPOSITORY_EXTENSION_POINT_XPATH + "/repository", "name", repositoryName);\r
+ // logger.warn("After edit=\n" + repoConfigDoc.asXML());\r
+ repoConfigDoc = XmlTools.setAttributeValue(repoConfigDoc,\r
+ REPOSITORY_EXTENSION_POINT_XPATH + "/repository/repository", "name", repositoryName);\r
+ // logger.warn("After edit=\n" + repoConfigDoc.asXML());\r
+ repoConfigDoc = XmlTools.setElementValue(repoConfigDoc,\r
+ REPOSITORY_EXTENSION_POINT_XPATH + "/repository/repository/xa-datasource", PLACEHOLDER);\r
+ // logger.warn("After edit=\n" + repoConfigDoc.asXML());\r
+ repoConfigDoc = XmlTools.setElementValue(repoConfigDoc,\r
+ REPOSITORY_EXTENSION_POINT_XPATH + "/repository/repository/property[@name='URL']", PLACEHOLDER);\r
+ // logger.warn("After edit=\n" + repoConfigDoc.asXML());\r
+ repoConfigDoc = XmlTools.setElementValue(repoConfigDoc,\r
+ REPOSITORY_EXTENSION_POINT_XPATH + "/repository/repository/property[@name='ServerName']", PLACEHOLDER);\r
+ // logger.warn("After edit=\n" + repoConfigDoc.asXML());\r
+ repoConfigDoc = XmlTools.setElementValue(repoConfigDoc,\r
+ REPOSITORY_EXTENSION_POINT_XPATH + "/repository/repository/property[@name='DatabaseName']", repositoryName);\r
+ // logger.warn("After edit=\n" + repoConfigDoc.asXML());\r
+ repoConfigDoc = XmlTools.setElementValue(repoConfigDoc,\r
+ REPOSITORY_EXTENSION_POINT_XPATH + "/repository/repository/property[@name='User']", PLACEHOLDER);\r
+ // logger.warn("After edit=\n" + repoConfigDoc.asXML());\r
+ repoConfigDoc = XmlTools.setElementValue(repoConfigDoc,\r
+ REPOSITORY_EXTENSION_POINT_XPATH + "/repository/repository/property[@name='Password']", PLACEHOLDER);\r
+ // logger.warn("After edit=\n" + repoConfigDoc.asXML());\r
+ // Text substitutions within second extension point\r
+ repoConfigDoc = XmlTools.setElementValue(repoConfigDoc,\r
+ REPOSITORIES_EXTENSION_POINT_XPATH + "/documentation", PLACEHOLDER);\r
+ // logger.warn("After edit=\n" + repoConfigDoc.asXML());\r
+ repoConfigDoc = XmlTools.setAttributeValue(repoConfigDoc,\r
+ REPOSITORIES_EXTENSION_POINT_XPATH + "/repository", "name", repositoryName);\r
+ // logger.warn("After edit=\n" + repoConfigDoc.asXML());\r
+ repoConfigDoc = XmlTools.setAttributeValue(repoConfigDoc,\r
+ REPOSITORIES_EXTENSION_POINT_XPATH + "/repository", "label", PLACEHOLDER);\r
+ // logger.warn("After edit=\n" + repoConfigDoc.asXML());\r
+ return repoConfigDoc;\r
+ }\r
+\r
\r
}\r
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;
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.
element.setText(elementValue == null ? "" : elementValue);
return doc;
} catch (Exception e) {
- System.out.println(e.getStackTrace());
+ System.err.println(e.getStackTrace());
} finally {
return doc;
}
element.addAttribute(attributeName, attributeValue == null ? "" : attributeValue);
return doc;
} catch (Exception e) {
- System.out.println(e.getStackTrace());
+ System.err.println(e.getStackTrace());
} finally {
return doc;
}