From 428e92479a4e17849a9b99efac29438a1afafc65 Mon Sep 17 00:00:00 2001 From: Derek Hulley Date: Mon, 3 Mar 2008 14:10:10 +0000 Subject: [PATCH] Merged V2.2 to HEAD 7560: Better handling of exceptions in WCM File Picker when folder or search restriction values invalid 7567: Minor fix-up of incorrectly encoded text Fixed line endings on repository.properties 7568: Fixed AR-1812: Use hibernate.default_schema to control visibility of metadata queries git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@8415 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../messages/schema-update.properties | 1 + config/alfresco/repository.properties | 380 +++++++++--------- .../repo/domain/schema/SchemaBootstrap.java | 51 ++- 3 files changed, 234 insertions(+), 198 deletions(-) diff --git a/config/alfresco/messages/schema-update.properties b/config/alfresco/messages/schema-update.properties index e44cf2a74a..6afd8b1618 100644 --- a/config/alfresco/messages/schema-update.properties +++ b/config/alfresco/messages/schema-update.properties @@ -10,6 +10,7 @@ schema.update.msg.executing_statement= Executing statement: {0} schema.update.msg.optional_statement_failed=Optional statement execution failed:\n SQL: {0}\n Error: {1}\n File: {2}\n Line: {3} schema.update.warn.dialect_unsupported=Alfresco should not be used with database dialect {0}. schema.update.warn.dialect_hsql=Alfresco is using the HSQL default database. Please only use this while evaluating Alfresco, it is NOT recommended for production or deployment! +schema.update.err.found_multiple=\nMore than one Alfresco schema was found when querying the database metadata.\n Limit the database user's permissions or set the 'hibernate.default_schema' property in 'custom-hibernate-dialect.properties'. schema.update.err.previous_failed=A previous schema upgrade failed. Revert to the original database before attempting the upgrade again. schema.update.err.statement_failed=Statement execution failed:\n SQL: {0}\n Error: {1}\n File: {2}\n Line: {3} schema.update.err.update_failed=Schema auto-update failed diff --git a/config/alfresco/repository.properties b/config/alfresco/repository.properties index d06aa10385..7d60352d63 100644 --- a/config/alfresco/repository.properties +++ b/config/alfresco/repository.properties @@ -1,190 +1,190 @@ -# Directory configuration - -dir.root=./alf_data - -dir.contentstore=${dir.root}/contentstore -dir.contentstore.deleted=${dir.root}/contentstore.deleted - -dir.auditcontentstore=${dir.root}/audit.contentstore - -# The location for lucene index files -dir.indexes=${dir.root}/lucene-indexes - -# The location for lucene index locks -dir.indexes.lock=${dir.indexes}/locks - -# ######################################### # -# Index Recovery and Tracking Configuration # -# ######################################### # -# -# Recovery types are: -# NONE: Ignore -# VALIDATE: Checks that the first and last transaction for each store is represented in the indexes -# AUTO: Validates and auto-recovers if validation fails -# FULL: Full index rebuild, processing all transactions in order. The server is temporarily suspended. -index.recovery.mode=VALIDATE -# Force FULL recovery to stop when encountering errors -index.recovery.stopOnError=true -# Set the frequency with which the index tracking is triggered. -# For more information on index tracking in a cluster: -# http://wiki.alfresco.com/wiki/High_Availability_Configuration_V1.4_to_V2.1#Version_1.4.5.2C_2.1.1_and_later -# By default, this is effectively never, but can be modified as required. -# Examples: -# Once every five seconds: 0/5 * * * * ? -# Once every two seconds : 0/2 * * * * ? -# See http://quartz.sourceforge.net/javadoc/org/quartz/CronTrigger.html -index.tracking.cronExpression=* * * * * ? 2099 -index.tracking.adm.cronExpression=${index.tracking.cronExpression} -index.tracking.avm.cronExpression=${index.tracking.cronExpression} -# Other properties. -index.tracking.maxTxnDurationMinutes=60 -index.tracking.reindexLagMs=1000 -index.tracking.maxRecordSetSize=1000 - -# Change the failure behaviour of the configuration checker -system.bootstrap.config_check.strict=true - -# Server Single User Mode -# note: -# only allow named user (note: if blank or not set then will allow all users) -# assuming maxusers is not set to 0 -#server.singleuseronly.name=admin - -# Server Max Users - limit number of users with non-expired tickets -# note: -# -1 allows any number of users, assuming not in single-user mode -# 0 prevents further logins, including the ability to enter single-user mode -server.maxusers=-1 - -# -# Properties to limit resources spent on individual searches -# -# The maximum time spent pruning results -system.acl.maxPermissionCheckTimeMillis=10000 -# The maximum number of results to perform permission checks against -system.acl.maxPermissionChecks=1000 - -# #################### # -# Lucene configuration # -# #################### # -# -# Millisecond threshold for text transformations -# Slower transformers will force the text extraction to be asynchronous -# -lucene.maxAtomicTransformationTime=20 -# -# The maximum number of clauses that are allowed in a lucene query -# -lucene.query.maxClauses=10000 -# -# The size of the queue of nodes waiting for index -# Events are generated as nodes are changed, this is the maximum size of the queue used to coalesce event -# When this size is reached the lists of nodes will be indexed -# -# http://issues.alfresco.com/browse/AR-1280: Setting this high is the workaround as of 1.4.3. -# -lucene.indexer.batchSize=1000000 -# -# Lucene index min merge docs - the in memory size of the index -# -lucene.indexer.minMergeDocs=1000 -# -# When lucene index files are merged together - it will try to keep this number of segments/files in -# -lucene.indexer.mergeFactor=10 -# -# Roughly the maximum number of nodes indexed in one file/segment -# -lucene.indexer.maxMergeDocs=100000 -# -# The number of terms from a document that will be indexed -# -lucene.indexer.maxFieldLength=10000 - -lucene.write.lock.timeout=10000 -lucene.commit.lock.timeout=100000 -lucene.lock.poll.interval=100 - -# Database configuration -db.schema.update=true -db.driver=org.gjt.mm.mysql.Driver -db.name=alfresco -db.url=jdbc:mysql:///${db.name} -db.username=alfresco -db.password=alfresco -db.pool.initial=10 -db.pool.max=20 - -# Email configuration -mail.host= -mail.port=25 -mail.username=anonymous -mail.password= -# Set this value to UTF-8 or similar for encoding of email messages as required -mail.encoding=UTF-8 -# Set this value to 7bit or similar for Asian encoding of email headers as required -mail.header= -mail.from.default=alfresco@alfresco.org - -# System Configuration -system.store=system://system -system.descriptor.childname=sys:descriptor -system.descriptor.current.childname=sys:descriptor-current - -# User config -alfresco_user_store.store=user://alfrescoUserStore -alfresco_user_store.system_container.childname=sys:system -alfresco_user_store.user_container.childname=sys:people -alfresco_user_store.authorities_container.childname=sys:authorities - -# note: default admin username - should not be changed -alfresco_user_store.adminusername=admin - -# note: default guest username - should not be changed -alfresco_user_store.guestusername=guest - -# Spaces Archive Configuration -spaces.archive.store=archive://SpacesStore - -# Spaces Configuration -spaces.store=workspace://SpacesStore -spaces.company_home.childname=app:company_home -spaces.guest_home.childname=app:guest_home -spaces.dictionary.childname=app:dictionary -spaces.templates.childname=app:space_templates -spaces.templates.content.childname=app:content_templates -spaces.templates.email.childname=app:email_templates -spaces.templates.rss.childname=app:rss_templates -spaces.savedsearches.childname=app:saved_searches -spaces.scripts.childname=app:scripts -spaces.wcm.childname=app:wcm -spaces.wcm_content_forms.childname=app:wcm_forms -spaces.content_forms.childname=app:forms -spaces.user_homes.childname=app:user_homes -spaces.projects.childname=app:projects - -# Folders for storing people -system.system_container.childname=sys:system -system.people_container.childname=sys:people - -# Folders for storing workflow related info -system.workflow_container.childname=sys:workflow - -# Are user names case sensitive? -# ============================== -# -# NOTE: If you are using mysql you must have case sensitive collation -# -# You can do this when creating the alfresco database at the start -# CREATE DATABASE alfresco CHARACTER SET utf8 COLLATE utf8_bin; -# If you want to do this later this is a dump and load fix as it is done when the database, tables and columns are created. -# -# Must other databases are case sensitive by default. -# -user.name.caseSensitive=false - -# AVM Specific properties. -avm.remote.idlestream.timeout=30000 - -# ECM content usages/quotas -system.usages.enabled=true +# Directory configuration + +dir.root=./alf_data + +dir.contentstore=${dir.root}/contentstore +dir.contentstore.deleted=${dir.root}/contentstore.deleted + +dir.auditcontentstore=${dir.root}/audit.contentstore + +# The location for lucene index files +dir.indexes=${dir.root}/lucene-indexes + +# The location for lucene index locks +dir.indexes.lock=${dir.indexes}/locks + +# ######################################### # +# Index Recovery and Tracking Configuration # +# ######################################### # +# +# Recovery types are: +# NONE: Ignore +# VALIDATE: Checks that the first and last transaction for each store is represented in the indexes +# AUTO: Validates and auto-recovers if validation fails +# FULL: Full index rebuild, processing all transactions in order. The server is temporarily suspended. +index.recovery.mode=VALIDATE +# Force FULL recovery to stop when encountering errors +index.recovery.stopOnError=true +# Set the frequency with which the index tracking is triggered. +# For more information on index tracking in a cluster: +# http://wiki.alfresco.com/wiki/High_Availability_Configuration_V1.4_to_V2.1#Version_1.4.5.2C_2.1.1_and_later +# By default, this is effectively never, but can be modified as required. +# Examples: +# Once every five seconds: 0/5 * * * * ? +# Once every two seconds : 0/2 * * * * ? +# See http://quartz.sourceforge.net/javadoc/org/quartz/CronTrigger.html +index.tracking.cronExpression=* * * * * ? 2099 +index.tracking.adm.cronExpression=${index.tracking.cronExpression} +index.tracking.avm.cronExpression=${index.tracking.cronExpression} +# Other properties. +index.tracking.maxTxnDurationMinutes=60 +index.tracking.reindexLagMs=1000 +index.tracking.maxRecordSetSize=1000 + +# Change the failure behaviour of the configuration checker +system.bootstrap.config_check.strict=true + +# Server Single User Mode +# note: +# only allow named user (note: if blank or not set then will allow all users) +# assuming maxusers is not set to 0 +#server.singleuseronly.name=admin + +# Server Max Users - limit number of users with non-expired tickets +# note: +# -1 allows any number of users, assuming not in single-user mode +# 0 prevents further logins, including the ability to enter single-user mode +server.maxusers=-1 + +# +# Properties to limit resources spent on individual searches +# +# The maximum time spent pruning results +system.acl.maxPermissionCheckTimeMillis=10000 +# The maximum number of results to perform permission checks against +system.acl.maxPermissionChecks=1000 + +# #################### # +# Lucene configuration # +# #################### # +# +# Millisecond threshold for text transformations +# Slower transformers will force the text extraction to be asynchronous +# +lucene.maxAtomicTransformationTime=20 +# +# The maximum number of clauses that are allowed in a lucene query +# +lucene.query.maxClauses=10000 +# +# The size of the queue of nodes waiting for index +# Events are generated as nodes are changed, this is the maximum size of the queue used to coalesce event +# When this size is reached the lists of nodes will be indexed +# +# http://issues.alfresco.com/browse/AR-1280: Setting this high is the workaround as of 1.4.3. +# +lucene.indexer.batchSize=1000000 +# +# Lucene index min merge docs - the in memory size of the index +# +lucene.indexer.minMergeDocs=1000 +# +# When lucene index files are merged together - it will try to keep this number of segments/files in +# +lucene.indexer.mergeFactor=10 +# +# Roughly the maximum number of nodes indexed in one file/segment +# +lucene.indexer.maxMergeDocs=100000 +# +# The number of terms from a document that will be indexed +# +lucene.indexer.maxFieldLength=10000 + +lucene.write.lock.timeout=10000 +lucene.commit.lock.timeout=100000 +lucene.lock.poll.interval=100 + +# Database configuration +db.schema.update=true +db.driver=org.gjt.mm.mysql.Driver +db.name=alfresco +db.url=jdbc:mysql:///${db.name} +db.username=alfresco +db.password=alfresco +db.pool.initial=10 +db.pool.max=20 + +# Email configuration +mail.host= +mail.port=25 +mail.username=anonymous +mail.password= +# Set this value to UTF-8 or similar for encoding of email messages as required +mail.encoding=UTF-8 +# Set this value to 7bit or similar for Asian encoding of email headers as required +mail.header= +mail.from.default=alfresco@alfresco.org + +# System Configuration +system.store=system://system +system.descriptor.childname=sys:descriptor +system.descriptor.current.childname=sys:descriptor-current + +# User config +alfresco_user_store.store=user://alfrescoUserStore +alfresco_user_store.system_container.childname=sys:system +alfresco_user_store.user_container.childname=sys:people +alfresco_user_store.authorities_container.childname=sys:authorities + +# note: default admin username - should not be changed +alfresco_user_store.adminusername=admin + +# note: default guest username - should not be changed +alfresco_user_store.guestusername=guest + +# Spaces Archive Configuration +spaces.archive.store=archive://SpacesStore + +# Spaces Configuration +spaces.store=workspace://SpacesStore +spaces.company_home.childname=app:company_home +spaces.guest_home.childname=app:guest_home +spaces.dictionary.childname=app:dictionary +spaces.templates.childname=app:space_templates +spaces.templates.content.childname=app:content_templates +spaces.templates.email.childname=app:email_templates +spaces.templates.rss.childname=app:rss_templates +spaces.savedsearches.childname=app:saved_searches +spaces.scripts.childname=app:scripts +spaces.wcm.childname=app:wcm +spaces.wcm_content_forms.childname=app:wcm_forms +spaces.content_forms.childname=app:forms +spaces.user_homes.childname=app:user_homes +spaces.projects.childname=app:projects + +# Folders for storing people +system.system_container.childname=sys:system +system.people_container.childname=sys:people + +# Folders for storing workflow related info +system.workflow_container.childname=sys:workflow + +# Are user names case sensitive? +# ============================== +# +# NOTE: If you are using mysql you must have case sensitive collation +# +# You can do this when creating the alfresco database at the start +# CREATE DATABASE alfresco CHARACTER SET utf8 COLLATE utf8_bin; +# If you want to do this later this is a dump and load fix as it is done when the database, tables and columns are created. +# +# Must other databases are case sensitive by default. +# +user.name.caseSensitive=false + +# AVM Specific properties. +avm.remote.idlestream.timeout=30000 + +# ECM content usages/quotas +system.usages.enabled=true diff --git a/source/java/org/alfresco/repo/domain/schema/SchemaBootstrap.java b/source/java/org/alfresco/repo/domain/schema/SchemaBootstrap.java index 309878b0c8..2a13765bd2 100644 --- a/source/java/org/alfresco/repo/domain/schema/SchemaBootstrap.java +++ b/source/java/org/alfresco/repo/domain/schema/SchemaBootstrap.java @@ -42,7 +42,6 @@ import java.util.List; import java.util.Properties; import org.alfresco.error.AlfrescoRuntimeException; -import org.alfresco.i18n.I18NUtil; import org.alfresco.repo.admin.patch.impl.SchemaUpgradeScriptPatch; import org.alfresco.repo.content.filestore.FileContentWriter; import org.alfresco.service.ServiceRegistry; @@ -95,6 +94,7 @@ public class SchemaBootstrap extends AbstractLifecycleBean private static final String MSG_OPTIONAL_STATEMENT_FAILED = "schema.update.msg.optional_statement_failed"; private static final String WARN_DIALECT_UNSUPPORTED = "schema.update.warn.dialect_unsupported"; private static final String WARN_DIALECT_HSQL = "schema.update.warn.dialect_hsql"; + private static final String ERR_MULTIPLE_SCHEMAS = "schema.update.err.found_multiple"; private static final String ERR_PREVIOUS_FAILED_BOOTSTRAP = "schema.update.err.previous_failed"; private static final String ERR_STATEMENT_FAILED = "schema.update.err.statement_failed"; private static final String ERR_UPDATE_FAILED = "schema.update.err.update_failed"; @@ -230,31 +230,61 @@ public class SchemaBootstrap extends AbstractLifecycleBean } /** + * Count applied patches. This fails if multiple applied patch tables are found, + * which normally indicates that the schema view needs to be limited. + * + * @param cfg The Hibernate config + * @param connection a valid database connection * @return Returns the number of applied patches + * @throws NoSchemaException if the table of applied patches can't be found */ - private int countAppliedPatches(Connection connection) throws Exception + private int countAppliedPatches(Configuration cfg, Connection connection) throws Exception { + String defaultSchema = cfg.getProperty("hibernate.default_schema"); + if (defaultSchema != null && defaultSchema.length() == 0) + { + defaultSchema = null; + } + String defaultCatalog = cfg.getProperty("hibernate.default_catalog"); + if (defaultCatalog != null && defaultCatalog.length() == 0) + { + defaultCatalog = null; + } DatabaseMetaData dbMetadata = connection.getMetaData(); - ResultSet tableRs = dbMetadata.getTables(null, null, "%", null); + ResultSet tableRs = dbMetadata.getTables(defaultCatalog, defaultSchema, "%", null); boolean newPatchTable = false; boolean oldPatchTable = false; try { + boolean multipleSchemas = false; while (tableRs.next()) { String tableName = tableRs.getString("TABLE_NAME"); if (tableName.equalsIgnoreCase("applied_patch")) { + if (oldPatchTable || newPatchTable) + { + // Found earlier + multipleSchemas = true; + } oldPatchTable = true; - break; } else if (tableName.equalsIgnoreCase("alf_applied_patch")) { + if (oldPatchTable || newPatchTable) + { + // Found earlier + multipleSchemas = true; + } newPatchTable = true; - break; } } + // We go through all the tables so that multiple visible schemas are detected + if (multipleSchemas) + { + throw new AlfrescoRuntimeException(ERR_MULTIPLE_SCHEMAS); + } } finally { @@ -271,6 +301,11 @@ public class SchemaBootstrap extends AbstractLifecycleBean int count = rs.getInt(1); return count; } + catch (SQLException e) + { + // This should work at least and is probably an indication of the user viewing multiple schemas + throw new AlfrescoRuntimeException(ERR_MULTIPLE_SCHEMAS); + } finally { try { stmt.close(); } catch (Throwable e) {} @@ -424,7 +459,7 @@ public class SchemaBootstrap extends AbstractLifecycleBean boolean create = false; try { - countAppliedPatches(connection); + countAppliedPatches(cfg, connection); } catch (NoSchemaException e) { @@ -501,7 +536,7 @@ public class SchemaBootstrap extends AbstractLifecycleBean boolean apply) throws Exception { // first check if there have been any applied patches - int appliedPatchCount = countAppliedPatches(connection); + int appliedPatchCount = countAppliedPatches(cfg, connection); if (appliedPatchCount == 0) { // This is a new schema, so upgrade scripts are irrelevant @@ -747,7 +782,7 @@ public class SchemaBootstrap extends AbstractLifecycleBean } if (dialectClazz.equals(HSQLDialect.class)) { - logger.info(I18NUtil.getMessage(WARN_DIALECT_HSQL)); + LogUtil.info(logger, WARN_DIALECT_HSQL); } // Ensure that our static connection provider is used