<copy todir="${jee.server.cspace}/nuxeo-server">
<fileset dir="${basedir}/nuxeo-server/${nuxeo.release}">
<exclude name="**/config/proto-*-config.xml"/>
+ <exclude name="**/config/proto-*-extension.xml"/>
</fileset>
</copy>
<echo message="Copying Nuxeo prototype repo config file ..."/>
<filter token="NUXEO_PW" value="${db.nuxeo.user.password}"/>
</filterset>
</copy>
+ <copy todir="${jee.server.cspace}/cspace/config/services" overwrite="true">
+ <fileset file="${basedir}/nuxeo-server/${nuxeo.release}/config/proto-elasticsearch-config.xml"/>
+ </copy>
+ <copy todir="${jee.server.cspace}/cspace/config/services" overwrite="true">
+ <fileset file="${basedir}/nuxeo-server/${nuxeo.release}/config/proto-elasticsearch-extension.xml"/>
+ </copy>
<ant antfile="nuxeo-platform-collectionspace/build.xml" target="deploy" inheritall="false"/>
<ant antfile="nuxeo-platform-listener/build.xml" target="deploy" inheritall="false"/>
+++ /dev/null
-<?xml version="1.0"?>
-<component name="org.nuxeo.elasticsearch.defaultConfig">
- <require>org.nuxeo.elasticsearch.ElasticSearchComponent</require>
-
- <extension target="org.nuxeo.elasticsearch.ElasticSearchComponent"
- point="elasticSearchLocal">
- <elasticSearchLocal
- clusterName="nuxeoCluster"
- nodeName="nuxeoNode"
- pathData="C:\dev\tools\nuxeo-cap-6.0-tomcat\nxserver\data/elasticsearch"
- pathLogs="C:\dev\tools\nuxeo-cap-6.0-tomcat\log/elasticsearch"
- httpEnabled="false" />
- </extension>
-
- <extension target="org.nuxeo.elasticsearch.ElasticSearchComponent"
- point="elasticSearchIndex">
- <elasticSearchIndex name="nuxeo" type="doc" repository="default">
- <fetchFromSource>
- <include>ecm:*</include>
- <include>dc:*</include>
- <exclude>ecm:binarytext</exclude>
- </fetchFromSource>
-
- <settings>
-{
- "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"
- }
- }
- }
-}
- </settings>
- <mapping>
-{
- "_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"
- }
- }
-}
- </mapping>
-
- </elasticSearchIndex>
- </extension>
-
- <extension target="org.nuxeo.elasticsearch.ElasticSearchComponent"
- point="elasticSearchIndex">
- <elasticSearchIndex name="lifesci_domain" type="doc" repository="lifesci_domain">
- <fetchFromSource>
- <include>ecm:*</include>
- <include>dc:*</include>
- <exclude>ecm:binarytext</exclude>
- </fetchFromSource>
-
- <settings>
-{
- "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"
- }
- }
- }
-}
- </settings>
- <mapping>
-{
- "_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"
- }
- }
-}
- </mapping>
-
- </elasticSearchIndex>
- </extension>
-
-</component>
-
--- /dev/null
+<?xml version="1.0"?>
+<component name="org.nuxeo.elasticsearch.defaultConfig">
+ <require>org.nuxeo.elasticsearch.ElasticSearchComponent</require>
+
+ <!--
+ <extension target="org.nuxeo.elasticsearch.ElasticSearchComponent"
+ point="elasticSearchLocal">
+ <elasticSearchLocal
+ clusterName="nuxeoCluster"
+ nodeName="nuxeoNode"
+ pathData="C:\dev\tools\apache-tomcat-7.0.57\nuxeo-server\data\elasticsearch"
+ pathLogs="C:\dev\tools\apache-tomcat-7.0.57\nuxeo-server\log\elasticsearch"
+ httpEnabled="true" />
+ </extension>
+ -->
+
+ <extension target="org.nuxeo.elasticsearch.ElasticSearchComponent"
+ point="elasticSearchRemote">
+ <elasticSearchRemote
+ clusterName="elasticsearch"
+ addressList="localhost:9300"
+ clientTransportSniff="false"
+ clientTransportIgnoreClusterName="false"
+ clientTransportPingTimeout="5s"
+ clientTransportNodesSamplerInterval="5s" />
+ </extension>
+
+ %elasticSearchIndex_extensions%
+
+ </component>
+
--- /dev/null
+ <extension target="org.nuxeo.elasticsearch.ElasticSearchComponent"
+ point="elasticSearchIndex">
+ <elasticSearchIndex name="index_name_placeholder" type="doc" repository="repository_name_placeholder">
+ <fetchFromSource>
+ <include>ecm:*</include>
+ <include>dc:*</include>
+ <exclude>ecm:binarytext</exclude>
+ </fetchFromSource>
+
+ <settings>
+{
+ "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"
+ }
+ }
+ }
+}
+ </settings>
+ <mapping>
+{
+ "_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"
+ }
+ }
+}
+ </mapping>
+
+ </elasticSearchIndex>
+ </extension>
\ No newline at end of file
# 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);
domain.nuxeo=nuxeo-server
#nuxeo
-nuxeo.release=6.0
+nuxeo.release=6.0-HF21
nuxeo.ear=nuxeo.ear
nuxeo.system=bundles
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<cspace.services.version>4.3-SNAPSHOT</cspace.services.version>
<cspace.services.client.version>4.3-SNAPSHOT</cspace.services.client.version>
- <nuxeo.general.release>6.0</nuxeo.general.release>
+ <nuxeo.general.release>6.0-HF21</nuxeo.general.release>
<nuxeo.shell.version>${nuxeo.general.release}</nuxeo.shell.version>
<nuxeo.platform.version>${nuxeo.general.release}</nuxeo.platform.version>
<nuxeo.core.version>${nuxeo.general.release}</nuxeo.core.version>
<artifactId>lucene-analyzers-common</artifactId>
<groupId>org.apache.lucene</groupId>
</exclusion>
+ <exclusion>
+ <artifactId>nuxeo-automation-server</artifactId>
+ <groupId>org.nuxeo.ecm.automation</groupId>
+ </exclusion>
+ <exclusion>
+ <artifactId>nuxeo-automation-io</artifactId>
+ <groupId>org.nuxeo.ecm.automation</groupId>
+ </exclusion>
+ <exclusion>
+ <artifactId>jsp-api-2.1</artifactId>
+ <groupId>org.mortbay.jetty</groupId>
+ </exclusion>
+ <exclusion>
+ <artifactId>jsp-2.1</artifactId>
+ <groupId>org.mortbay.jetty</groupId>
+ </exclusion>
</exclusions>
</dependency>
<dependency>
<artifactId>jsf-impl</artifactId>
<groupId>com.sun.faces</groupId>
</exclusion>
+ <exclusion>
+ <artifactId>el-api</artifactId>
+ <groupId>javax.el</groupId>
+ </exclusion>
</exclusions>
</dependency>
<dependency>
# 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
#
<dependency>
<groupId>org.collectionspace.services</groupId>
<artifactId>org.collectionspace.services.common</artifactId>
+ <exclusions>
+ <exclusion>
+ <artifactId>nuxeo-automation-io</artifactId>
+ <groupId>org.nuxeo.ecm.automation</groupId>
+ </exclusion>
+ <exclusion>
+ <artifactId>nuxeo-automation-server</artifactId>
+ <groupId>org.nuxeo.ecm.automation</groupId>
+ </exclusion>
+ </exclusions>
</dependency>
<dependency>
<groupId>org.collectionspace.services</groupId>
}
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();
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;
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();
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";
//import javax.servlet.ServletException;
//import javax.servlet.http.HttpServlet;
+
+
import net.sf.jmimemagic.Magic;
import net.sf.jmimemagic.MagicException;
import net.sf.jmimemagic.MagicMatch;
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;
/**
* 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_";
* 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;
}
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);
+ }
+ }
}
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;
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";
// 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.
}
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;
}
}
}
+
+ 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<String, TenantBindingType> tenantBindingTypeMap = tenantBindingConfigReader.getTenantBindings();
+ for (TenantBindingType tbt : tenantBindingTypeMap.values()) {
+ List<String> 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
// 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;
// Set the <datasource> 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 <datasource> 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 <datasource> 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 <datasource> 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 <link> 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 <link> 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 <elasticSearchIndex> element's name attribute
+ String indexName = getElasticsearchIndexName(elasticsearchConfigDoc, repositoryName, cspaceInstanceId);
+ elasticsearchConfigDoc = XmlTools.setAttributeValue(elasticsearchConfigDoc,
+ ConfigUtils.ELASTICSEARCH_INDEX_EXTENSION_XPATH + "/elasticSearchIndex", "name", indexName);
+
+ // Set the <elasticSearchIndex> 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
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;
// Output format for XML pretty printing.
public final static OutputFormat PRETTY_PRINT_OUTPUT_FORMAT = defaultPrettyPrintOutputFormat();
+ public final static String UTF8_ENCODING = "UTF-8";
/**
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.
// 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);
}
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;
//
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()));
public CoreSession getCoreSession();
+ public void setTransactionRollbackOnly();
+
+ public boolean isTransactionMarkedForRollbackOnly();
+
/**
* Gets the root document of this repository.
*
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);
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;
@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);
+ }
}
/**
* @throws ClientException
* @throws SecurityException
*/
- @NoRollbackOnException
@Override
public DocumentModel getDocument(DocumentRef docRef) throws ClientException {
return repoSession.getDocument(docRef);
@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;
+ }
}
/**
*/
@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;
+ }
}
/**
* specified parent document is not a folder
* @throws ClientException
*/
- @NoRollbackOnException
@Override
public DocumentModelList getChildren(DocumentRef parent) throws ClientException {
return repoSession.getChildren(parent);
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();
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;
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;
} catch (BadRequestException bre) {
throw bre;
} catch (Exception e) {
- logger.error("Caught exception ", e);
throw new NuxeoDocumentException(e);
} finally {
if (repoSession != null) {
} catch (CSWebApplicationException wae) {
throw wae;
} catch (Exception e) {
- if (logger.isDebugEnabled()) {
- logger.debug("Caught exception ", e);
- }
throw new NuxeoDocumentException(e);
} finally {
if (repoSession != null) {
public class ConfigUtils {
final static Logger logger = LoggerFactory.getLogger(ConfigUtils.class);
+ public static final String EXTENSION_XPATH = "/extension[@point='%s']";
+ public static final String COMPONENT_EXTENSION_XPATH = "/component" + EXTENSION_XPATH;
+ public static final String DATASOURCE_EXTENSION_POINT_XPATH = String.format(COMPONENT_EXTENSION_XPATH, "datasources");
+ public static final String REPOSITORY_EXTENSION_POINT_XPATH = String.format(COMPONENT_EXTENSION_XPATH, "repository");
+ public static final String ELASTICSEARCH_INDEX_EXTENSION_XPATH = String.format(EXTENSION_XPATH, "elasticSearchIndex");
+ public static final String ELASTICSEARCH_EXTENSIONS_EXPANDER_STR = "%elasticSearchIndex_extensions%";
+
+
// Default database names
-// public static String DEFAULT_CSPACE_DATABASE_NAME = "cspace";
+
+ // public static String DEFAULT_CSPACE_DATABASE_NAME = "cspace";
public static String DEFAULT_NUXEO_REPOSITORY_NAME = "default";
public static String DEFAULT_NUXEO_DATABASE_NAME = "nuxeo";
+ public static String DEFAULT_ELASTICSEARCH_INDEX_NAME = "nuxeo";
/*
* Returns the list of repository/DB names defined by a tenant bindings file
import org.collectionspace.services.client.PoxPayloadOut;
import org.collectionspace.services.common.AbstractCollectionSpaceResourceImpl;
import org.collectionspace.services.common.ConfigurationException;
-import org.collectionspace.services.common.FileUtils;
+import org.collectionspace.services.common.FileUtilities;
import org.collectionspace.services.common.ServiceMain;
import org.collectionspace.services.common.ServiceMessages;
import org.collectionspace.services.common.api.FileTools;
fileStream = part.getBody(InputStream.class, null);
- File zipfile = FileUtils.createTmpFile(fileStream,
+ File zipfile = FileUtilities.createTmpFile(fileStream,
getServiceName() + "_");
String zipfileName = zipfile.getCanonicalPath();
logger.trace("Imports zip file saved to:" + zipfileName);