From e5f8093e7c24aa6752e1f4e4c71cf3d6f1cb7995 Mon Sep 17 00:00:00 2001 From: remillet Date: Tue, 22 Dec 2015 16:12:58 -0800 Subject: [PATCH] CSPACE-6564: Add code at init time that will add an Elasticsearch config section/element for each separate repository specified in the tenant bindings. --- 3rdparty/nuxeo/build.xml | 7 + .../6.0-HF21/config/elasticsearch-config.xml | 368 ------------------ .../config/proto-elasticsearch-config.xml | 31 ++ .../config/proto-elasticsearch-extension.xml | 175 +++++++++ .../6.0-HF21/config/vcsconfig.sql.txt | 9 +- build.properties | 2 +- pom.xml | 2 +- services/JaxRsServiceProvider/pom.xml | 20 + .../src/main/resources/log4j.properties | 1 + services/authority/service/pom.xml | 10 + .../nuxeo/AuthorityDocumentModelHandler.java | 4 + .../services/blob/BlobResource.java | 4 +- .../common/api/JEEServerDeployment.java | 12 +- .../{FileUtils.java => FileUtilities.java} | 46 ++- .../services/common/ServiceMain.java | 182 +++++++-- .../services/common/XmlTools.java | 21 + .../services/common/blob/BlobInput.java | 2 +- .../common/imaging/nuxeo/NuxeoBlobUtils.java | 4 +- .../client/java/CoreSessionInterface.java | 4 + .../nuxeo/client/java/CoreSessionWrapper.java | 73 +++- .../client/java/NuxeoClientEmbedded.java | 2 +- .../client/java/RepositoryJavaClientImpl.java | 6 +- .../services/common/config/ConfigUtils.java | 12 +- .../services/imports/ImportsResource.java | 4 +- 24 files changed, 577 insertions(+), 424 deletions(-) delete mode 100644 3rdparty/nuxeo/nuxeo-server/6.0-HF21/config/elasticsearch-config.xml create mode 100644 3rdparty/nuxeo/nuxeo-server/6.0-HF21/config/proto-elasticsearch-config.xml create mode 100644 3rdparty/nuxeo/nuxeo-server/6.0-HF21/config/proto-elasticsearch-extension.xml rename services/common/src/main/java/org/collectionspace/services/common/{FileUtils.java => FileUtilities.java} (83%) diff --git a/3rdparty/nuxeo/build.xml b/3rdparty/nuxeo/build.xml index 953d89153..98a7fb801 100644 --- a/3rdparty/nuxeo/build.xml +++ b/3rdparty/nuxeo/build.xml @@ -112,6 +112,7 @@ + @@ -140,6 +141,12 @@ + + + + + + diff --git a/3rdparty/nuxeo/nuxeo-server/6.0-HF21/config/elasticsearch-config.xml b/3rdparty/nuxeo/nuxeo-server/6.0-HF21/config/elasticsearch-config.xml deleted file mode 100644 index 7fdb10454..000000000 --- a/3rdparty/nuxeo/nuxeo-server/6.0-HF21/config/elasticsearch-config.xml +++ /dev/null @@ -1,368 +0,0 @@ - - - org.nuxeo.elasticsearch.ElasticSearchComponent - - - - - - - - - ecm:* - dc:* - ecm:binarytext - - - -{ - "analysis" : { - "filter" : { - "en_stem_filter" : { - "name" : "minimal_english", - "type" : "stemmer" - }, - "en_stop_filter" : { - "stopwords" : [ - "_english_" - ], - "type" : "stop" - }, - "fr_elision_filter" : { - "articles" : [ - "c", - "l", - "m", - "t", - "qu", - "n", - "s", - "j" - ], - "type" : "elision" - }, - "fr_stem_filter" : { - "name" : "minimal_french", - "type" : "stemmer" - }, - "fr_stop_filter" : { - "stopwords" : [ - "_french_" - ], - "type" : "stop" - } - }, - "tokenizer" : { - "path_tokenizer" : { - "delimiter" : "/", - "type" : "path_hierarchy" - } - }, - "analyzer" : { - "en_analyzer" : { - "alias" : "fulltext", - "filter" : [ - "lowercase", - "en_stop_filter", - "en_stem_filter", - "asciifolding" - ], - "type" : "custom", - "tokenizer" : "standard" - }, - "fr_analyzer" : { - "filter" : [ - "lowercase", - "fr_stop_filter", - "fr_stem_filter", - "asciifolding", - "fr_elision_filter" - ], - "type" : "custom", - "tokenizer" : "standard" - }, - "path_analyzer" : { - "type" : "custom", - "tokenizer" : "path_tokenizer" - }, - "default" : { - "type" : "custom", - "tokenizer" : "keyword" - } - } - } -} - - -{ - "_size" : { - "enabled" : true - }, - "_all" : { - "analyzer" : "fulltext" - }, - "properties" : { - "dc:title" : { - "type" : "multi_field", - "fields" : { - "dc:title" : { - "index" : "not_analyzed", - "type" : "string" - }, - "fulltext" : { - "boost": 2, - "type": "string", - "analyzer" : "fulltext" - } - } - }, - "dc:description" : { - "type" : "multi_field", - "fields" : { - "dc:description" : { - "index" : "no", - "include_in_all" : "true", - "type" : "string" - }, - "fulltext" : { - "boost": 1.5, - "type": "string", - "analyzer" : "fulltext" - } - } - }, - "note:note" : { - "type" : "multi_field", - "fields" : { - "note:note" : { - "index" : "no", - "include_in_all" : "true", - "type" : "string" - }, - "fulltext" : { - "type": "string", - "analyzer" : "fulltext" - } - } - }, - "ecm:binarytext*" : { - "type" : "string", - "analyzer" : "fulltext" - }, - "ecm:path" : { - "type" : "multi_field", - "fields" : { - "children" : { - "search_analyzer" : "keyword", - "index_analyzer" : "path_analyzer", - "type" : "string" - }, - "ecm:path" : { - "index" : "not_analyzed", - "type" : "string" - } - } - }, - "ecm:pos": { - "type": "integer" - }, - "dc:created": { - "format": "dateOptionalTime", - "type": "date" - }, - "dc:modified": { - "format": "dateOptionalTime", - "type": "date" - } - } -} - - - - - - - - - ecm:* - dc:* - ecm:binarytext - - - -{ - "analysis" : { - "filter" : { - "en_stem_filter" : { - "name" : "minimal_english", - "type" : "stemmer" - }, - "en_stop_filter" : { - "stopwords" : [ - "_english_" - ], - "type" : "stop" - }, - "fr_elision_filter" : { - "articles" : [ - "c", - "l", - "m", - "t", - "qu", - "n", - "s", - "j" - ], - "type" : "elision" - }, - "fr_stem_filter" : { - "name" : "minimal_french", - "type" : "stemmer" - }, - "fr_stop_filter" : { - "stopwords" : [ - "_french_" - ], - "type" : "stop" - } - }, - "tokenizer" : { - "path_tokenizer" : { - "delimiter" : "/", - "type" : "path_hierarchy" - } - }, - "analyzer" : { - "en_analyzer" : { - "alias" : "fulltext", - "filter" : [ - "lowercase", - "en_stop_filter", - "en_stem_filter", - "asciifolding" - ], - "type" : "custom", - "tokenizer" : "standard" - }, - "fr_analyzer" : { - "filter" : [ - "lowercase", - "fr_stop_filter", - "fr_stem_filter", - "asciifolding", - "fr_elision_filter" - ], - "type" : "custom", - "tokenizer" : "standard" - }, - "path_analyzer" : { - "type" : "custom", - "tokenizer" : "path_tokenizer" - }, - "default" : { - "type" : "custom", - "tokenizer" : "keyword" - } - } - } -} - - -{ - "_size" : { - "enabled" : true - }, - "_all" : { - "analyzer" : "fulltext" - }, - "properties" : { - "dc:title" : { - "type" : "multi_field", - "fields" : { - "dc:title" : { - "index" : "not_analyzed", - "type" : "string" - }, - "fulltext" : { - "boost": 2, - "type": "string", - "analyzer" : "fulltext" - } - } - }, - "dc:description" : { - "type" : "multi_field", - "fields" : { - "dc:description" : { - "index" : "no", - "include_in_all" : "true", - "type" : "string" - }, - "fulltext" : { - "boost": 1.5, - "type": "string", - "analyzer" : "fulltext" - } - } - }, - "note:note" : { - "type" : "multi_field", - "fields" : { - "note:note" : { - "index" : "no", - "include_in_all" : "true", - "type" : "string" - }, - "fulltext" : { - "type": "string", - "analyzer" : "fulltext" - } - } - }, - "ecm:binarytext*" : { - "type" : "string", - "analyzer" : "fulltext" - }, - "ecm:path" : { - "type" : "multi_field", - "fields" : { - "children" : { - "search_analyzer" : "keyword", - "index_analyzer" : "path_analyzer", - "type" : "string" - }, - "ecm:path" : { - "index" : "not_analyzed", - "type" : "string" - } - } - }, - "ecm:pos": { - "type": "integer" - }, - "dc:created": { - "format": "dateOptionalTime", - "type": "date" - }, - "dc:modified": { - "format": "dateOptionalTime", - "type": "date" - } - } -} - - - - - - - diff --git a/3rdparty/nuxeo/nuxeo-server/6.0-HF21/config/proto-elasticsearch-config.xml b/3rdparty/nuxeo/nuxeo-server/6.0-HF21/config/proto-elasticsearch-config.xml new file mode 100644 index 000000000..33029f680 --- /dev/null +++ b/3rdparty/nuxeo/nuxeo-server/6.0-HF21/config/proto-elasticsearch-config.xml @@ -0,0 +1,31 @@ + + + org.nuxeo.elasticsearch.ElasticSearchComponent + + + + + + + + %elasticSearchIndex_extensions% + + + diff --git a/3rdparty/nuxeo/nuxeo-server/6.0-HF21/config/proto-elasticsearch-extension.xml b/3rdparty/nuxeo/nuxeo-server/6.0-HF21/config/proto-elasticsearch-extension.xml new file mode 100644 index 000000000..4302653a2 --- /dev/null +++ b/3rdparty/nuxeo/nuxeo-server/6.0-HF21/config/proto-elasticsearch-extension.xml @@ -0,0 +1,175 @@ + + + + ecm:* + dc:* + ecm:binarytext + + + +{ + "analysis" : { + "filter" : { + "en_stem_filter" : { + "name" : "minimal_english", + "type" : "stemmer" + }, + "en_stop_filter" : { + "stopwords" : [ + "_english_" + ], + "type" : "stop" + }, + "fr_elision_filter" : { + "articles" : [ + "c", + "l", + "m", + "t", + "qu", + "n", + "s", + "j" + ], + "type" : "elision" + }, + "fr_stem_filter" : { + "name" : "minimal_french", + "type" : "stemmer" + }, + "fr_stop_filter" : { + "stopwords" : [ + "_french_" + ], + "type" : "stop" + } + }, + "tokenizer" : { + "path_tokenizer" : { + "delimiter" : "/", + "type" : "path_hierarchy" + } + }, + "analyzer" : { + "en_analyzer" : { + "alias" : "fulltext", + "filter" : [ + "lowercase", + "en_stop_filter", + "en_stem_filter", + "asciifolding" + ], + "type" : "custom", + "tokenizer" : "standard" + }, + "fr_analyzer" : { + "filter" : [ + "lowercase", + "fr_stop_filter", + "fr_stem_filter", + "asciifolding", + "fr_elision_filter" + ], + "type" : "custom", + "tokenizer" : "standard" + }, + "path_analyzer" : { + "type" : "custom", + "tokenizer" : "path_tokenizer" + }, + "default" : { + "type" : "custom", + "tokenizer" : "keyword" + } + } + } +} + + +{ + "_size" : { + "enabled" : true + }, + "_all" : { + "analyzer" : "fulltext" + }, + "properties" : { + "dc:title" : { + "type" : "multi_field", + "fields" : { + "dc:title" : { + "index" : "not_analyzed", + "type" : "string" + }, + "fulltext" : { + "boost": 2, + "type": "string", + "analyzer" : "fulltext" + } + } + }, + "dc:description" : { + "type" : "multi_field", + "fields" : { + "dc:description" : { + "index" : "no", + "include_in_all" : "true", + "type" : "string" + }, + "fulltext" : { + "boost": 1.5, + "type": "string", + "analyzer" : "fulltext" + } + } + }, + "note:note" : { + "type" : "multi_field", + "fields" : { + "note:note" : { + "index" : "no", + "include_in_all" : "true", + "type" : "string" + }, + "fulltext" : { + "type": "string", + "analyzer" : "fulltext" + } + } + }, + "ecm:binarytext*" : { + "type" : "string", + "analyzer" : "fulltext" + }, + "ecm:path" : { + "type" : "multi_field", + "fields" : { + "children" : { + "search_analyzer" : "keyword", + "index_analyzer" : "path_analyzer", + "type" : "string" + }, + "ecm:path" : { + "index" : "not_analyzed", + "type" : "string" + } + } + }, + "ecm:pos": { + "type": "integer" + }, + "dc:created": { + "format": "dateOptionalTime", + "type": "date" + }, + "dc:modified": { + "format": "dateOptionalTime", + "type": "date" + } + } +} + + + + \ No newline at end of file diff --git a/3rdparty/nuxeo/nuxeo-server/6.0-HF21/config/vcsconfig.sql.txt b/3rdparty/nuxeo/nuxeo-server/6.0-HF21/config/vcsconfig.sql.txt index c28de5738..2adea1c35 100644 --- a/3rdparty/nuxeo/nuxeo-server/6.0-HF21/config/vcsconfig.sql.txt +++ b/3rdparty/nuxeo/nuxeo-server/6.0-HF21/config/vcsconfig.sql.txt @@ -3,12 +3,15 @@ # See https://doc.nuxeo.com/display/ADMINDOC/VCS+Configuration#VCSConfiguration-DatabaseCreationOption # - #CATEGORY: afterTableCreation - # # Add a unique constraint to the shortidentifier column of the vocabularies_common table. # LOG.INFO Adding a unique constraint to the shortidentifier column of the vocabularies_common table -ALTER TABLE vocabularies_common add CONSTRAINT shortid_unique UNIQUE (shortidentifier); \ No newline at end of file + +#TEST: +SELECT constraint_name FROM information_schema.constraint_column_usage WHERE table_name = 'vocabularies_common' AND constraint_name = 'shortid_unique'; + +#IF: emptyResult +ALTER TABLE vocabularies_common add CONSTRAINT shortid_unique UNIQUE (shortidentifier); diff --git a/build.properties b/build.properties index 7b2011d05..61bd5bedc 100644 --- a/build.properties +++ b/build.properties @@ -17,7 +17,7 @@ cspace.services.war=${cspace.services.context}.war domain.nuxeo=nuxeo-server #nuxeo -nuxeo.release=6.0 +nuxeo.release=6.0-HF21 nuxeo.ear=nuxeo.ear nuxeo.system=bundles diff --git a/pom.xml b/pom.xml index 87cc1a4ad..f11b79215 100644 --- a/pom.xml +++ b/pom.xml @@ -13,7 +13,7 @@ UTF-8 4.3-SNAPSHOT 4.3-SNAPSHOT - 6.0 + 6.0-HF21 ${nuxeo.general.release} ${nuxeo.general.release} ${nuxeo.general.release} diff --git a/services/JaxRsServiceProvider/pom.xml b/services/JaxRsServiceProvider/pom.xml index e294d1154..42973269b 100644 --- a/services/JaxRsServiceProvider/pom.xml +++ b/services/JaxRsServiceProvider/pom.xml @@ -141,6 +141,22 @@ lucene-analyzers-common org.apache.lucene + + nuxeo-automation-server + org.nuxeo.ecm.automation + + + nuxeo-automation-io + org.nuxeo.ecm.automation + + + jsp-api-2.1 + org.mortbay.jetty + + + jsp-2.1 + org.mortbay.jetty + @@ -645,6 +661,10 @@ jsf-impl com.sun.faces + + el-api + javax.el + diff --git a/services/JaxRsServiceProvider/src/main/resources/log4j.properties b/services/JaxRsServiceProvider/src/main/resources/log4j.properties index 350c73c56..caf6cd4e1 100644 --- a/services/JaxRsServiceProvider/src/main/resources/log4j.properties +++ b/services/JaxRsServiceProvider/src/main/resources/log4j.properties @@ -64,6 +64,7 @@ log4j.logger.org.collectionspace.services.nuxeo.client.java.NuxeoClientEmbedded= # Nuxeo loggers, levels, and associated appenders # log4j.logger.org.nuxeo=WARN +log4j.logger.org.nuxeo.elasticsearch=INFO #log4j.logger.org.nuxeo.ecm.core.storage.sql=TRACE # diff --git a/services/authority/service/pom.xml b/services/authority/service/pom.xml index 6663569ec..24d329c23 100644 --- a/services/authority/service/pom.xml +++ b/services/authority/service/pom.xml @@ -37,6 +37,16 @@ org.collectionspace.services org.collectionspace.services.common + + + nuxeo-automation-io + org.nuxeo.ecm.automation + + + nuxeo-automation-server + org.nuxeo.ecm.automation + + org.collectionspace.services diff --git a/services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/nuxeo/AuthorityDocumentModelHandler.java b/services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/nuxeo/AuthorityDocumentModelHandler.java index 137bd11b3..4e78078b0 100644 --- a/services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/nuxeo/AuthorityDocumentModelHandler.java +++ b/services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/nuxeo/AuthorityDocumentModelHandler.java @@ -96,6 +96,10 @@ public abstract class AuthorityDocumentModelHandler } private boolean isUnique(DocumentModel docModel, String schemaName) throws DocumentException { + return true; + } + + private boolean temp_isUnique(DocumentModel docModel, String schemaName) throws DocumentException { boolean result = true; ServiceContext ctx = this.getServiceContext(); diff --git a/services/blob/service/src/main/java/org/collectionspace/services/blob/BlobResource.java b/services/blob/service/src/main/java/org/collectionspace/services/blob/BlobResource.java index 185f4b32d..0a4f59b64 100644 --- a/services/blob/service/src/main/java/org/collectionspace/services/blob/BlobResource.java +++ b/services/blob/service/src/main/java/org/collectionspace/services/blob/BlobResource.java @@ -28,7 +28,7 @@ import org.collectionspace.services.client.BlobClient; import org.collectionspace.services.client.PayloadPart; import org.collectionspace.services.client.PoxPayloadIn; import org.collectionspace.services.client.PoxPayloadOut; -import org.collectionspace.services.common.FileUtils; +import org.collectionspace.services.common.FileUtilities; import org.collectionspace.services.common.NuxeoBasedResource; import org.collectionspace.services.common.ResourceMap; import org.collectionspace.services.common.ServiceMessages; @@ -182,7 +182,7 @@ public class BlobResource extends NuxeoBasedResource { String mediaType = part.getMediaType().toString(); System.out.println("Media type is:" + mediaType); fileStream = part.getBody(InputStream.class, null); - FileUtils.createTmpFile(fileStream, getServiceName() + "_"); + FileUtilities.createTmpFile(fileStream, getServiceName() + "_"); } ResponseBuilder rb = Response.ok(); diff --git a/services/common-api/src/main/java/org/collectionspace/services/common/api/JEEServerDeployment.java b/services/common-api/src/main/java/org/collectionspace/services/common/api/JEEServerDeployment.java index 7c62cf082..42447c021 100644 --- a/services/common-api/src/main/java/org/collectionspace/services/common/api/JEEServerDeployment.java +++ b/services/common-api/src/main/java/org/collectionspace/services/common/api/JEEServerDeployment.java @@ -21,10 +21,20 @@ public interface JEEServerDeployment { public final static String NUXEO_SERVER_DIR = "nuxeo-server"; public final static String NUXEO_CONFIG_DIR = CONFIG_DIR_NAME; public final static String NUXEO_SERVER_CONFIG_DIR = NUXEO_SERVER_DIR + File.separator + NUXEO_CONFIG_DIR; + + // The file name parts for a Nuxeo repository configuration file. These end up in tomcat/nuxeo-server/config dir public final static String NUXEO_REPO_CONFIG_FILENAME_SUFFIX = "-repo-config.xml"; + public final static String NUXEO_PROTOTYPE_REPO_CONFIG_FILENAME = "proto" + NUXEO_REPO_CONFIG_FILENAME_SUFFIX; + + // The file name parts for a Nuxeo datasource configuration file. These end up in tomcat/nuxeo-server/config dir public final static String NUXEO_DATASOURCE_CONFIG_FILENAME_SUFFIX = "-datasource-config.xml"; - public final static String NUXEO_PROTOTYPE_CONFIG_FILENAME = "proto" + NUXEO_REPO_CONFIG_FILENAME_SUFFIX; public final static String NUXEO_PROTOTYPE_DATASOURCE_FILENAME = "proto" + NUXEO_DATASOURCE_CONFIG_FILENAME_SUFFIX; + + // The file name parts for Nuxeo's Elasticsearch configuration + public final static String NUXEO_ELASTICSEARCH_CONFIG_FILENAME = "elasticsearch-config.xml"; + public final static String NUXEO_PROTO_ELASTICSEARCH_CONFIG_FILENAME = "proto-" + NUXEO_ELASTICSEARCH_CONFIG_FILENAME; + public final static String NUXEO_PROTO_ELASTICSEARCH_EXTENSION_FILENAME = "proto-elasticsearch-extension.XML"; + public final static String NUXEO_PLUGINS_DIR = "plugins"; public final static String NUXEO_SERVER_PLUGINS_DIR = NUXEO_SERVER_DIR + File.separator + NUXEO_PLUGINS_DIR; public final static String NUXEO_DB_INIT_SCRIPT_FILENAME = "init_nuxeo_db.sql"; diff --git a/services/common/src/main/java/org/collectionspace/services/common/FileUtils.java b/services/common/src/main/java/org/collectionspace/services/common/FileUtilities.java similarity index 83% rename from services/common/src/main/java/org/collectionspace/services/common/FileUtils.java rename to services/common/src/main/java/org/collectionspace/services/common/FileUtilities.java index 1b59b5880..8a73a714e 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/FileUtils.java +++ b/services/common/src/main/java/org/collectionspace/services/common/FileUtilities.java @@ -40,6 +40,8 @@ import java.util.UUID; //import javax.servlet.ServletException; //import javax.servlet.http.HttpServlet; + + import net.sf.jmimemagic.Magic; import net.sf.jmimemagic.MagicException; import net.sf.jmimemagic.MagicMatch; @@ -50,7 +52,7 @@ import org.apache.commons.fileupload.FileItemFactory; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.servlet.ServletFileUpload; import org.apache.commons.fileupload.disk.DiskFileItemFactory; - +import org.dom4j.Document; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -58,9 +60,9 @@ import org.slf4j.LoggerFactory; /** * The Class FileUtils. */ -public class FileUtils { +public class FileUtilities { /** The Constant logger. */ - private static final Logger logger = LoggerFactory.getLogger(FileUtils.class); + private static final Logger logger = LoggerFactory.getLogger(FileUtilities.class); /** The Constant TMP_FILE_PREFIX. */ public static final String TMP_BLOB_PREFIX = "cspace_blob_"; @@ -89,7 +91,7 @@ public class FileUtils { * Creates a copy of the srcFile to a temp file */ static public File createTmpFile(File srcFile, String prefix) throws Exception { - String fileExtension = FileUtils.getExtension(srcFile); + String fileExtension = FileUtilities.getExtension(srcFile); File result = createTmpFile(new FileInputStream(srcFile), prefix, fileExtension); return result; } @@ -236,4 +238,40 @@ public class FileUtils { return result; } + /** + * 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) { + logger.trace("Failed to close filewriter.", e); + // Do nothing here + } + } + public static void StringToFile(String doc, File file) throws Exception { + if (doc == null) { + System.err.println("Document is null"); + return; + } + FileWriter filewriter = null; + try { + filewriter = new FileWriter(file); + // asXML() appears to output an adequate serialization, thus + // obviating the need to use an XML-aware writer here. + filewriter.write(doc); + filewriter.flush(); + filewriter.close(); + } catch (Exception e) { + System.err.println(e.getStackTrace()); + throw e; + } finally { + closeQuietly(filewriter); + } + } } 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 5c5931a80..78f36f5c9 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 @@ -41,6 +41,8 @@ import org.collectionspace.services.config.types.PropertyItemType; import org.collectionspace.services.config.types.PropertyType; import org.collectionspace.services.nuxeo.client.java.NuxeoConnectorEmbedded; import org.collectionspace.services.nuxeo.client.java.TenantRepository; + +import org.apache.commons.io.FileUtils; import org.jboss.resteasy.spi.ResteasyProviderFactory; import org.dom4j.Document; import org.slf4j.Logger; @@ -70,11 +72,7 @@ public class ServiceMain { private ServicesConfigReaderImpl servicesConfigReader; private TenantBindingConfigReaderImpl tenantBindingConfigReader; private UriTemplateRegistry uriTemplateRegistry = new UriTemplateRegistry(); - - private static final String COMPONENT_EXTENSION_XPATH = "/component/extension[@point='%s']"; - private static final String DATASOURCE_EXTENSION_POINT_XPATH = String.format(COMPONENT_EXTENSION_XPATH, "datasources"); - private static final String REPOSITORY_EXTENSION_POINT_XPATH = String.format(COMPONENT_EXTENSION_XPATH, "repository"); - + private static final String DROP_DATABASE_SQL_CMD = "DROP DATABASE"; private static final String DROP_DATABASE_IF_EXISTS_SQL_CMD = DROP_DATABASE_SQL_CMD + " IF EXISTS %s;"; private static final String DROP_USER_SQL_CMD = "DROP USER"; @@ -163,6 +161,7 @@ public class ServiceMain { // Create or update Nuxeo's per-repository configuration files. createOrUpdateNuxeoDatasourceConfigFiles(); createOrUpdateNuxeoRepositoryConfigFiles(); + createOrUpdateNuxeoElasticsearchConfigFiles(); // Create the Nuxeo-managed databases, along with the requisite // access rights to each. @@ -417,13 +416,21 @@ public class ServiceMain { } private String getNuxeoProtoConfigFilename() { - return JEEServerDeployment.NUXEO_PROTOTYPE_CONFIG_FILENAME; + return JEEServerDeployment.NUXEO_PROTOTYPE_REPO_CONFIG_FILENAME; } private String getNuxeoProtoDatasourceFilename() { return JEEServerDeployment.NUXEO_PROTOTYPE_DATASOURCE_FILENAME; - } + } + private String getNuxeoProtoElasticsearchConfigFilename() { + return JEEServerDeployment.NUXEO_PROTO_ELASTICSEARCH_CONFIG_FILENAME; + } + + private String getNuxeoProtoElasticsearchExtensionFilename() { + return JEEServerDeployment.NUXEO_PROTO_ELASTICSEARCH_EXTENSION_FILENAME; + } + private String getDatabaseScriptsPath() { DatabaseProductType dbType; String databaseProductName; @@ -842,6 +849,104 @@ public class ServiceMain { } } } + + private File getProtoElasticsearchConfigFile() throws Exception { + File result = new File(getCspaceServicesConfigDir() + File.separator + + getNuxeoProtoElasticsearchConfigFilename()); + // FIXME: Consider checking for the presence of existing configuration + // files, rather than always failing outright if the prototype file for + // creating new or updated files can't be located. + if (result.canRead() == false) { + String msg = String + .format("Could not find and/or read the prototype Elasticsearch config file '%s'. " + + "Please redeploy this file by running 'ant deploy' from the Services layer source code's '3rdparty/nuxeo' module.", + result.getCanonicalPath()); + throw new RuntimeException(msg); + } + + if (logger.isInfoEnabled()) { + logger.info("Found and can read the prototype Elasticsearch configuration file at path '%s'.", + result.getAbsolutePath()); + } + + return result; + } + + private File getProtoElasticsearchExtensionFile() throws Exception { + File result = new File(getCspaceServicesConfigDir() + File.separator + + getNuxeoProtoElasticsearchExtensionFilename()); + // FIXME: Consider checking for the presence of existing configuration + // files, rather than always failing outright if the prototype file for + // creating new or updated files can't be located. + if (result.canRead() == false) { + String msg = String + .format("Could not find and/or read the prototype Elasticsearch extension file '%s'. " + + "Please redeploy this file by running 'ant deploy' from the Services layer source code's '3rdparty/nuxeo' module.", + result.getCanonicalPath()); + throw new RuntimeException(msg); + } + + if (logger.isInfoEnabled()) { + logger.info("Found and can read the prototype Elasticsearch extension file at path %s", + result.getAbsolutePath()); + } + + return result; + } + + private void createOrUpdateNuxeoElasticsearchConfigFiles() throws Exception { + // + // Get the prototype copy of the Nuxeo Elasticsearch extension element and + // fill it in for each tenant + // + File protoElasticsearchExtensionFile = getProtoElasticsearchExtensionFile(); + StringBuffer extensionList = new StringBuffer(); + Hashtable tenantBindingTypeMap = tenantBindingConfigReader.getTenantBindings(); + for (TenantBindingType tbt : tenantBindingTypeMap.values()) { + List repositoryNameList = ConfigUtils.getRepositoryNameList(tbt); + logger.debug("Getting repository name(s) for tenant " + tbt.getName()); + + if (repositoryNameList == null || repositoryNameList.isEmpty() == true) { + logger.error(String.format("Could not get repository name(s) for tenant %s", tbt.getName())); + continue; // break out of loop and go to the next tenant binding + } else { + for (String repositoryName : repositoryNameList) { + if (Tools.isBlank(repositoryName)) { + logger.error(String.format("Repository name(s) for tenant %s was empty.", tbt.getName())); + } else { + logger.debug(String.format("Repository name is %s", repositoryName)); + Document protoElasticsearchExtensionDoc = XmlTools.fileToXMLDocument(protoElasticsearchExtensionFile); + + protoElasticsearchExtensionDoc = updateElasticSearchExtensionDoc(protoElasticsearchExtensionDoc, repositoryName, this.getCspaceInstanceId()); + if (logger.isDebugEnabled()) { + String extension = protoElasticsearchExtensionDoc.asXML(); + logger.trace(String.format("Updated Elasticsearch extension for '%s' repository: contents=\n", repositoryName, extension)); + } + //extensionList.append(protoElasticsearchExtensionDoc.asXML() + '\n'); + extensionList.append(XmlTools.asXML(protoElasticsearchExtensionDoc, true) + '\n'); + } + } + } + } + + // + // Create the final Nuxeo Elasticsearch configuration file and deploy it to the Nuxeo server. + // + if (extensionList.length() > 0) { + // Get the prototype copy of the Nuxeo Elasticsearch config file. + String str = FileUtils.readFileToString(getProtoElasticsearchConfigFile()); + str = str.replace(ConfigUtils.ELASTICSEARCH_EXTENSIONS_EXPANDER_STR, extensionList); + + // + // Create the final xml Elasticsearch config and fill in the correct values. + // + File elasticSearchConfigFile = new File(getNuxeoConfigDir() + File.separator + + JEEServerDeployment.NUXEO_ELASTICSEARCH_CONFIG_FILENAME); + FileUtilities.StringToFile(str, elasticSearchConfigFile); + } else { + logger.error("Could not create Elasticsearch configuration files. Check that the prototype configuration files are properly formatted and in the correct location."); + } + } /** * Ensure that Nuxeo repository configuration files exist for each repository @@ -928,24 +1033,24 @@ public class ServiceMain { // Text substitutions within first extension point, "repository" repoConfigDoc = XmlTools.setAttributeValue(repoConfigDoc, - REPOSITORY_EXTENSION_POINT_XPATH + "/repository", "name", + ConfigUtils.REPOSITORY_EXTENSION_POINT_XPATH + "/repository", "name", repositoryName); repoConfigDoc = XmlTools.setAttributeValue(repoConfigDoc, - REPOSITORY_EXTENSION_POINT_XPATH + "/repository", "name", + ConfigUtils.REPOSITORY_EXTENSION_POINT_XPATH + "/repository", "name", repositoryName); repoConfigDoc = XmlTools.setAttributeValue(repoConfigDoc, - REPOSITORY_EXTENSION_POINT_XPATH + "/repository/binaryStore", "path", + ConfigUtils.REPOSITORY_EXTENSION_POINT_XPATH + "/repository/binaryStore", "path", Tools.isBlank(binaryStorePath) ? repositoryName : binaryStorePath); // Can be either partial or full path. Partial path will be relative to Nuxeo's data directory /* Create the JDBC url options if any exist */ String jdbcOptions = XmlTools.getElementValue(repoConfigDoc, - REPOSITORY_EXTENSION_POINT_XPATH + "/repository/property[@name='JDBCOptions']"); + ConfigUtils.REPOSITORY_EXTENSION_POINT_XPATH + "/repository/property[@name='JDBCOptions']"); jdbcOptions = Tools.isBlank(jdbcOptions) ? "" : "?" + jdbcOptions; repoConfigDoc = XmlTools.setElementValue(repoConfigDoc, - REPOSITORY_EXTENSION_POINT_XPATH + "/repository/property[@name='DatabaseName']", + ConfigUtils.REPOSITORY_EXTENSION_POINT_XPATH + "/repository/property[@name='DatabaseName']", databaseName + jdbcOptions); return repoConfigDoc; @@ -964,50 +1069,79 @@ public class ServiceMain { // Set the element's name attribute String datasoureName = "jdbc/" + repositoryName; repoConfigDoc = XmlTools.setAttributeValue(repoConfigDoc, - DATASOURCE_EXTENSION_POINT_XPATH + "/datasource", "name", datasoureName); + ConfigUtils.DATASOURCE_EXTENSION_POINT_XPATH + "/datasource", "name", datasoureName); // Get the DB server name String serverName = XmlTools.getElementValue(repoConfigDoc, - DATASOURCE_EXTENSION_POINT_XPATH + "/property[@name='ServerName']"); + ConfigUtils.DATASOURCE_EXTENSION_POINT_XPATH + "/property[@name='ServerName']"); // Get the JDBC options String jdbcOptions = XmlTools.getElementValue(repoConfigDoc, - DATASOURCE_EXTENSION_POINT_XPATH + "/property[@name='JDBCOptions']"); + ConfigUtils.DATASOURCE_EXTENSION_POINT_XPATH + "/property[@name='JDBCOptions']"); jdbcOptions = Tools.isBlank(jdbcOptions) ? "" : "?" + jdbcOptions; // Get the DB port nubmer String portNumber = XmlTools.getElementValue(repoConfigDoc, - DATASOURCE_EXTENSION_POINT_XPATH + "/property[@name='PortNumber']"); + ConfigUtils.DATASOURCE_EXTENSION_POINT_XPATH + "/property[@name='PortNumber']"); // Build the JDBC URL from the parts String jdbcUrl = String.format("jdbc:postgresql://%s:%s/%s%s", //FIXME: 'postgresql' string should not be hard coded here serverName, portNumber, databaseName, jdbcOptions); // Set the element's url attribute repoConfigDoc = XmlTools.setAttributeValue(repoConfigDoc, - DATASOURCE_EXTENSION_POINT_XPATH + "/datasource", "url", jdbcUrl); + ConfigUtils.DATASOURCE_EXTENSION_POINT_XPATH + "/datasource", "url", jdbcUrl); logger.debug(String.format("Built up the following JDBC url: %s", jdbcUrl)); // Get the DB username String username = XmlTools.getElementValue(repoConfigDoc, - DATASOURCE_EXTENSION_POINT_XPATH + "/property[@name='User']"); + ConfigUtils.DATASOURCE_EXTENSION_POINT_XPATH + "/property[@name='User']"); // Set the element's user attribute repoConfigDoc = XmlTools.setAttributeValue(repoConfigDoc, - DATASOURCE_EXTENSION_POINT_XPATH + "/datasource", "username", username); + ConfigUtils.DATASOURCE_EXTENSION_POINT_XPATH + "/datasource", "username", username); // Get the DB password String password = XmlTools.getElementValue(repoConfigDoc, - DATASOURCE_EXTENSION_POINT_XPATH + "/property[@name='Password']"); + ConfigUtils.DATASOURCE_EXTENSION_POINT_XPATH + "/property[@name='Password']"); // Set the element's password attribute repoConfigDoc = XmlTools.setAttributeValue(repoConfigDoc, - DATASOURCE_EXTENSION_POINT_XPATH + "/datasource", "password", password); + ConfigUtils.DATASOURCE_EXTENSION_POINT_XPATH + "/datasource", "password", password); // Set the element's name attribute repoConfigDoc = XmlTools.setAttributeValue(repoConfigDoc, - DATASOURCE_EXTENSION_POINT_XPATH + "/link", "name", "jdbc/repository_" + repositoryName); + ConfigUtils.DATASOURCE_EXTENSION_POINT_XPATH + "/link", "name", "jdbc/repository_" + repositoryName); // Set the element's global attribute repoConfigDoc = XmlTools.setAttributeValue(repoConfigDoc, - DATASOURCE_EXTENSION_POINT_XPATH + "/link", "global", datasoureName); + ConfigUtils.DATASOURCE_EXTENSION_POINT_XPATH + "/link", "global", datasoureName); return repoConfigDoc; - } + } + + private String getElasticsearchIndexName(Document repoConfigDoc, String repositoryName, + String cspaceInstanceId) { + String result = ConfigUtils.DEFAULT_ELASTICSEARCH_INDEX_NAME; + + if (repositoryName.equalsIgnoreCase(ConfigUtils.DEFAULT_NUXEO_REPOSITORY_NAME) == false) { + return repositoryName; + } + + return result; + } + + /* + * This method is filling out the elasticsearch-config.xml file with tenant specific repository information. + */ + private Document updateElasticSearchExtensionDoc(Document elasticsearchConfigDoc, String repositoryName, + String cspaceInstanceId) { + + // Set the element's name attribute + String indexName = getElasticsearchIndexName(elasticsearchConfigDoc, repositoryName, cspaceInstanceId); + elasticsearchConfigDoc = XmlTools.setAttributeValue(elasticsearchConfigDoc, + ConfigUtils.ELASTICSEARCH_INDEX_EXTENSION_XPATH + "/elasticSearchIndex", "name", indexName); + + // Set the element's repository attribute + elasticsearchConfigDoc = XmlTools.setAttributeValue(elasticsearchConfigDoc, + ConfigUtils.ELASTICSEARCH_INDEX_EXTENSION_XPATH + "/elasticSearchIndex", "repository", repositoryName); + + return elasticsearchConfigDoc; + } /** * Update the current copy of the Nuxeo databases initialization script file by 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 4507fb802..7bcdc288f 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 @@ -5,6 +5,7 @@ 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; import org.dom4j.DocumentException; @@ -26,6 +27,7 @@ public class XmlTools { // Output format for XML pretty printing. public final static OutputFormat PRETTY_PRINT_OUTPUT_FORMAT = defaultPrettyPrintOutputFormat(); + public final static String UTF8_ENCODING = "UTF-8"; /** @@ -107,6 +109,25 @@ public class XmlTools { return doc; } + + public static String asXML(Document doc, boolean suppressDeclaration) { + OutputFormat format = new OutputFormat(); + format.setSuppressDeclaration(suppressDeclaration); + format.setEncoding(UTF8_ENCODING); + + try { + StringWriter out = new StringWriter(); + XMLWriter writer = new XMLWriter(out, format); + writer.write(doc); + writer.flush(); + + return out.toString(); + } catch (IOException e) { + throw new RuntimeException("IOException while generating textual " + + "representation: " + e.getMessage()); + } + } + /** * Returns a dom4j XML document, when provided with a file * containing a well-formed XML document. diff --git a/services/common/src/main/java/org/collectionspace/services/common/blob/BlobInput.java b/services/common/src/main/java/org/collectionspace/services/common/blob/BlobInput.java index 5bc9eea7b..222634c48 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/blob/BlobInput.java +++ b/services/common/src/main/java/org/collectionspace/services/common/blob/BlobInput.java @@ -175,7 +175,7 @@ public class BlobInput { // are we also receiving the blobUri? // public void createBlobFile(HttpServletRequest req, String blobUri) throws Exception { - File tmpFile = org.collectionspace.services.common.FileUtils.createTmpFile(req); + File tmpFile = org.collectionspace.services.common.FileUtilities.createTmpFile(req); this.setBlobFile(tmpFile); this.setBlobUri(blobUri); } diff --git a/services/common/src/main/java/org/collectionspace/services/common/imaging/nuxeo/NuxeoBlobUtils.java b/services/common/src/main/java/org/collectionspace/services/common/imaging/nuxeo/NuxeoBlobUtils.java index 949b7e3e4..77c7c52c6 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/imaging/nuxeo/NuxeoBlobUtils.java +++ b/services/common/src/main/java/org/collectionspace/services/common/imaging/nuxeo/NuxeoBlobUtils.java @@ -66,7 +66,7 @@ import org.slf4j.LoggerFactory; import org.apache.commons.io.IOUtils; import org.collectionspace.services.client.PoxPayloadIn; import org.collectionspace.services.client.PoxPayloadOut; -import org.collectionspace.services.common.FileUtils; +import org.collectionspace.services.common.FileUtilities; import org.collectionspace.services.common.ServiceMain; import org.collectionspace.services.common.blob.BlobInput; import org.collectionspace.services.common.context.ServiceContext; @@ -699,7 +699,7 @@ public class NuxeoBlobUtils { // String sanitizedName = NuxeoBlobUtils.getSanizitedFilename(originalFile); if (sanitizedName.equals(originalFile.getName()) == false) { - targetFile = FileUtils.createTmpFile(originalFile, sanitizedName); + targetFile = FileUtilities.createTmpFile(originalFile, sanitizedName); if (logger.isDebugEnabled() == true) { logger.debug(String.format("The file '%s''s name has characters that Nuxeo can't deal with. Rather than renaming the file, we created a new temp file at '%s'", originalFile.getName(), targetFile.getAbsolutePath())); diff --git a/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/CoreSessionInterface.java b/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/CoreSessionInterface.java index 5fbb014db..228cf218b 100644 --- a/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/CoreSessionInterface.java +++ b/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/CoreSessionInterface.java @@ -16,6 +16,10 @@ public interface CoreSessionInterface { public CoreSession getCoreSession(); + public void setTransactionRollbackOnly(); + + public boolean isTransactionMarkedForRollbackOnly(); + /** * Gets the root document of this repository. * diff --git a/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/CoreSessionWrapper.java b/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/CoreSessionWrapper.java index cbfaeef69..2de822bdf 100644 --- a/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/CoreSessionWrapper.java +++ b/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/CoreSessionWrapper.java @@ -2,23 +2,24 @@ package org.collectionspace.services.nuxeo.client.java; import java.security.Principal; -import org.collectionspace.services.nuxeo.util.NuxeoUtils; import org.nuxeo.ecm.core.api.ClientException; import org.nuxeo.ecm.core.api.DocumentModel; import org.nuxeo.ecm.core.api.DocumentModelList; import org.nuxeo.ecm.core.api.DocumentRef; import org.nuxeo.ecm.core.api.Filter; import org.nuxeo.ecm.core.api.IterableQueryResult; -import org.nuxeo.ecm.core.api.NoRollbackOnException; import org.nuxeo.ecm.core.api.event.DocumentEventTypes; import org.nuxeo.ecm.core.api.impl.LifeCycleFilter; import org.nuxeo.ecm.core.api.CoreSession; +import org.nuxeo.runtime.transaction.TransactionHelper; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class CoreSessionWrapper implements CoreSessionInterface { private CoreSession repoSession; + private boolean transactionSetForRollback = false; /** The logger. */ private static Logger logger = LoggerFactory.getLogger(CoreSessionWrapper.class); @@ -37,11 +38,28 @@ public class CoreSessionWrapper implements CoreSessionInterface { filter != null ? filter.toString() : "none", limit, offset, countTotal, query)); } - public CoreSessionWrapper(CoreSession repoSession) { this.repoSession = repoSession; } + /* + * Mark this session's transaction for rollback only + */ + @Override + public void setTransactionRollbackOnly() { + TransactionHelper.setTransactionRollbackOnly(); + transactionSetForRollback = true; + } + + @Override + public boolean isTransactionMarkedForRollbackOnly() { + if (transactionSetForRollback != TransactionHelper.isTransactionMarkedRollback()) { + logger.error(String.format("Transaction status is in an inconsistent state. Internal state is '%b'. TransactionHelper statis is '%b'.", + transactionSetForRollback, TransactionHelper.isTransactionMarkedRollback())); + } + return transactionSetForRollback; + } + @Override public CoreSession getCoreSession() { return repoSession; @@ -54,7 +72,12 @@ public class CoreSessionWrapper implements CoreSessionInterface { @Override public void close() throws Exception { - repoSession.close(); + try { + repoSession.close(); + } catch (Throwable t) { + logger.error(String.format("Could not close session for repository '%s'.", this.repoSession.getRepositoryName()), + t); + } } /** @@ -134,7 +157,6 @@ public class CoreSessionWrapper implements CoreSessionInterface { * @throws ClientException * @throws SecurityException */ - @NoRollbackOnException @Override public DocumentModel getDocument(DocumentRef docRef) throws ClientException { return repoSession.getDocument(docRef); @@ -142,12 +164,36 @@ public class CoreSessionWrapper implements CoreSessionInterface { @Override public DocumentModel saveDocument(DocumentModel docModel) throws ClientException { - return repoSession.saveDocument(docModel); + DocumentModel result = null; + + try { + if (isTransactionMarkedForRollbackOnly() == false) { + result = repoSession.saveDocument(docModel); + } else { + logger.trace(String.format("The repository session on thread '%d' has a transaction that is marked for rollback.", + Thread.currentThread().getId())); + } + } catch (Throwable t) { + setTransactionRollbackOnly(); + throw t; + } + + return result; } @Override public void save() throws ClientException { - repoSession.save(); + try { + if (isTransactionMarkedForRollbackOnly() == false) { + repoSession.save(); + } else { + logger.trace(String.format("The repository session on thread '%d' has a transaction that is marked for rollback.", + Thread.currentThread().getId())); + } + } catch (Throwable t) { + setTransactionRollbackOnly(); + throw t; + } } /** @@ -158,7 +204,17 @@ public class CoreSessionWrapper implements CoreSessionInterface { */ @Override public void saveDocuments(DocumentModel[] docModels) throws ClientException { - repoSession.saveDocuments(docModels); + try { + if (isTransactionMarkedForRollbackOnly() == false) { + repoSession.saveDocuments(docModels); + } else { + logger.trace(String.format("The repository session on thread '%d' has a transaction that is marked for rollback.", + Thread.currentThread().getId())); + } + } catch (Throwable t) { + setTransactionRollbackOnly(); + throw t; + } } /** @@ -217,7 +273,6 @@ public class CoreSessionWrapper implements CoreSessionInterface { * specified parent document is not a folder * @throws ClientException */ - @NoRollbackOnException @Override public DocumentModelList getChildren(DocumentRef parent) throws ClientException { return repoSession.getChildren(parent); diff --git a/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/NuxeoClientEmbedded.java b/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/NuxeoClientEmbedded.java index 5d192f215..559e3ccf4 100644 --- a/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/NuxeoClientEmbedded.java +++ b/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/NuxeoClientEmbedded.java @@ -331,7 +331,7 @@ public final class NuxeoClientEmbedded { repoSession.save(); } catch (Exception e) { String errMsg = String.format("Possible data loss. Could not save and/or close the Nuxeo repository name = '%s'.", name); - logger.trace(errMsg, e); + logger.warn(errMsg, e); throw e; } finally { repoSession.close(); diff --git a/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RepositoryJavaClientImpl.java b/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RepositoryJavaClientImpl.java index 1330b01ad..33246138f 100644 --- a/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RepositoryJavaClientImpl.java +++ b/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RepositoryJavaClientImpl.java @@ -71,6 +71,7 @@ import org.apache.chemistry.opencmis.commons.enums.CmisVersion; import org.apache.chemistry.opencmis.commons.server.CallContext; import org.apache.chemistry.opencmis.server.impl.CallContextImpl; import org.apache.chemistry.opencmis.server.shared.ThresholdOutputStreamFactory; + import org.nuxeo.common.utils.IdUtils; import org.nuxeo.ecm.core.api.ClientException; import org.nuxeo.ecm.core.api.DocumentModel; @@ -84,6 +85,7 @@ import org.nuxeo.ecm.core.api.PathRef; import org.nuxeo.runtime.transaction.TransactionRuntimeException; import org.nuxeo.ecm.core.opencmis.bindings.NuxeoCmisServiceFactory; import org.nuxeo.ecm.core.opencmis.impl.server.NuxeoCmisService; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -210,7 +212,6 @@ public class RepositoryJavaClientImpl implements RepositoryClient