From 8fa8216fefd0a571f2805437ef73b9e7dcea3e0f Mon Sep 17 00:00:00 2001 From: Derek Hulley Date: Mon, 2 Sep 2013 17:45:26 +0000 Subject: [PATCH] Merged DEV to HEAD: 54373: MNT-2641 : User can delete or move a working copy 54469: Compilation fix for MNT-2641 test 54470: Removed thousands of tabs 54523: Fixed ALF-19843: Integrity checking does not enforce mandatory aspects on aspects 54525: Pull IntegrityChecker properties into property file (ALF-19843) 54527: Fixed Eclipse warning about potentially unclosed file 54528: Prevent cm:workingcopy aspect from being removed directly (MNT-2641) 54529: Nail down behaviour around cm:workingcopy git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@54798 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- config/alfresco/node-services-context.xml | 32 +- config/alfresco/repository.properties | 2147 +++++++++-------- .../patch/impl/CopiedFromAspectPatch.java | 1 + .../alfresco/repo/coci/WorkingCopyAspect.java | 18 +- .../node/integrity/AspectsIntegrityEvent.java | 31 +- .../coci/CheckOutCheckInServiceImplTest.java | 912 +++++-- .../repo/node/integrity/IntegrityTest.java | 62 +- .../node/integrity/IntegrityTest_model.xml | 7 + 8 files changed, 1824 insertions(+), 1386 deletions(-) diff --git a/config/alfresco/node-services-context.xml b/config/alfresco/node-services-context.xml index 9013497a6f..0ed7523bdb 100644 --- a/config/alfresco/node-services-context.xml +++ b/config/alfresco/node-services-context.xml @@ -162,30 +162,14 @@ - - - - - - - - - - - - - - true - - - false - - - true - - - 5 - + + + + + + + + ${version.store.version2Store} diff --git a/config/alfresco/repository.properties b/config/alfresco/repository.properties index e7145a042d..c5c92cf208 100644 --- a/config/alfresco/repository.properties +++ b/config/alfresco/repository.properties @@ -1,1067 +1,1080 @@ -# Repository configuration - -repository.name=Main Repository - -# Directory configuration - -dir.root=./alf_data - -dir.contentstore=${dir.root}/contentstore -dir.contentstore.deleted=${dir.root}/contentstore.deleted - -# The location of cached content -dir.cachedcontent=${dir.root}/cachedcontent - -dir.auditcontentstore=${dir.root}/audit.contentstore - -# The value for the maximum permitted size in bytes of all content. -# No value (or a negative long) will be taken to mean that no limit should be applied. -# See content-services-context.xml -system.content.maximumFileSizeLimit= - -# The location for lucene index files -dir.indexes=${dir.root}/lucene-indexes - -# The location for index backups -dir.indexes.backup=${dir.root}/backup-lucene-indexes - -# The location for lucene index locks -dir.indexes.lock=${dir.indexes}/locks - -#Directory to find external license -dir.license.external=. -# Spring resource location of external license files -location.license.external=file://${dir.license.external}/*.lic -# Spring resource location of embedded license files -location.license.embedded=/WEB-INF/alfresco/license/*.lic -# Spring resource location of license files on shared classpath -location.license.shared=classpath*:/alfresco/extension/license/*.lic - -# WebDAV initialization properties -system.webdav.servlet.enabled=true -system.webdav.url.path.prefix= -system.webdav.storeName=${protocols.storeName} -system.webdav.rootPath=${protocols.rootPath} -# File name patterns that trigger rename shuffle detection -# pattern is used by move - tested against full path after it has been lower cased. -system.webdav.renameShufflePattern=(.*/\\..*)|(.*[a-f0-9]{8}+$)|(.*\\.tmp$)|(.*\\.wbk$)|(.*\\.bak$)|(.*\\~$)|(.*backup.*\\.do[ct]{1}[x]?[m]?$) -system.webdav.activities.enabled=false - - -# Is the JBPM Deploy Process Servlet enabled? -# Default is false. Should not be enabled in production environments as the -# servlet allows unauthenticated deployment of new workflows. -system.workflow.deployservlet.enabled=false - -# Sets the location for the JBPM Configuration File -system.workflow.jbpm.config.location=classpath:org/alfresco/repo/workflow/jbpm/jbpm.cfg.xml - -# Determines if JBPM workflow definitions are shown. -# Default is false. This controls the visibility of JBPM -# workflow definitions from the getDefinitions and -# getAllDefinitions WorkflowService API but still allows -# any in-flight JBPM workflows to be completed. -system.workflow.engine.jbpm.definitions.visible=false - -#Determines if Activiti definitions are visible -system.workflow.engine.activiti.definitions.visible=true - -# Determines if the JBPM engine is enabled -system.workflow.engine.jbpm.enabled=true - -# Determines if the Activiti engine is enabled -system.workflow.engine.activiti.enabled=true -system.workflow.engine.activiti.idblocksize=100 - -# Determines if the workflows that are deployed to the activiti engine should -# be deployed in the tenant-context of the thread IF the tenant-service is enabled -# If set to false, all workflows deployed will be shared among tenants. Recommended -# setting is true unless there is a good reason to not allow deploy tenant-specific -# worklfows when a MT-environment is set up. -system.workflow.deployWorkflowsInTenant=true - -# The maximum number of groups to check for pooled tasks. For performance -# reasons, this is limited to 100 by default. -system.workflow.maxAuthoritiesForPooledTasks=100 - -# The maximum number of pooled tasks to return in a query. It may be necessary -# to limit this depending on UI limitations. -system.workflow.maxPooledTasks=-1 - -# The maximum number of reviewers for "Group Review and Approve" workflow. -# Use '0' for unlimited. -system.workflow.maxGroupReviewers=0 - -index.subsystem.name=lucene - -# ######################################### # -# 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 -# FULL recovery continues when encountering errors -index.recovery.stopOnError=false -index.recovery.maximumPoolSize=5 -# 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: -# Never: * * * * * ? 2099 -# Once every five seconds: 0/5 * * * * ? -# Once every two seconds : 0/2 * * * * ? -# See http://www.quartz-scheduler.org/docs/tutorials/crontrigger.html -index.tracking.cronExpression=0/5 * * * * ? -index.tracking.adm.cronExpression=${index.tracking.cronExpression} -index.tracking.avm.cronExpression=${index.tracking.cronExpression} -# Other properties. -index.tracking.maxTxnDurationMinutes=10 -index.tracking.reindexLagMs=1000 -index.tracking.maxRecordSetSize=1000 -index.tracking.maxTransactionsPerLuceneCommit=100 -index.tracking.disableInTransactionIndexing=false -# Index tracking information of a certain age is cleaned out by a scheduled job. -# Any clustered system that has been offline for longer than this period will need to be seeded -# with a more recent backup of the Lucene indexes or the indexes will have to be fully rebuilt. -# Use -1 to disable purging. This can be switched on at any stage. -index.tracking.minRecordPurgeAgeDays=30 -# Unused transactions will be purged in chunks determined by commit time boundaries. 'index.tracking.purgeSize' specifies the size -# of the chunk (in ms). Default is a couple of hours. -index.tracking.purgeSize=7200000 - -# Reindexing of missing content is by default 'never' carried out. -# The cron expression below can be changed to control the timing of this reindexing. -# Users of Enterprise Alfresco can configure this cron expression via JMX without a server restart. -# Note that if alfresco.cluster.enabled is false in Enterprise, then reindexing will not occur. -index.reindexMissingContent.cronExpression=* * * * * ? 2099 - -# Change the failure behaviour of the configuration checker -system.bootstrap.config_check.strict=true - - -# -# How long should shutdown wait to complete normally before -# taking stronger action and calling System.exit() -# in ms, 10,000 is 10 seconds -# -shutdown.backstop.timeout=10000 -shutdown.backstop.enabled=false - -# 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 - -# The Cron expression controlling the frequency with which the OpenOffice connection is tested -openOffice.test.cronExpression=0 * * * * ? - -# -# Disable all shared caches (mutable and immutable) -# These properties are used for diagnostic purposes -system.cache.disableMutableSharedCaches=false -system.cache.disableImmutableSharedCaches=false - -# The maximum capacity of the parent assocs cache (the number of nodes whose parents can be cached) -system.cache.parentAssocs.maxSize=130000 - -# The average number of parents expected per cache entry. This parameter is multiplied by the above -# value to compute a limit on the total number of cached parents, which will be proportional to the -# cache's memory usage. The cache will be pruned when this limit is exceeded to avoid excessive -# memory usage. -system.cache.parentAssocs.limitFactor=8 - -# -# Properties to limit resources spent on individual searches -# -# The maximum time spent pruning results -system.acl.maxPermissionCheckTimeMillis=10000 -# The maximum number of search results to perform permission checks against -system.acl.maxPermissionChecks=1000 - -# The maximum number of filefolder list results -system.filefolderservice.defaultListMaxResults=5000 - -# Properties to control read permission evaluation for acegi -system.readpermissions.optimise=true -system.readpermissions.bulkfetchsize=1000 - -# -# Manually control how the system handles maximum string lengths. -# Any zero or negative value is ignored. -# Only change this after consulting support or reading the appropriate Javadocs for -# org.alfresco.repo.domain.schema.SchemaBootstrap for V2.1.2 -system.maximumStringLength=-1 - -# -# Limit hibernate session size by trying to amalgamate events for the L2 session invalidation -# - hibernate works as is up to this size -# - after the limit is hit events that can be grouped invalidate the L2 cache by type and not instance -# events may not group if there are post action listener registered (this is not the case with the default distribution) -system.hibernateMaxExecutions=20000 - -# -# Determine if modification timestamp propagation from child to parent nodes is respected or not. -# Even if 'true', the functionality is only supported for child associations that declare the -# 'propagateTimestamps' element in the dictionary definition. -system.enableTimestampPropagation=true - -# -# Decide if content should be removed from the system immediately after being orphaned. -# Do not change this unless you have examined the impact it has on your backup procedures. -system.content.eagerOrphanCleanup=false -# The number of days to keep orphaned content in the content stores. -# This has no effect on the 'deleted' content stores, which are not automatically emptied. -system.content.orphanProtectDays=14 -# The action to take when a store or stores fails to delete orphaned content -# IGNORE: Just log a warning. The binary remains and the record is expunged -# KEEP_URL: Log a warning and create a URL entry with orphan time 0. It won't be processed or removed. -system.content.deletionFailureAction=IGNORE -# The CRON expression to trigger the deletion of resources associated with orphaned content. -system.content.orphanCleanup.cronExpression=0 0 4 * * ? -# The CRON expression to trigger content URL conversion. This process is not intesive and can -# be triggered on a live system. Similarly, it can be triggered using JMX on a dedicated machine. -system.content.contentUrlConverter.cronExpression=* * * * * ? 2099 -system.content.contentUrlConverter.threadCount=2 -system.content.contentUrlConverter.batchSize=500 -system.content.contentUrlConverter.runAsScheduledJob=false - -# #################### # -# Lucene configuration # -# #################### # -# -# Millisecond threshold for text transformations -# Slower transformers will force the text extraction to be asynchronous -# -lucene.maxAtomicTransformationTime=100 -# -# 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 -fts.indexer.batchSize=1000 -# -# Index cache sizes -# -lucene.indexer.cacheEnabled=true -lucene.indexer.maxDocIdCacheSize=100000 -lucene.indexer.maxDocumentCacheSize=100 -lucene.indexer.maxIsCategoryCacheSize=-1 -lucene.indexer.maxLinkAspectCacheSize=10000 -lucene.indexer.maxParentCacheSize=100000 -lucene.indexer.maxPathCacheSize=100000 -lucene.indexer.maxTypeCacheSize=10000 -# -# Properties for merge (not this does not affect the final index segment which will be optimised) -# Max merge docs only applies to the merge process not the resulting index which will be optimised. -# -lucene.indexer.mergerMaxMergeDocs=1000000 -lucene.indexer.mergerMergeFactor=5 -lucene.indexer.mergerMaxBufferedDocs=-1 -lucene.indexer.mergerRamBufferSizeMb=16 -# -# Properties for delta indexes (not this does not affect the final index segment which will be optimised) -# Max merge docs only applies to the index building process not the resulting index which will be optimised. -# -lucene.indexer.writerMaxMergeDocs=1000000 -lucene.indexer.writerMergeFactor=5 -lucene.indexer.writerMaxBufferedDocs=-1 -lucene.indexer.writerRamBufferSizeMb=16 -# -# Target number of indexes and deltas in the overall index and what index size to merge in memory -# -lucene.indexer.mergerTargetIndexCount=8 -lucene.indexer.mergerTargetOverlayCount=5 -lucene.indexer.mergerTargetOverlaysBlockingFactor=2 -lucene.indexer.maxDocsForInMemoryMerge=60000 -lucene.indexer.maxRamInMbForInMemoryMerge=16 -lucene.indexer.maxDocsForInMemoryIndex=60000 -lucene.indexer.maxRamInMbForInMemoryIndex=16 -# -# Other lucene properties -# -lucene.indexer.termIndexInterval=128 -lucene.indexer.useNioMemoryMapping=true -# over-ride to false for pre 3.0 behaviour -lucene.indexer.postSortDateTime=true -lucene.indexer.defaultMLIndexAnalysisMode=EXACT_LANGUAGE_AND_ALL -lucene.indexer.defaultMLSearchAnalysisMode=EXACT_LANGUAGE_AND_ALL -# -# The number of terms from a document that will be indexed -# -lucene.indexer.maxFieldLength=10000 - -# Should we use a 'fair' locking policy, giving queue-like access behaviour to -# the indexes and avoiding starvation of waiting writers? Set to false on old -# JVMs where this appears to cause deadlock -lucene.indexer.fairLocking=true - -# -# Index locks (mostly deprecated and will be tidied up with the next lucene upgrade) -# -lucene.write.lock.timeout=10000 -lucene.commit.lock.timeout=100000 -lucene.lock.poll.interval=100 - -lucene.indexer.useInMemorySort=true -lucene.indexer.maxRawResultSetSizeForInMemorySort=1000 -lucene.indexer.contentIndexingEnabled=true - -index.backup.cronExpression=0 0 3 * * ? - -lucene.defaultAnalyserResourceBundleName=alfresco/model/dataTypeAnalyzers - - -# When transforming archive files (.zip etc) into text representations (such as -# for full text indexing), should the files within the archive be processed too? -# If enabled, transformation takes longer, but searches of the files find more. -transformer.Archive.includeContents=false - -# Database configuration -db.schema.stopAfterSchemaBootstrap=false -db.schema.update=true -db.schema.update.lockRetryCount=24 -db.schema.update.lockRetryWaitSeconds=5 -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=40 -db.txn.isolation=-1 -db.pool.statements.enable=true -db.pool.statements.max=40 -db.pool.min=0 -db.pool.idle=-1 -db.pool.wait.max=-1 - -db.pool.validate.query= -db.pool.evict.interval=-1 -db.pool.evict.idle.min=1800000 -# -# note: for 'db.pool.evict.num.tests' see http://commons.apache.org/dbcp/configuration.html (numTestsPerEvictionRun) -# and also following extract from "org.apache.commons.pool.impl.GenericKeyedObjectPool" (1.5.5) -# -# * The number of objects to examine during each run of the idle object evictor thread (if any). -# * When a negative value is supplied, ceil({@link #getNumIdle})/abs({@link #getNumTestsPerEvictionRun}) -# * tests will be run. I.e., when the value is -n, roughly one nth of the -# * idle objects will be tested per run. -# -db.pool.evict.num.tests=-1 - -db.pool.evict.validate=false -db.pool.validate.borrow=true -db.pool.validate.return=false - -db.pool.abandoned.detect=false -db.pool.abandoned.time=300 -# -# db.pool.abandoned.log=true (logAbandoned) adds overhead (http://commons.apache.org/dbcp/configuration.html) -# and also requires db.pool.abandoned.detect=true (removeAbandoned) -# -db.pool.abandoned.log=false - - -# Audit configuration -audit.enabled=true -audit.tagging.enabled=true -audit.alfresco-access.enabled=false -audit.alfresco-access.sub-actions.enabled=false -audit.cmischangelog.enabled=false -audit.dod5015.enabled=false -# Setting this flag to true will force startup failure when invalid audit configurations are detected -audit.config.strict=false -# Audit map filter for AccessAuditor - restricts recorded events to user driven events -audit.filter.alfresco-access.default.enabled=true -audit.filter.alfresco-access.transaction.user=~System;~null;.* -audit.filter.alfresco-access.transaction.type=cm:folder;cm:content;st:site -audit.filter.alfresco-access.transaction.path=~/sys:archivedItem;~/ver:;.* - - -# 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 - -# note: default admin username - should not be changed after installation -alfresco_user_store.adminusername=admin - -# Initial password - editing this will not have any effect once the repository is installed -alfresco_user_store.adminpassword=209c6174da490caeb422f3fa5a7ae634 -alfresco_user_store.adminsalt=ad3b938f-c1ad-4f2b-828b-6f3afd30ffdd -alfresco_user_store.adminpassword2=f378d5d7b947d5c26f478e21819e7ec3a6668c8149b050d086c64447bc40173b - -# note: default guest username - should not be changed after installation -alfresco_user_store.guestusername=guest - -# Used to move home folders to a new location -home_folder_provider_synchronizer.enabled=false -home_folder_provider_synchronizer.override_provider= -home_folder_provider_synchronizer.keep_empty_parents=false - -# 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.imap_attachments.childname=cm:Imap Attachments -spaces.imap_home.childname=cm:Imap Home -spaces.imapConfig.childname=app:imap_configs -spaces.imap_templates.childname=app:imap_templates -spaces.scheduled_actions.childname=cm:Scheduled Actions -spaces.emailActions.childname=app:email_actions -spaces.searchAction.childname=cm:search -spaces.templates.content.childname=app:content_templates -spaces.templates.email.childname=app:email_templates -spaces.templates.email.invite1.childname=app:invite_email_templates -spaces.templates.email.notify.childname=app:notify_email_templates -spaces.templates.email.following.childname=app:following -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.user_homes.regex.key=userName -spaces.user_homes.regex.pattern= -spaces.user_homes.regex.group_order= -spaces.sites.childname=st:sites -spaces.templates.email.invite.childname=cm:invite -spaces.templates.email.activities.childname=cm:activities -spaces.rendition.rendering_actions.childname=app:rendering_actions -spaces.replication.replication_actions.childname=app:replication_actions -spaces.wcm_deployed.childname=cm:wcm_deployed -spaces.transfers.childname=app:transfers -spaces.transfer_groups.childname=app:transfer_groups -spaces.transfer_temp.childname=app:temp -spaces.inbound_transfer_records.childname=app:inbound_transfer_records -spaces.webscripts.childname=cm:webscripts -spaces.extension_webscripts.childname=cm:extensionwebscripts -spaces.models.childname=app:models -spaces.workflow.definitions.childname=app:workflow_defs -spaces.publishing.root.childname=app:publishing_root -spaces.templates.email.workflowemailnotification.childname=cm:workflownotification -spaces.nodetemplates.childname=app:node_templates -spaces.shared.childname=app:shared - -# ADM VersionStore Configuration -version.store.enableAutoVersioning=true -version.store.deprecated.lightWeightVersionStore=workspace://lightWeightVersionStore -version.store.version2Store=workspace://version2Store - -version.store.migrateVersionStore.threadCount=3 -version.store.migrateVersionStore.batchSize=1 - -version.store.migrateCleanupJob.threadCount=3 -version.store.migrateCleanupJob.batchSize=1 - - -# WARNING: For non-production testing only !!! Do not change (to avoid version store issues, including possible mismatch). Should be false since lightWeightVersionStore is deprecated. -version.store.onlyUseDeprecatedV1=false - -# The CRON expression to trigger migration of the version store from V1 (2.x) to V2 (3.x) -# By default, this is effectively 'never' but can be modified as required. -# Examples: -# Never: * * * * * ? 2099 -# Once every thirty minutes: 0 0/30 * * * ? -# See http://www.quartz-scheduler.org/docs/tutorials/crontrigger.html -version.store.migrateVersionStore.cronExpression=* * * * * ? 2099 -# Limit number of version histories to migrate per job cycle, where -1 = unlimited. Note: if limit > 0 then need to schedule job to run regularly in order to complete the migration. -version.store.migrateVersionStore.limitPerJobCycle=-1 -version.store.migrateVersionStore.runAsScheduledJob=false - -# Optional Comparator class name to sort versions. -# Set to: org.alfresco.repo.version.common.VersionLabelComparator -# if upgrading from a version that used unordered sequences in a cluster. -version.store.versionComparatorClass= - -# Folders for storing people -system.system_container.childname=sys:system -system.people_container.childname=sys:people -system.authorities_container.childname=sys:authorities -system.zones_container.childname=sys:zones - -# Folders for storing workflow related info -system.workflow_container.childname=sys:workflow - -# Folder for storing shared remote credentials -system.remote_credentials_container.childname=sys:remote_credentials - -# Folder for storing syncset definitions -system.syncset_definition_container.childname=sys:syncset_definitions - -# Folder for storing download archives -system.downloads_container.childname=sys:downloads - -# Folder for storing IdP's certificate definitions -system.certificate_container.childname=sys:samlcertificate - -# Are user names case sensitive? -user.name.caseSensitive=false -domain.name.caseSensitive=false -domain.separator= - -# AVM Specific properties. -avm.remote.idlestream.timeout=30000 - -#Format caption extracted from the XML Schema. -xforms.formatCaption=true - -# ECM content usages/quotas -system.usages.enabled=false -system.usages.clearBatchSize=0 -system.usages.updateBatchSize=50 - -# Repository endpoint - used by Activity Service -repo.remote.endpoint=/service - -# Some authentication mechanisms may need to create people -# in the repository on demand. This enables that feature. -# If disabled an error will be generated for missing -# people. If enabled then a person will be created and -# persisted. -create.missing.people=${server.transaction.allow-writes} - -# Create home folders (unless disabled, see next property) as people are created (true) or create them lazily (false) -home.folder.creation.eager=true -# Disable home folder creation - if true then home folders are not created (neither eagerly nor lazily) -home.folder.creation.disabled=false - -# Should we consider zero byte content to be the same as no content when firing -# content update policies? Prevents 'premature' firing of inbound content rules -# for some clients such as Mac OS X Finder -policy.content.update.ignoreEmpty=true - -# The well known RMI registry port and external host name published in the stubs -# is defined in the alfresco-shared.properties file -# -# alfresco.rmi.services.port=50500 - -# Default value of alfresco.rmi.services.host is 0.0.0.0 which means 'listen on all adapters'. -# This allows connections to JMX both remotely and locally. -# -alfresco.rmi.services.host=0.0.0.0 - -# If the RMI address is in-use, how many retries should be done before aborting -# Default value of alfresco.rmi.services.retries is 0 which means 'Don't retry if the address is in-use' -alfresco.rmi.services.retries=4 - -# RMI service ports for the individual services. -# These eight services are available remotely. -# -# Assign individual ports for each service for best performance -# or run several services on the same port, you can even run everything on 50500 if -# running through a firewall. -# -# Specify 0 to use a random unused port. -# -avm.rmi.service.port=50501 -avmsync.rmi.service.port=50502 -authentication.rmi.service.port=50504 -repo.rmi.service.port=50505 -action.rmi.service.port=50506 -deployment.rmi.service.port=50507 -monitor.rmi.service.port=50508 - -# -# enable or disable individual RMI services -# -avm.rmi.service.enabled=true -avmsync.rmi.service.enabled=true -authentication.rmi.service.enabled=true -repo.rmi.service.enabled=true -action.rmi.service.enabled=true -deployment.rmi.service.enabled=true -monitor.rmi.service.enabled=true - - -# Should the Mbean server bind to an existing server. Set to true for most application servers. -# false for WebSphere clusters. -mbean.server.locateExistingServerIfPossible=true - -# External executable locations -ooo.exe=soffice -ooo.user=${dir.root}/oouser -img.root=./ImageMagick -img.dyn=${img.root}/lib -img.exe=${img.root}/bin/convert -swf.exe=./bin/pdf2swf -swf.languagedir=. - -# Thumbnail Service -system.thumbnail.generate=true - -# Default thumbnail limits -# When creating thumbnails, only use the first pageLimit pages -system.thumbnail.definition.default.timeoutMs=-1 -system.thumbnail.definition.default.readLimitTimeMs=-1 -system.thumbnail.definition.default.maxSourceSizeKBytes=-1 -system.thumbnail.definition.default.readLimitKBytes=-1 -system.thumbnail.definition.default.pageLimit=1 -system.thumbnail.definition.default.maxPages=-1 - -# Max mimetype sizes to create thumbnail icons -system.thumbnail.mimetype.maxSourceSizeKBytes.pdf=-1 -system.thumbnail.mimetype.maxSourceSizeKBytes.txt=-1 -system.thumbnail.mimetype.maxSourceSizeKBytes.docx=-1 -system.thumbnail.mimetype.maxSourceSizeKBytes.xlsx=-1 -system.thumbnail.mimetype.maxSourceSizeKBytes.pptx=-1 -system.thumbnail.mimetype.maxSourceSizeKBytes.odt=-1 -system.thumbnail.mimetype.maxSourceSizeKBytes.ods=-1 -system.thumbnail.mimetype.maxSourceSizeKBytes.odp=-1 - -# Configuration for handling of failing thumbnails. -# See NodeEligibleForRethumbnailingEvaluator's javadoc for details. -# -# Retry periods limit the frequency with which the repository will attempt to create Share thumbnails -# for content nodes which have previously failed in their thumbnail attempts. -# These periods are in seconds. -# -# 604800s = 60s * 60m * 24h * 7d = 1 week -system.thumbnail.retryPeriod=60 -system.thumbnail.retryCount=2 -system.thumbnail.quietPeriod=604800 -system.thumbnail.quietPeriodRetriesEnabled=true -system.thumbnail.redeployStaticDefsOnStartup=true - -# The default timeout for metadata mapping extracters -content.metadataExtracter.default.timeoutMs=20000 - -# Property to enable upgrade from 2.1-A -V2.1-A.fixes.to.schema=0 -#V2.1-A.fixes.to.schema=82 - -# The default authentication chain -authentication.chain=alfrescoNtlm1:alfrescoNtlm - -# Do authentication tickets expire or live for ever? -authentication.ticket.ticketsExpire=true - -# If ticketsEpire is true then how they should expire? -# Valid values are: AFTER_INACTIVITY, AFTER_FIXED_TIME, DO_NOT_EXPIRE -# The default is AFTER_FIXED_TIME -authentication.ticket.expiryMode=AFTER_INACTIVITY - -# If authentication.ticket.ticketsExpire is true and -# authentication.ticket.expiryMode is AFTER_FIXED_TIME or AFTER_INACTIVITY, -# this controls the minimum period for which tickets are valid. -# The default is PT1H for one hour. -authentication.ticket.validDuration=PT1H - -# Use one ticket for all user sessions -# For the pre 4.2 behaviour of one ticket per session set this to false. -authentication.ticket.useSingleTicketPerUser=true - -# If kerberos.authentication.cifs.enableTicketCracking is false, -# the Kerberos ticket cracking code is switched off. -# This code was required to get mutual authentication with a Windows AD client working in earlier versions of Java (version 5 or earlier). -# The latest JVMs don't require this code as they have better support for SPNEGO/GSS authentication. -# Please, see MNT-7392 for details. -kerberos.authentication.cifs.enableTicketCracking=false - -# Default NFS user mappings (empty). Note these users will be able to -# authenticate through NFS without password so ensure NFS port is secure before -# enabling and adding mappings -nfs.user.mappings= -nfs.user.mappings.default.uid=0 -nfs.user.mappings.default.gid=0 - -#Example NFS user mappings -#nfs.user.mappings=admin,user1 -#nfs.user.mappings.value.admin.uid=0 -#nfs.user.mappings.value.admin.gid=0 -#nfs.user.mappings.value.user1.uid=500 -#nfs.user.mappings.value.user1.gid=500 - -# Default root path for protocols -protocols.storeName=${spaces.store} -protocols.rootPath=/${spaces.company_home.childname} - -# OpenCMIS -opencmis.connector.default.store=${spaces.store} -opencmis.connector.default.rootPath=/${spaces.company_home.childname} -opencmis.connector.default.typesDefaultMaxItems=500 -opencmis.connector.default.typesDefaultDepth=-1 -opencmis.connector.default.objectsDefaultMaxItems=10000 -opencmis.connector.default.objectsDefaultDepth=100 -opencmis.connector.default.openHttpSession=false -opencmis.activities.enabled=true - -# IMAP -imap.server.enabled=false -imap.server.port=143 -imap.server.attachments.extraction.enabled=true - -# Default IMAP mount points -imap.config.home.store=${spaces.store} -imap.config.home.rootPath=/${spaces.company_home.childname} -imap.config.home.folderPath=${spaces.imap_home.childname} -imap.config.server.mountPoints=AlfrescoIMAP -imap.config.server.mountPoints.default.mountPointName=IMAP -imap.config.server.mountPoints.default.modeName=ARCHIVE -imap.config.server.mountPoints.default.store=${spaces.store} -imap.config.server.mountPoints.default.rootPath=${protocols.rootPath} -imap.config.server.mountPoints.value.AlfrescoIMAP.mountPointName=Alfresco IMAP -imap.config.server.mountPoints.value.AlfrescoIMAP.modeName=MIXED - -#Imap extraction settings -#imap.attachments.mode: -# SEPARATE -- All attachments for each email will be extracted to separate folder. -# COMMON -- All attachments for all emails will be extracted to one folder. -# SAME -- Attachments will be extracted to the same folder where email lies. -imap.server.attachments.extraction.enabled=true -imap.attachments.mode=SEPARATE -imap.attachments.folder.store=${spaces.store} -imap.attachments.folder.rootPath=/${spaces.company_home.childname} -imap.attachments.folder.folderPath=${spaces.imap_attachments.childname} - -# Activities Feed - refer to subsystem - -# Feed max ID range to limit maximum number of entries -activities.feed.max.idRange=1000000 -# Feed max size (number of entries) -activities.feed.max.size=100 -# Feed max age (eg. 44640 mins => 31 days) -activities.feed.max.ageMins=44640 - -activities.feed.generator.jsonFormatOnly=true -activities.feed.fetchBatchSize=150 -activities.feedNotifier.batchSize=200 -activities.feedNotifier.numThreads=2 - -# Subsystem unit test values. Will not have any effect on production servers -subsystems.test.beanProp.default.longProperty=123456789123456789 -subsystems.test.beanProp.default.anotherStringProperty=Global Default -subsystems.test.beanProp=inst1,inst2,inst3 -subsystems.test.beanProp.value.inst2.boolProperty=true -subsystems.test.beanProp.value.inst3.anotherStringProperty=Global Instance Default -subsystems.test.simpleProp2=true -subsystems.test.simpleProp3=Global Default3 - -# Default Async Action Thread Pool -default.async.action.threadPriority=1 -default.async.action.corePoolSize=8 -default.async.action.maximumPoolSize=20 - -# Deployment Service -deployment.service.numberOfSendingThreads=5 -deployment.service.corePoolSize=2 -deployment.service.maximumPoolSize=3 -deployment.service.threadPriority=5 -# How long to wait in mS before refreshing a target lock - detects shutdown servers -deployment.service.targetLockRefreshTime=60000 -# How long to wait in mS from the last communication before deciding that deployment has failed, possibly -# the destination is no longer available? -deployment.service.targetLockTimeout=3600000 - -#Invitation Service -# Should send emails as part of invitation process. -notification.email.siteinvite=true - -# Transfer Service -transferservice.receiver.enabled=true -transferservice.receiver.stagingDir=${java.io.tmpdir}/alfresco-transfer-staging -# -# How long to wait in mS before refreshing a transfer lock - detects shutdown servers -# Default 1 minute. -transferservice.receiver.lockRefreshTime=60000 -# -# How many times to attempt retry the transfer lock -transferservice.receiver.lockRetryCount=3 -# How long to wait, in mS, before retrying the transfer lock -transferservice.receiver.lockRetryWait=100 -# -# How long to wait, in mS, since the last contact with from the client before -# timing out a transfer. Needs to be long enough to cope with network delays and "thinking -# time" for both source and destination. Default 5 minutes. -transferservice.receiver.lockTimeOut=300000 - -# Max time allowed for WCM folder rename operation issued by external clients (CIFS, FTP) -wcm.rename.max.time.milliseconds=2000 - -; DM Receiever Properties -; -; The name of the DM Receiver target - you deploy to this target name -deployment.dmr.name=alfresco - -; consolidate staging, author and workflow sandboxes to one -deployment.dmr.consolidate=true - -; The name of the Alfresco receiver targer -deployment.avm.name=avm - -;Where should the root of the web project be stored, by default /www/avm_webapps -deployment.avm.rootPath=/www/avm_webapps - -; Pattern for live stores deployment by the alfresco receiver -deployment.avm.storeNamePattern=%storeName%-live - -; Built in deployment receiver properties for the default -; filesystem receiver - -; filesystem receiver configuration -deployment.filesystem.rootdir=./wcm -deployment.filesystem.datadir=${deployment.filesystem.rootdir}/depdata -deployment.filesystem.logdir=${deployment.filesystem.rootdir}/deplog -deployment.filesystem.metadatadir=${deployment.filesystem.rootdir}/depmetadata - -deployment.filesystem.autofix=true -deployment.filesystem.errorOnOverwrite=false - -; default filesystem target configuration -deployment.filesystem.default.rootdir=./www -deployment.filesystem.default.name=filesystem -deployment.filesystem.default.metadatadir=${deployment.filesystem.metadatadir}/default - -# OrphanReaper -orphanReaper.lockRefreshTime=60000 -orphanReaper.lockTimeOut=3600000 - - -# security -security.anyDenyDenies=true - -# -# Encryption properties -# -# default keystores location -dir.keystore=classpath:alfresco/keystore - -# general encryption parameters -encryption.keySpec.class=org.alfresco.encryption.DESEDEKeyGenerator -encryption.keyAlgorithm=DESede -encryption.cipherAlgorithm=DESede/CBC/PKCS5Padding - -# secret key keystore configuration -encryption.keystore.location=${dir.keystore}/keystore -encryption.keystore.keyMetaData.location=${dir.keystore}/keystore-passwords.properties -encryption.keystore.provider= -encryption.keystore.type=JCEKS - -# backup secret key keystore configuration -encryption.keystore.backup.location=${dir.keystore}/backup-keystore -encryption.keystore.backup.keyMetaData.location=${dir.keystore}/backup-keystore-passwords.properties -encryption.keystore.backup.provider= -encryption.keystore.backup.type=JCEKS - -# Should encryptable properties be re-encrypted with new encryption keys on botstrap? -encryption.bootstrap.reencrypt=false - -# mac/md5 encryption -encryption.mac.messageTimeout=30000 -encryption.mac.algorithm=HmacSHA1 - -# ssl encryption -encryption.ssl.keystore.location=${dir.keystore}/ssl.keystore -encryption.ssl.keystore.provider= -encryption.ssl.keystore.type=JCEKS -encryption.ssl.keystore.keyMetaData.location=${dir.keystore}/ssl-keystore-passwords.properties -encryption.ssl.truststore.location=${dir.keystore}/ssl.truststore -encryption.ssl.truststore.provider= -encryption.ssl.truststore.type=JCEKS -encryption.ssl.truststore.keyMetaData.location=${dir.keystore}/ssl-truststore-passwords.properties - -# Re-encryptor properties -encryption.reencryptor.chunkSize=100 -encryption.reencryptor.numThreads=2 - -# SOLR connection details (e.g. for JMX) -solr.host=localhost -solr.port=8080 -solr.port.ssl=8443 -solr.solrUser=solr -solr.solrPassword=solr -# none, https -solr.secureComms=https -solr.cmis.alternativeDictionary=DEFAULT_DICTIONARY - -solr.max.total.connections=40 -solr.max.host.connections=40 - -# Solr connection timeouts -# solr connect timeout in ms -solr.solrConnectTimeout=5000 - -# cron expression defining how often the Solr Admin client (used by JMX) pings Solr if it goes away -solr.solrPingCronExpression=0 0/5 * * * ? * - - -#Default SOLR store mappings mappings -solr.store.mappings=solrMappingAlfresco,solrMappingArchive -solr.store.mappings.value.solrMappingAlfresco.httpClientFactory=solrHttpClientFactory -solr.store.mappings.value.solrMappingAlfresco.baseUrl=/solr/alfresco -solr.store.mappings.value.solrMappingAlfresco.protocol=workspace -solr.store.mappings.value.solrMappingAlfresco.identifier=SpacesStore -solr.store.mappings.value.solrMappingArchive.httpClientFactory=solrHttpClientFactory -solr.store.mappings.value.solrMappingArchive.baseUrl=/solr/archive -solr.store.mappings.value.solrMappingArchive.protocol=archive -solr.store.mappings.value.solrMappingArchive.identifier=SpacesStore - -# -# Web Publishing Properties -# -publishing.root.path=/app:company_home/app:dictionary -publishing.root=${publishing.root.path}/${spaces.publishing.root.childname} - -# -# URL Shortening Properties -# -urlshortening.bitly.username=brianalfresco -urlshortening.bitly.api.key=R_ca15c6c89e9b25ccd170bafd209a0d4f -urlshortening.bitly.url.length=20 - -# -# Bulk Filesystem Importer -# - -# The number of threads to employ in a batch import -bulkImport.batch.numThreads=4 - -# The size of a batch in a batch import i.e. the number of files to import in a -# transaction/thread -bulkImport.batch.batchSize=20 - - -# -# Caching Content Store -# -system.content.caching.cacheOnInbound=true -system.content.caching.maxDeleteWatchCount=1 -# Clean up every day at 3 am -system.content.caching.contentCleanup.cronExpression=0 0 3 * * ? -system.content.caching.minFileAgeMillis=60000 -system.content.caching.maxUsageMB=4096 -# maxFileSizeMB - 0 means no max file size. -system.content.caching.maxFileSizeMB=0 - -mybatis.useLocalCaches=false - -fileFolderService.checkHidden.enabled=true - - -ticket.cleanup.cronExpression=0 0 * * * ? - -# -# Disable load of sample site -# -sample.site.disabled=false - -# -# Download Service Cleanup -# -download.cleaner.startDelayMins=60 -download.cleaner.repeatIntervalMins=60 -download.cleaner.maxAgeMins=60 - -# enable QuickShare - if false then the QuickShare-specific REST APIs will return 403 Forbidden -system.quickshare.enabled=true - -# -# Download Service Limits, in bytes -# -download.maxContentSize=2152852358 - -# Max size of view trashcan files -# -trashcan.MaxSize=1000 - -# -# Use bridge tables for caching authority evaluation. -# -authority.useBridgeTable=true - -# enable QuickShare - if false then the QuickShare-specific REST APIs will return 403 Forbidden -system.quickshare.enabled=true - -# Oubound Mail -mail.service.corePoolSize=8 -mail.service.maximumPoolSize=20 - -# OpenCMIS - -# URL generation overrides - -# if true, the context path of OpenCMIS generated urls will be set to "opencmis.context.value", otherwise it will be taken from the request url -opencmis.context.override=false -opencmis.context.value= -# if true, the servlet path of OpenCMIS generated urls will be set to "opencmis.servletpath.value", otherwise it will be taken from the request url -opencmis.servletpath.override=false -opencmis.servletpath.value= -opencmis.server.override=false -opencmis.server.value= - -nodes.bulkLoad.cachingThreshold=10 - -# Multi-Tenancy - -# if "dir.contentstore.tenants" is set then -# tenants are not co-mingled and all content roots will appear below this container (in sub-folder) -# and when creating a tenant the "contentRootPath" (root content store directory for a given tenant) will be ignored -dir.contentstore.tenants= - -# Gateway Authentication -# gateway authentication is disabled if empty host is specified -alfresco.authentication.gateway.host= -alfresco.authentication.gateway.protocol=https -alfresco.authentication.gateway.port=443 -alfresco.authentication.gateway.outboundHeaders=Authorization,key -alfresco.authentication.gateway.inboundHeaders=X-Alfresco-Authenticator-Key,X-Alfresco-Remote-User -alfresco.authentication.gateway.prefixUrl=/publicapi -alfresco.authentication.gateway.bufferSize=2048 -alfresco.authentication.gateway.connectTimeout=10000 -alfresco.authentication.gateway.readTimeout=120000 -alfresco.authentication.gateway.httpTcpNodelay=true -alfresco.authentication.gateway.httpConnectionStalecheck=true - -# webscripts config -webscripts.encryptTempFiles=false -webscripts.tempDirectoryName=WebScripts -# 4mb -webscripts.memoryThreshold=4194304 -# 4gb -webscripts.setMaxContentSize=4294967296 - -# Property to enable index upgrade for metadata query (MDQ) -# -# The indexes are not added unless this value is changed -# Adding each the supporting indexes may take several hours depending on the size of the database. -# The required indexes may be added in stages. -# See: classpath:alfresco/dbscripts/upgrade/4.2/${db.script.dialect}/metadata-query-indexes.sql -system.metadata-query-indexes.ignored=true - -# -# Do we defer running the shared folder patch? -# -system.patch.sharedFolder.deferred=false -# Default value is run new years day 2030 i.e. not run. -system.patch.sharedFolder.cronExpression=0 0 0 ? 1 1 2030 - +# Repository configuration + +repository.name=Main Repository + +# Directory configuration + +dir.root=./alf_data + +dir.contentstore=${dir.root}/contentstore +dir.contentstore.deleted=${dir.root}/contentstore.deleted + +# The location of cached content +dir.cachedcontent=${dir.root}/cachedcontent + +dir.auditcontentstore=${dir.root}/audit.contentstore + +# The value for the maximum permitted size in bytes of all content. +# No value (or a negative long) will be taken to mean that no limit should be applied. +# See content-services-context.xml +system.content.maximumFileSizeLimit= + +# The location for lucene index files +dir.indexes=${dir.root}/lucene-indexes + +# The location for index backups +dir.indexes.backup=${dir.root}/backup-lucene-indexes + +# The location for lucene index locks +dir.indexes.lock=${dir.indexes}/locks + +#Directory to find external license +dir.license.external=. +# Spring resource location of external license files +location.license.external=file://${dir.license.external}/*.lic +# Spring resource location of embedded license files +location.license.embedded=/WEB-INF/alfresco/license/*.lic +# Spring resource location of license files on shared classpath +location.license.shared=classpath*:/alfresco/extension/license/*.lic + +# WebDAV initialization properties +system.webdav.servlet.enabled=true +system.webdav.url.path.prefix= +system.webdav.storeName=${protocols.storeName} +system.webdav.rootPath=${protocols.rootPath} +# File name patterns that trigger rename shuffle detection +# pattern is used by move - tested against full path after it has been lower cased. +system.webdav.renameShufflePattern=(.*/\\..*)|(.*[a-f0-9]{8}+$)|(.*\\.tmp$)|(.*\\.wbk$)|(.*\\.bak$)|(.*\\~$)|(.*backup.*\\.do[ct]{1}[x]?[m]?$) +system.webdav.activities.enabled=false + + +# Is the JBPM Deploy Process Servlet enabled? +# Default is false. Should not be enabled in production environments as the +# servlet allows unauthenticated deployment of new workflows. +system.workflow.deployservlet.enabled=false + +# Sets the location for the JBPM Configuration File +system.workflow.jbpm.config.location=classpath:org/alfresco/repo/workflow/jbpm/jbpm.cfg.xml + +# Determines if JBPM workflow definitions are shown. +# Default is false. This controls the visibility of JBPM +# workflow definitions from the getDefinitions and +# getAllDefinitions WorkflowService API but still allows +# any in-flight JBPM workflows to be completed. +system.workflow.engine.jbpm.definitions.visible=false + +#Determines if Activiti definitions are visible +system.workflow.engine.activiti.definitions.visible=true + +# Determines if the JBPM engine is enabled +system.workflow.engine.jbpm.enabled=true + +# Determines if the Activiti engine is enabled +system.workflow.engine.activiti.enabled=true +system.workflow.engine.activiti.idblocksize=100 + +# Determines if the workflows that are deployed to the activiti engine should +# be deployed in the tenant-context of the thread IF the tenant-service is enabled +# If set to false, all workflows deployed will be shared among tenants. Recommended +# setting is true unless there is a good reason to not allow deploy tenant-specific +# worklfows when a MT-environment is set up. +system.workflow.deployWorkflowsInTenant=true + +# The maximum number of groups to check for pooled tasks. For performance +# reasons, this is limited to 100 by default. +system.workflow.maxAuthoritiesForPooledTasks=100 + +# The maximum number of pooled tasks to return in a query. It may be necessary +# to limit this depending on UI limitations. +system.workflow.maxPooledTasks=-1 + +# The maximum number of reviewers for "Group Review and Approve" workflow. +# Use '0' for unlimited. +system.workflow.maxGroupReviewers=0 + +index.subsystem.name=lucene + +# ######################################### # +# 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 +# FULL recovery continues when encountering errors +index.recovery.stopOnError=false +index.recovery.maximumPoolSize=5 +# 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: +# Never: * * * * * ? 2099 +# Once every five seconds: 0/5 * * * * ? +# Once every two seconds : 0/2 * * * * ? +# See http://www.quartz-scheduler.org/docs/tutorials/crontrigger.html +index.tracking.cronExpression=0/5 * * * * ? +index.tracking.adm.cronExpression=${index.tracking.cronExpression} +index.tracking.avm.cronExpression=${index.tracking.cronExpression} +# Other properties. +index.tracking.maxTxnDurationMinutes=10 +index.tracking.reindexLagMs=1000 +index.tracking.maxRecordSetSize=1000 +index.tracking.maxTransactionsPerLuceneCommit=100 +index.tracking.disableInTransactionIndexing=false +# Index tracking information of a certain age is cleaned out by a scheduled job. +# Any clustered system that has been offline for longer than this period will need to be seeded +# with a more recent backup of the Lucene indexes or the indexes will have to be fully rebuilt. +# Use -1 to disable purging. This can be switched on at any stage. +index.tracking.minRecordPurgeAgeDays=30 +# Unused transactions will be purged in chunks determined by commit time boundaries. 'index.tracking.purgeSize' specifies the size +# of the chunk (in ms). Default is a couple of hours. +index.tracking.purgeSize=7200000 + +# Reindexing of missing content is by default 'never' carried out. +# The cron expression below can be changed to control the timing of this reindexing. +# Users of Enterprise Alfresco can configure this cron expression via JMX without a server restart. +# Note that if alfresco.cluster.enabled is false in Enterprise, then reindexing will not occur. +index.reindexMissingContent.cronExpression=* * * * * ? 2099 + +# Change the failure behaviour of the configuration checker +system.bootstrap.config_check.strict=true + + +# +# How long should shutdown wait to complete normally before +# taking stronger action and calling System.exit() +# in ms, 10,000 is 10 seconds +# +shutdown.backstop.timeout=10000 +shutdown.backstop.enabled=false + +# 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 + +# The Cron expression controlling the frequency with which the OpenOffice connection is tested +openOffice.test.cronExpression=0 * * * * ? + +# +# Disable all shared caches (mutable and immutable) +# These properties are used for diagnostic purposes +system.cache.disableMutableSharedCaches=false +system.cache.disableImmutableSharedCaches=false + +# The maximum capacity of the parent assocs cache (the number of nodes whose parents can be cached) +system.cache.parentAssocs.maxSize=130000 + +# The average number of parents expected per cache entry. This parameter is multiplied by the above +# value to compute a limit on the total number of cached parents, which will be proportional to the +# cache's memory usage. The cache will be pruned when this limit is exceeded to avoid excessive +# memory usage. +system.cache.parentAssocs.limitFactor=8 + +# +# Properties to limit resources spent on individual searches +# +# The maximum time spent pruning results +system.acl.maxPermissionCheckTimeMillis=10000 +# The maximum number of search results to perform permission checks against +system.acl.maxPermissionChecks=1000 + +# The maximum number of filefolder list results +system.filefolderservice.defaultListMaxResults=5000 + +# Properties to control read permission evaluation for acegi +system.readpermissions.optimise=true +system.readpermissions.bulkfetchsize=1000 + +# +# Manually control how the system handles maximum string lengths. +# Any zero or negative value is ignored. +# Only change this after consulting support or reading the appropriate Javadocs for +# org.alfresco.repo.domain.schema.SchemaBootstrap for V2.1.2 +system.maximumStringLength=-1 + +# +# Limit hibernate session size by trying to amalgamate events for the L2 session invalidation +# - hibernate works as is up to this size +# - after the limit is hit events that can be grouped invalidate the L2 cache by type and not instance +# events may not group if there are post action listener registered (this is not the case with the default distribution) +system.hibernateMaxExecutions=20000 + +# +# Determine if modification timestamp propagation from child to parent nodes is respected or not. +# Even if 'true', the functionality is only supported for child associations that declare the +# 'propagateTimestamps' element in the dictionary definition. +system.enableTimestampPropagation=true + +# +# Enable system model integrity checking. +# WARNING: Changing this is unsupported; bugs may corrupt data +system.integrity.enabled=true +# Do integrity violations fail transactions +# WARNING: Changing this is unsupported; bugs may corrupt data +system.integrity.failOnViolation=true +# The number of errors to report when violations are detected +system.integrity.maxErrorsPerTransaction=5 +# Add call stacks to integrity events so that errors are logged with possible causes +# WARNING: This is expensive and should only be switched on for diagnostic purposes +system.integrity.trace=false + +# +# Decide if content should be removed from the system immediately after being orphaned. +# Do not change this unless you have examined the impact it has on your backup procedures. +system.content.eagerOrphanCleanup=false +# The number of days to keep orphaned content in the content stores. +# This has no effect on the 'deleted' content stores, which are not automatically emptied. +system.content.orphanProtectDays=14 +# The action to take when a store or stores fails to delete orphaned content +# IGNORE: Just log a warning. The binary remains and the record is expunged +# KEEP_URL: Log a warning and create a URL entry with orphan time 0. It won't be processed or removed. +system.content.deletionFailureAction=IGNORE +# The CRON expression to trigger the deletion of resources associated with orphaned content. +system.content.orphanCleanup.cronExpression=0 0 4 * * ? +# The CRON expression to trigger content URL conversion. This process is not intesive and can +# be triggered on a live system. Similarly, it can be triggered using JMX on a dedicated machine. +system.content.contentUrlConverter.cronExpression=* * * * * ? 2099 +system.content.contentUrlConverter.threadCount=2 +system.content.contentUrlConverter.batchSize=500 +system.content.contentUrlConverter.runAsScheduledJob=false + +# #################### # +# Lucene configuration # +# #################### # +# +# Millisecond threshold for text transformations +# Slower transformers will force the text extraction to be asynchronous +# +lucene.maxAtomicTransformationTime=100 +# +# 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 +fts.indexer.batchSize=1000 +# +# Index cache sizes +# +lucene.indexer.cacheEnabled=true +lucene.indexer.maxDocIdCacheSize=100000 +lucene.indexer.maxDocumentCacheSize=100 +lucene.indexer.maxIsCategoryCacheSize=-1 +lucene.indexer.maxLinkAspectCacheSize=10000 +lucene.indexer.maxParentCacheSize=100000 +lucene.indexer.maxPathCacheSize=100000 +lucene.indexer.maxTypeCacheSize=10000 +# +# Properties for merge (not this does not affect the final index segment which will be optimised) +# Max merge docs only applies to the merge process not the resulting index which will be optimised. +# +lucene.indexer.mergerMaxMergeDocs=1000000 +lucene.indexer.mergerMergeFactor=5 +lucene.indexer.mergerMaxBufferedDocs=-1 +lucene.indexer.mergerRamBufferSizeMb=16 +# +# Properties for delta indexes (not this does not affect the final index segment which will be optimised) +# Max merge docs only applies to the index building process not the resulting index which will be optimised. +# +lucene.indexer.writerMaxMergeDocs=1000000 +lucene.indexer.writerMergeFactor=5 +lucene.indexer.writerMaxBufferedDocs=-1 +lucene.indexer.writerRamBufferSizeMb=16 +# +# Target number of indexes and deltas in the overall index and what index size to merge in memory +# +lucene.indexer.mergerTargetIndexCount=8 +lucene.indexer.mergerTargetOverlayCount=5 +lucene.indexer.mergerTargetOverlaysBlockingFactor=2 +lucene.indexer.maxDocsForInMemoryMerge=60000 +lucene.indexer.maxRamInMbForInMemoryMerge=16 +lucene.indexer.maxDocsForInMemoryIndex=60000 +lucene.indexer.maxRamInMbForInMemoryIndex=16 +# +# Other lucene properties +# +lucene.indexer.termIndexInterval=128 +lucene.indexer.useNioMemoryMapping=true +# over-ride to false for pre 3.0 behaviour +lucene.indexer.postSortDateTime=true +lucene.indexer.defaultMLIndexAnalysisMode=EXACT_LANGUAGE_AND_ALL +lucene.indexer.defaultMLSearchAnalysisMode=EXACT_LANGUAGE_AND_ALL +# +# The number of terms from a document that will be indexed +# +lucene.indexer.maxFieldLength=10000 + +# Should we use a 'fair' locking policy, giving queue-like access behaviour to +# the indexes and avoiding starvation of waiting writers? Set to false on old +# JVMs where this appears to cause deadlock +lucene.indexer.fairLocking=true + +# +# Index locks (mostly deprecated and will be tidied up with the next lucene upgrade) +# +lucene.write.lock.timeout=10000 +lucene.commit.lock.timeout=100000 +lucene.lock.poll.interval=100 + +lucene.indexer.useInMemorySort=true +lucene.indexer.maxRawResultSetSizeForInMemorySort=1000 +lucene.indexer.contentIndexingEnabled=true + +index.backup.cronExpression=0 0 3 * * ? + +lucene.defaultAnalyserResourceBundleName=alfresco/model/dataTypeAnalyzers + + +# When transforming archive files (.zip etc) into text representations (such as +# for full text indexing), should the files within the archive be processed too? +# If enabled, transformation takes longer, but searches of the files find more. +transformer.Archive.includeContents=false + +# Database configuration +db.schema.stopAfterSchemaBootstrap=false +db.schema.update=true +db.schema.update.lockRetryCount=24 +db.schema.update.lockRetryWaitSeconds=5 +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=40 +db.txn.isolation=-1 +db.pool.statements.enable=true +db.pool.statements.max=40 +db.pool.min=0 +db.pool.idle=-1 +db.pool.wait.max=-1 + +db.pool.validate.query= +db.pool.evict.interval=-1 +db.pool.evict.idle.min=1800000 +# +# note: for 'db.pool.evict.num.tests' see http://commons.apache.org/dbcp/configuration.html (numTestsPerEvictionRun) +# and also following extract from "org.apache.commons.pool.impl.GenericKeyedObjectPool" (1.5.5) +# +# * The number of objects to examine during each run of the idle object evictor thread (if any). +# * When a negative value is supplied, ceil({@link #getNumIdle})/abs({@link #getNumTestsPerEvictionRun}) +# * tests will be run. I.e., when the value is -n, roughly one nth of the +# * idle objects will be tested per run. +# +db.pool.evict.num.tests=-1 + +db.pool.evict.validate=false +db.pool.validate.borrow=true +db.pool.validate.return=false + +db.pool.abandoned.detect=false +db.pool.abandoned.time=300 +# +# db.pool.abandoned.log=true (logAbandoned) adds overhead (http://commons.apache.org/dbcp/configuration.html) +# and also requires db.pool.abandoned.detect=true (removeAbandoned) +# +db.pool.abandoned.log=false + + +# Audit configuration +audit.enabled=true +audit.tagging.enabled=true +audit.alfresco-access.enabled=false +audit.alfresco-access.sub-actions.enabled=false +audit.cmischangelog.enabled=false +audit.dod5015.enabled=false +# Setting this flag to true will force startup failure when invalid audit configurations are detected +audit.config.strict=false +# Audit map filter for AccessAuditor - restricts recorded events to user driven events +audit.filter.alfresco-access.default.enabled=true +audit.filter.alfresco-access.transaction.user=~System;~null;.* +audit.filter.alfresco-access.transaction.type=cm:folder;cm:content;st:site +audit.filter.alfresco-access.transaction.path=~/sys:archivedItem;~/ver:;.* + + +# 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 + +# note: default admin username - should not be changed after installation +alfresco_user_store.adminusername=admin + +# Initial password - editing this will not have any effect once the repository is installed +alfresco_user_store.adminpassword=209c6174da490caeb422f3fa5a7ae634 +alfresco_user_store.adminsalt=ad3b938f-c1ad-4f2b-828b-6f3afd30ffdd +alfresco_user_store.adminpassword2=f378d5d7b947d5c26f478e21819e7ec3a6668c8149b050d086c64447bc40173b + +# note: default guest username - should not be changed after installation +alfresco_user_store.guestusername=guest + +# Used to move home folders to a new location +home_folder_provider_synchronizer.enabled=false +home_folder_provider_synchronizer.override_provider= +home_folder_provider_synchronizer.keep_empty_parents=false + +# 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.imap_attachments.childname=cm:Imap Attachments +spaces.imap_home.childname=cm:Imap Home +spaces.imapConfig.childname=app:imap_configs +spaces.imap_templates.childname=app:imap_templates +spaces.scheduled_actions.childname=cm:Scheduled Actions +spaces.emailActions.childname=app:email_actions +spaces.searchAction.childname=cm:search +spaces.templates.content.childname=app:content_templates +spaces.templates.email.childname=app:email_templates +spaces.templates.email.invite1.childname=app:invite_email_templates +spaces.templates.email.notify.childname=app:notify_email_templates +spaces.templates.email.following.childname=app:following +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.user_homes.regex.key=userName +spaces.user_homes.regex.pattern= +spaces.user_homes.regex.group_order= +spaces.sites.childname=st:sites +spaces.templates.email.invite.childname=cm:invite +spaces.templates.email.activities.childname=cm:activities +spaces.rendition.rendering_actions.childname=app:rendering_actions +spaces.replication.replication_actions.childname=app:replication_actions +spaces.wcm_deployed.childname=cm:wcm_deployed +spaces.transfers.childname=app:transfers +spaces.transfer_groups.childname=app:transfer_groups +spaces.transfer_temp.childname=app:temp +spaces.inbound_transfer_records.childname=app:inbound_transfer_records +spaces.webscripts.childname=cm:webscripts +spaces.extension_webscripts.childname=cm:extensionwebscripts +spaces.models.childname=app:models +spaces.workflow.definitions.childname=app:workflow_defs +spaces.publishing.root.childname=app:publishing_root +spaces.templates.email.workflowemailnotification.childname=cm:workflownotification +spaces.nodetemplates.childname=app:node_templates +spaces.shared.childname=app:shared + +# ADM VersionStore Configuration +version.store.enableAutoVersioning=true +version.store.deprecated.lightWeightVersionStore=workspace://lightWeightVersionStore +version.store.version2Store=workspace://version2Store + +version.store.migrateVersionStore.threadCount=3 +version.store.migrateVersionStore.batchSize=1 + +version.store.migrateCleanupJob.threadCount=3 +version.store.migrateCleanupJob.batchSize=1 + + +# WARNING: For non-production testing only !!! Do not change (to avoid version store issues, including possible mismatch). Should be false since lightWeightVersionStore is deprecated. +version.store.onlyUseDeprecatedV1=false + +# The CRON expression to trigger migration of the version store from V1 (2.x) to V2 (3.x) +# By default, this is effectively 'never' but can be modified as required. +# Examples: +# Never: * * * * * ? 2099 +# Once every thirty minutes: 0 0/30 * * * ? +# See http://www.quartz-scheduler.org/docs/tutorials/crontrigger.html +version.store.migrateVersionStore.cronExpression=* * * * * ? 2099 +# Limit number of version histories to migrate per job cycle, where -1 = unlimited. Note: if limit > 0 then need to schedule job to run regularly in order to complete the migration. +version.store.migrateVersionStore.limitPerJobCycle=-1 +version.store.migrateVersionStore.runAsScheduledJob=false + +# Optional Comparator class name to sort versions. +# Set to: org.alfresco.repo.version.common.VersionLabelComparator +# if upgrading from a version that used unordered sequences in a cluster. +version.store.versionComparatorClass= + +# Folders for storing people +system.system_container.childname=sys:system +system.people_container.childname=sys:people +system.authorities_container.childname=sys:authorities +system.zones_container.childname=sys:zones + +# Folders for storing workflow related info +system.workflow_container.childname=sys:workflow + +# Folder for storing shared remote credentials +system.remote_credentials_container.childname=sys:remote_credentials + +# Folder for storing syncset definitions +system.syncset_definition_container.childname=sys:syncset_definitions + +# Folder for storing download archives +system.downloads_container.childname=sys:downloads + +# Folder for storing IdP's certificate definitions +system.certificate_container.childname=sys:samlcertificate + +# Are user names case sensitive? +user.name.caseSensitive=false +domain.name.caseSensitive=false +domain.separator= + +# AVM Specific properties. +avm.remote.idlestream.timeout=30000 + +#Format caption extracted from the XML Schema. +xforms.formatCaption=true + +# ECM content usages/quotas +system.usages.enabled=false +system.usages.clearBatchSize=0 +system.usages.updateBatchSize=50 + +# Repository endpoint - used by Activity Service +repo.remote.endpoint=/service + +# Some authentication mechanisms may need to create people +# in the repository on demand. This enables that feature. +# If disabled an error will be generated for missing +# people. If enabled then a person will be created and +# persisted. +create.missing.people=${server.transaction.allow-writes} + +# Create home folders (unless disabled, see next property) as people are created (true) or create them lazily (false) +home.folder.creation.eager=true +# Disable home folder creation - if true then home folders are not created (neither eagerly nor lazily) +home.folder.creation.disabled=false + +# Should we consider zero byte content to be the same as no content when firing +# content update policies? Prevents 'premature' firing of inbound content rules +# for some clients such as Mac OS X Finder +policy.content.update.ignoreEmpty=true + +# The well known RMI registry port and external host name published in the stubs +# is defined in the alfresco-shared.properties file +# +# alfresco.rmi.services.port=50500 + +# Default value of alfresco.rmi.services.host is 0.0.0.0 which means 'listen on all adapters'. +# This allows connections to JMX both remotely and locally. +# +alfresco.rmi.services.host=0.0.0.0 + +# If the RMI address is in-use, how many retries should be done before aborting +# Default value of alfresco.rmi.services.retries is 0 which means 'Don't retry if the address is in-use' +alfresco.rmi.services.retries=4 + +# RMI service ports for the individual services. +# These eight services are available remotely. +# +# Assign individual ports for each service for best performance +# or run several services on the same port, you can even run everything on 50500 if +# running through a firewall. +# +# Specify 0 to use a random unused port. +# +avm.rmi.service.port=50501 +avmsync.rmi.service.port=50502 +authentication.rmi.service.port=50504 +repo.rmi.service.port=50505 +action.rmi.service.port=50506 +deployment.rmi.service.port=50507 +monitor.rmi.service.port=50508 + +# +# enable or disable individual RMI services +# +avm.rmi.service.enabled=true +avmsync.rmi.service.enabled=true +authentication.rmi.service.enabled=true +repo.rmi.service.enabled=true +action.rmi.service.enabled=true +deployment.rmi.service.enabled=true +monitor.rmi.service.enabled=true + + +# Should the Mbean server bind to an existing server. Set to true for most application servers. +# false for WebSphere clusters. +mbean.server.locateExistingServerIfPossible=true + +# External executable locations +ooo.exe=soffice +ooo.user=${dir.root}/oouser +img.root=./ImageMagick +img.dyn=${img.root}/lib +img.exe=${img.root}/bin/convert +swf.exe=./bin/pdf2swf +swf.languagedir=. + +# Thumbnail Service +system.thumbnail.generate=true + +# Default thumbnail limits +# When creating thumbnails, only use the first pageLimit pages +system.thumbnail.definition.default.timeoutMs=-1 +system.thumbnail.definition.default.readLimitTimeMs=-1 +system.thumbnail.definition.default.maxSourceSizeKBytes=-1 +system.thumbnail.definition.default.readLimitKBytes=-1 +system.thumbnail.definition.default.pageLimit=1 +system.thumbnail.definition.default.maxPages=-1 + +# Max mimetype sizes to create thumbnail icons +system.thumbnail.mimetype.maxSourceSizeKBytes.pdf=-1 +system.thumbnail.mimetype.maxSourceSizeKBytes.txt=-1 +system.thumbnail.mimetype.maxSourceSizeKBytes.docx=-1 +system.thumbnail.mimetype.maxSourceSizeKBytes.xlsx=-1 +system.thumbnail.mimetype.maxSourceSizeKBytes.pptx=-1 +system.thumbnail.mimetype.maxSourceSizeKBytes.odt=-1 +system.thumbnail.mimetype.maxSourceSizeKBytes.ods=-1 +system.thumbnail.mimetype.maxSourceSizeKBytes.odp=-1 + +# Configuration for handling of failing thumbnails. +# See NodeEligibleForRethumbnailingEvaluator's javadoc for details. +# +# Retry periods limit the frequency with which the repository will attempt to create Share thumbnails +# for content nodes which have previously failed in their thumbnail attempts. +# These periods are in seconds. +# +# 604800s = 60s * 60m * 24h * 7d = 1 week +system.thumbnail.retryPeriod=60 +system.thumbnail.retryCount=2 +system.thumbnail.quietPeriod=604800 +system.thumbnail.quietPeriodRetriesEnabled=true +system.thumbnail.redeployStaticDefsOnStartup=true + +# The default timeout for metadata mapping extracters +content.metadataExtracter.default.timeoutMs=20000 + +# Property to enable upgrade from 2.1-A +V2.1-A.fixes.to.schema=0 +#V2.1-A.fixes.to.schema=82 + +# The default authentication chain +authentication.chain=alfrescoNtlm1:alfrescoNtlm + +# Do authentication tickets expire or live for ever? +authentication.ticket.ticketsExpire=true + +# If ticketsEpire is true then how they should expire? +# Valid values are: AFTER_INACTIVITY, AFTER_FIXED_TIME, DO_NOT_EXPIRE +# The default is AFTER_FIXED_TIME +authentication.ticket.expiryMode=AFTER_INACTIVITY + +# If authentication.ticket.ticketsExpire is true and +# authentication.ticket.expiryMode is AFTER_FIXED_TIME or AFTER_INACTIVITY, +# this controls the minimum period for which tickets are valid. +# The default is PT1H for one hour. +authentication.ticket.validDuration=PT1H + +# Use one ticket for all user sessions +# For the pre 4.2 behaviour of one ticket per session set this to false. +authentication.ticket.useSingleTicketPerUser=true + +# If kerberos.authentication.cifs.enableTicketCracking is false, +# the Kerberos ticket cracking code is switched off. +# This code was required to get mutual authentication with a Windows AD client working in earlier versions of Java (version 5 or earlier). +# The latest JVMs don't require this code as they have better support for SPNEGO/GSS authentication. +# Please, see MNT-7392 for details. +kerberos.authentication.cifs.enableTicketCracking=false + +# Default NFS user mappings (empty). Note these users will be able to +# authenticate through NFS without password so ensure NFS port is secure before +# enabling and adding mappings +nfs.user.mappings= +nfs.user.mappings.default.uid=0 +nfs.user.mappings.default.gid=0 + +#Example NFS user mappings +#nfs.user.mappings=admin,user1 +#nfs.user.mappings.value.admin.uid=0 +#nfs.user.mappings.value.admin.gid=0 +#nfs.user.mappings.value.user1.uid=500 +#nfs.user.mappings.value.user1.gid=500 + +# Default root path for protocols +protocols.storeName=${spaces.store} +protocols.rootPath=/${spaces.company_home.childname} + +# OpenCMIS +opencmis.connector.default.store=${spaces.store} +opencmis.connector.default.rootPath=/${spaces.company_home.childname} +opencmis.connector.default.typesDefaultMaxItems=500 +opencmis.connector.default.typesDefaultDepth=-1 +opencmis.connector.default.objectsDefaultMaxItems=10000 +opencmis.connector.default.objectsDefaultDepth=100 +opencmis.connector.default.openHttpSession=false +opencmis.activities.enabled=true + +# IMAP +imap.server.enabled=false +imap.server.port=143 +imap.server.attachments.extraction.enabled=true + +# Default IMAP mount points +imap.config.home.store=${spaces.store} +imap.config.home.rootPath=/${spaces.company_home.childname} +imap.config.home.folderPath=${spaces.imap_home.childname} +imap.config.server.mountPoints=AlfrescoIMAP +imap.config.server.mountPoints.default.mountPointName=IMAP +imap.config.server.mountPoints.default.modeName=ARCHIVE +imap.config.server.mountPoints.default.store=${spaces.store} +imap.config.server.mountPoints.default.rootPath=${protocols.rootPath} +imap.config.server.mountPoints.value.AlfrescoIMAP.mountPointName=Alfresco IMAP +imap.config.server.mountPoints.value.AlfrescoIMAP.modeName=MIXED + +#Imap extraction settings +#imap.attachments.mode: +# SEPARATE -- All attachments for each email will be extracted to separate folder. +# COMMON -- All attachments for all emails will be extracted to one folder. +# SAME -- Attachments will be extracted to the same folder where email lies. +imap.server.attachments.extraction.enabled=true +imap.attachments.mode=SEPARATE +imap.attachments.folder.store=${spaces.store} +imap.attachments.folder.rootPath=/${spaces.company_home.childname} +imap.attachments.folder.folderPath=${spaces.imap_attachments.childname} + +# Activities Feed - refer to subsystem + +# Feed max ID range to limit maximum number of entries +activities.feed.max.idRange=1000000 +# Feed max size (number of entries) +activities.feed.max.size=100 +# Feed max age (eg. 44640 mins => 31 days) +activities.feed.max.ageMins=44640 + +activities.feed.generator.jsonFormatOnly=true +activities.feed.fetchBatchSize=150 +activities.feedNotifier.batchSize=200 +activities.feedNotifier.numThreads=2 + +# Subsystem unit test values. Will not have any effect on production servers +subsystems.test.beanProp.default.longProperty=123456789123456789 +subsystems.test.beanProp.default.anotherStringProperty=Global Default +subsystems.test.beanProp=inst1,inst2,inst3 +subsystems.test.beanProp.value.inst2.boolProperty=true +subsystems.test.beanProp.value.inst3.anotherStringProperty=Global Instance Default +subsystems.test.simpleProp2=true +subsystems.test.simpleProp3=Global Default3 + +# Default Async Action Thread Pool +default.async.action.threadPriority=1 +default.async.action.corePoolSize=8 +default.async.action.maximumPoolSize=20 + +# Deployment Service +deployment.service.numberOfSendingThreads=5 +deployment.service.corePoolSize=2 +deployment.service.maximumPoolSize=3 +deployment.service.threadPriority=5 +# How long to wait in mS before refreshing a target lock - detects shutdown servers +deployment.service.targetLockRefreshTime=60000 +# How long to wait in mS from the last communication before deciding that deployment has failed, possibly +# the destination is no longer available? +deployment.service.targetLockTimeout=3600000 + +#Invitation Service +# Should send emails as part of invitation process. +notification.email.siteinvite=true + +# Transfer Service +transferservice.receiver.enabled=true +transferservice.receiver.stagingDir=${java.io.tmpdir}/alfresco-transfer-staging +# +# How long to wait in mS before refreshing a transfer lock - detects shutdown servers +# Default 1 minute. +transferservice.receiver.lockRefreshTime=60000 +# +# How many times to attempt retry the transfer lock +transferservice.receiver.lockRetryCount=3 +# How long to wait, in mS, before retrying the transfer lock +transferservice.receiver.lockRetryWait=100 +# +# How long to wait, in mS, since the last contact with from the client before +# timing out a transfer. Needs to be long enough to cope with network delays and "thinking +# time" for both source and destination. Default 5 minutes. +transferservice.receiver.lockTimeOut=300000 + +# Max time allowed for WCM folder rename operation issued by external clients (CIFS, FTP) +wcm.rename.max.time.milliseconds=2000 + +; DM Receiever Properties +; +; The name of the DM Receiver target - you deploy to this target name +deployment.dmr.name=alfresco + +; consolidate staging, author and workflow sandboxes to one +deployment.dmr.consolidate=true + +; The name of the Alfresco receiver targer +deployment.avm.name=avm + +;Where should the root of the web project be stored, by default /www/avm_webapps +deployment.avm.rootPath=/www/avm_webapps + +; Pattern for live stores deployment by the alfresco receiver +deployment.avm.storeNamePattern=%storeName%-live + +; Built in deployment receiver properties for the default +; filesystem receiver + +; filesystem receiver configuration +deployment.filesystem.rootdir=./wcm +deployment.filesystem.datadir=${deployment.filesystem.rootdir}/depdata +deployment.filesystem.logdir=${deployment.filesystem.rootdir}/deplog +deployment.filesystem.metadatadir=${deployment.filesystem.rootdir}/depmetadata + +deployment.filesystem.autofix=true +deployment.filesystem.errorOnOverwrite=false + +; default filesystem target configuration +deployment.filesystem.default.rootdir=./www +deployment.filesystem.default.name=filesystem +deployment.filesystem.default.metadatadir=${deployment.filesystem.metadatadir}/default + +# OrphanReaper +orphanReaper.lockRefreshTime=60000 +orphanReaper.lockTimeOut=3600000 + + +# security +security.anyDenyDenies=true + +# +# Encryption properties +# +# default keystores location +dir.keystore=classpath:alfresco/keystore + +# general encryption parameters +encryption.keySpec.class=org.alfresco.encryption.DESEDEKeyGenerator +encryption.keyAlgorithm=DESede +encryption.cipherAlgorithm=DESede/CBC/PKCS5Padding + +# secret key keystore configuration +encryption.keystore.location=${dir.keystore}/keystore +encryption.keystore.keyMetaData.location=${dir.keystore}/keystore-passwords.properties +encryption.keystore.provider= +encryption.keystore.type=JCEKS + +# backup secret key keystore configuration +encryption.keystore.backup.location=${dir.keystore}/backup-keystore +encryption.keystore.backup.keyMetaData.location=${dir.keystore}/backup-keystore-passwords.properties +encryption.keystore.backup.provider= +encryption.keystore.backup.type=JCEKS + +# Should encryptable properties be re-encrypted with new encryption keys on botstrap? +encryption.bootstrap.reencrypt=false + +# mac/md5 encryption +encryption.mac.messageTimeout=30000 +encryption.mac.algorithm=HmacSHA1 + +# ssl encryption +encryption.ssl.keystore.location=${dir.keystore}/ssl.keystore +encryption.ssl.keystore.provider= +encryption.ssl.keystore.type=JCEKS +encryption.ssl.keystore.keyMetaData.location=${dir.keystore}/ssl-keystore-passwords.properties +encryption.ssl.truststore.location=${dir.keystore}/ssl.truststore +encryption.ssl.truststore.provider= +encryption.ssl.truststore.type=JCEKS +encryption.ssl.truststore.keyMetaData.location=${dir.keystore}/ssl-truststore-passwords.properties + +# Re-encryptor properties +encryption.reencryptor.chunkSize=100 +encryption.reencryptor.numThreads=2 + +# SOLR connection details (e.g. for JMX) +solr.host=localhost +solr.port=8080 +solr.port.ssl=8443 +solr.solrUser=solr +solr.solrPassword=solr +# none, https +solr.secureComms=https +solr.cmis.alternativeDictionary=DEFAULT_DICTIONARY + +solr.max.total.connections=40 +solr.max.host.connections=40 + +# Solr connection timeouts +# solr connect timeout in ms +solr.solrConnectTimeout=5000 + +# cron expression defining how often the Solr Admin client (used by JMX) pings Solr if it goes away +solr.solrPingCronExpression=0 0/5 * * * ? * + + +#Default SOLR store mappings mappings +solr.store.mappings=solrMappingAlfresco,solrMappingArchive +solr.store.mappings.value.solrMappingAlfresco.httpClientFactory=solrHttpClientFactory +solr.store.mappings.value.solrMappingAlfresco.baseUrl=/solr/alfresco +solr.store.mappings.value.solrMappingAlfresco.protocol=workspace +solr.store.mappings.value.solrMappingAlfresco.identifier=SpacesStore +solr.store.mappings.value.solrMappingArchive.httpClientFactory=solrHttpClientFactory +solr.store.mappings.value.solrMappingArchive.baseUrl=/solr/archive +solr.store.mappings.value.solrMappingArchive.protocol=archive +solr.store.mappings.value.solrMappingArchive.identifier=SpacesStore + +# +# Web Publishing Properties +# +publishing.root.path=/app:company_home/app:dictionary +publishing.root=${publishing.root.path}/${spaces.publishing.root.childname} + +# +# URL Shortening Properties +# +urlshortening.bitly.username=brianalfresco +urlshortening.bitly.api.key=R_ca15c6c89e9b25ccd170bafd209a0d4f +urlshortening.bitly.url.length=20 + +# +# Bulk Filesystem Importer +# + +# The number of threads to employ in a batch import +bulkImport.batch.numThreads=4 + +# The size of a batch in a batch import i.e. the number of files to import in a +# transaction/thread +bulkImport.batch.batchSize=20 + + +# +# Caching Content Store +# +system.content.caching.cacheOnInbound=true +system.content.caching.maxDeleteWatchCount=1 +# Clean up every day at 3 am +system.content.caching.contentCleanup.cronExpression=0 0 3 * * ? +system.content.caching.minFileAgeMillis=60000 +system.content.caching.maxUsageMB=4096 +# maxFileSizeMB - 0 means no max file size. +system.content.caching.maxFileSizeMB=0 + +mybatis.useLocalCaches=false + +fileFolderService.checkHidden.enabled=true + + +ticket.cleanup.cronExpression=0 0 * * * ? + +# +# Disable load of sample site +# +sample.site.disabled=false + +# +# Download Service Cleanup +# +download.cleaner.startDelayMins=60 +download.cleaner.repeatIntervalMins=60 +download.cleaner.maxAgeMins=60 + +# enable QuickShare - if false then the QuickShare-specific REST APIs will return 403 Forbidden +system.quickshare.enabled=true + +# +# Download Service Limits, in bytes +# +download.maxContentSize=2152852358 + +# Max size of view trashcan files +# +trashcan.MaxSize=1000 + +# +# Use bridge tables for caching authority evaluation. +# +authority.useBridgeTable=true + +# enable QuickShare - if false then the QuickShare-specific REST APIs will return 403 Forbidden +system.quickshare.enabled=true + +# Oubound Mail +mail.service.corePoolSize=8 +mail.service.maximumPoolSize=20 + +# OpenCMIS + +# URL generation overrides + +# if true, the context path of OpenCMIS generated urls will be set to "opencmis.context.value", otherwise it will be taken from the request url +opencmis.context.override=false +opencmis.context.value= +# if true, the servlet path of OpenCMIS generated urls will be set to "opencmis.servletpath.value", otherwise it will be taken from the request url +opencmis.servletpath.override=false +opencmis.servletpath.value= +opencmis.server.override=false +opencmis.server.value= + +nodes.bulkLoad.cachingThreshold=10 + +# Multi-Tenancy + +# if "dir.contentstore.tenants" is set then +# tenants are not co-mingled and all content roots will appear below this container (in sub-folder) +# and when creating a tenant the "contentRootPath" (root content store directory for a given tenant) will be ignored +dir.contentstore.tenants= + +# Gateway Authentication +# gateway authentication is disabled if empty host is specified +alfresco.authentication.gateway.host= +alfresco.authentication.gateway.protocol=https +alfresco.authentication.gateway.port=443 +alfresco.authentication.gateway.outboundHeaders=Authorization,key +alfresco.authentication.gateway.inboundHeaders=X-Alfresco-Authenticator-Key,X-Alfresco-Remote-User +alfresco.authentication.gateway.prefixUrl=/publicapi +alfresco.authentication.gateway.bufferSize=2048 +alfresco.authentication.gateway.connectTimeout=10000 +alfresco.authentication.gateway.readTimeout=120000 +alfresco.authentication.gateway.httpTcpNodelay=true +alfresco.authentication.gateway.httpConnectionStalecheck=true + +# webscripts config +webscripts.encryptTempFiles=false +webscripts.tempDirectoryName=WebScripts +# 4mb +webscripts.memoryThreshold=4194304 +# 4gb +webscripts.setMaxContentSize=4294967296 + +# Property to enable index upgrade for metadata query (MDQ) +# +# The indexes are not added unless this value is changed +# Adding each the supporting indexes may take several hours depending on the size of the database. +# The required indexes may be added in stages. +# See: classpath:alfresco/dbscripts/upgrade/4.2/${db.script.dialect}/metadata-query-indexes.sql +system.metadata-query-indexes.ignored=true + +# +# Do we defer running the shared folder patch? +# +system.patch.sharedFolder.deferred=false +# Default value is run new years day 2030 i.e. not run. +system.patch.sharedFolder.cronExpression=0 0 0 ? 1 1 2030 + diff --git a/source/java/org/alfresco/repo/admin/patch/impl/CopiedFromAspectPatch.java b/source/java/org/alfresco/repo/admin/patch/impl/CopiedFromAspectPatch.java index 55c2db46cc..dfca2b905f 100644 --- a/source/java/org/alfresco/repo/admin/patch/impl/CopiedFromAspectPatch.java +++ b/source/java/org/alfresco/repo/admin/patch/impl/CopiedFromAspectPatch.java @@ -229,6 +229,7 @@ public class CopiedFromAspectPatch extends AbstractPatch } finally { + try { outputFile.close(); } catch (IOException e) {} try { file.close(); } catch (IOException e) {} } } diff --git a/source/java/org/alfresco/repo/coci/WorkingCopyAspect.java b/source/java/org/alfresco/repo/coci/WorkingCopyAspect.java index b0c1b05496..0652730d20 100644 --- a/source/java/org/alfresco/repo/coci/WorkingCopyAspect.java +++ b/source/java/org/alfresco/repo/coci/WorkingCopyAspect.java @@ -21,6 +21,7 @@ package org.alfresco.repo.coci; import java.io.Serializable; import java.util.Collections; +import java.util.List; import java.util.Map; import org.alfresco.model.ContentModel; @@ -34,12 +35,13 @@ import org.alfresco.repo.policy.JavaBehaviour; import org.alfresco.repo.policy.PolicyComponent; import org.alfresco.service.cmr.coci.CheckOutCheckInService; import org.alfresco.service.cmr.lock.LockService; +import org.alfresco.service.cmr.repository.AssociationRef; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.namespace.QName; import org.alfresco.util.GUID; -public class WorkingCopyAspect implements CopyServicePolicies.OnCopyNodePolicy +public class WorkingCopyAspect implements CopyServicePolicies.OnCopyNodePolicy, NodeServicePolicies.OnRemoveAspectPolicy { private PolicyComponent policyComponent; private NodeService nodeService; @@ -117,7 +119,12 @@ public class WorkingCopyAspect implements CopyServicePolicies.OnCopyNodePolicy NodeServicePolicies.BeforeDeleteNodePolicy.QNAME, ContentModel.ASPECT_WORKING_COPY, new JavaBehaviour(this, "beforeDeleteWorkingCopy")); - // register onBeforeDelete class behaviour for the checked-out aspect + + // Watch for removal of the aspect and ensure that the cm:workingcopylink assoc is removed + this.policyComponent.bindClassBehaviour( + NodeServicePolicies.OnRemoveAspectPolicy.QNAME, + ContentModel.ASPECT_WORKING_COPY, + new JavaBehaviour(this, "onRemoveAspect")); } /** @@ -143,6 +150,13 @@ public class WorkingCopyAspect implements CopyServicePolicies.OnCopyNodePolicy } } + @Override + public void onRemoveAspect(NodeRef nodeRef, QName aspectTypeQName) + { + // This is simply not allowed. + throw new UnsupportedOperationException("Use CheckOutCheckInservice to manipulate working copies."); + } + /** * @return Returns {@link WorkingCopyAspectCopyBehaviourCallback} */ diff --git a/source/java/org/alfresco/repo/node/integrity/AspectsIntegrityEvent.java b/source/java/org/alfresco/repo/node/integrity/AspectsIntegrityEvent.java index 5627d4cd54..61d26563bd 100644 --- a/source/java/org/alfresco/repo/node/integrity/AspectsIntegrityEvent.java +++ b/source/java/org/alfresco/repo/node/integrity/AspectsIntegrityEvent.java @@ -18,6 +18,7 @@ */ package org.alfresco.repo.node.integrity; +import java.util.Collections; import java.util.List; import java.util.Set; @@ -77,7 +78,9 @@ public class AspectsIntegrityEvent extends AbstractIntegrityEvent QName nodeTypeQName = nodeService.getType(nodeRef); // get the aspects that should exist TypeDefinition typeDef = dictionaryService.getType(nodeTypeQName); - List mandatoryAspectDefs = typeDef.getDefaultAspects(); + List mandatoryAspectDefs = (typeDef == null) + ? Collections.emptyList() + : typeDef.getDefaultAspects(); // check for (AspectDefinition aspect : mandatoryAspectDefs) @@ -96,6 +99,32 @@ public class AspectsIntegrityEvent extends AbstractIntegrityEvent // next one continue; } + + // Now, each aspect's mandatory aspects have to be checked + for (QName aspectQName : aspects) + { + AspectDefinition aspectDef = dictionaryService.getAspect(aspectQName); + mandatoryAspectDefs = (aspectDef == null) + ? Collections.emptyList() + : aspectDef.getDefaultAspects(); + for (AspectDefinition aspect : mandatoryAspectDefs) + { + if (aspects.contains(aspect.getName())) + { + // it's fine + continue; + } + IntegrityRecord result = new IntegrityRecord( + "Mandatory aspect (aspect-declared) not set: \n" + + " Node: " + nodeRef + "\n" + + " Aspect: " + aspectQName + "\n" + + " Missing: " + aspect.getName()); + eventResults.add(result); + // next one + continue; + } + } + // done } } diff --git a/source/test-java/org/alfresco/repo/coci/CheckOutCheckInServiceImplTest.java b/source/test-java/org/alfresco/repo/coci/CheckOutCheckInServiceImplTest.java index 16d4acef1a..a84d08d2e8 100644 --- a/source/test-java/org/alfresco/repo/coci/CheckOutCheckInServiceImplTest.java +++ b/source/test-java/org/alfresco/repo/coci/CheckOutCheckInServiceImplTest.java @@ -26,14 +26,21 @@ import java.util.List; import java.util.Locale; import java.util.Map; +import net.sf.acegisecurity.AccessDeniedException; + import org.alfresco.model.ContentModel; import org.alfresco.repo.content.MimetypeMap; +import org.alfresco.repo.node.integrity.IntegrityException; import org.alfresco.repo.security.authentication.AuthenticationComponent; import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; import org.alfresco.repo.version.VersionModel; +import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.coci.CheckOutCheckInService; import org.alfresco.service.cmr.lock.LockService; +import org.alfresco.service.cmr.lock.NodeLockedException; +import org.alfresco.service.cmr.model.FileFolderService; import org.alfresco.service.cmr.repository.AssociationRef; import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.ContentData; @@ -41,11 +48,13 @@ import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentService; import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.service.cmr.repository.CopyService; +import org.alfresco.service.cmr.repository.MLText; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.StoreRef; import org.alfresco.service.cmr.security.MutableAuthenticationService; import org.alfresco.service.cmr.security.PermissionService; +import org.alfresco.service.cmr.security.PersonService; import org.alfresco.service.cmr.version.Version; import org.alfresco.service.cmr.version.VersionService; import org.alfresco.service.cmr.version.VersionType; @@ -54,6 +63,7 @@ import org.alfresco.service.namespace.QName; import org.alfresco.service.transaction.TransactionService; import org.alfresco.util.BaseSpringTest; import org.alfresco.util.GUID; +import org.alfresco.util.PropertyMap; import org.alfresco.util.TestWithUserUtils; import org.springframework.extensions.surf.util.I18NUtil; @@ -64,39 +74,41 @@ import org.springframework.extensions.surf.util.I18NUtil; */ public class CheckOutCheckInServiceImplTest extends BaseSpringTest { - /** - * Services used by the tests - */ - private NodeService nodeService; - private CheckOutCheckInService cociService; - private ContentService contentService; - private VersionService versionService; + /** + * Services used by the tests + */ + private NodeService nodeService; + private CheckOutCheckInService cociService; + private ContentService contentService; + private VersionService versionService; private MutableAuthenticationService authenticationService; private LockService lockService; private TransactionService transactionService; private PermissionService permissionService; private CopyService copyService; - + private PersonService personService; + private FileFolderService fileFolderService; + /** - * Data used by the tests - */ - private StoreRef storeRef; - private NodeRef rootNodeRef; - private NodeRef nodeRef; - private String userNodeRef; + * Data used by the tests + */ + private StoreRef storeRef; + private NodeRef rootNodeRef; + private NodeRef nodeRef; + private String userNodeRef; private NodeRef folderNodeRef; private NodeRef fileNodeRef; - - /** - * Types and properties used by the tests - */ - private static final String TEST_VALUE_NAME = "myDocument.doc"; - private static final String TEST_VALUE_2 = "testValue2"; - private static final String TEST_VALUE_3 = "testValue3"; - private static final QName PROP_NAME_QNAME = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "name"); - private static final QName PROP2_QNAME = ContentModel.PROP_DESCRIPTION; - private static final String CONTENT_1 = "This is some content"; - private static final String CONTENT_2 = "This is the cotent modified."; + + /** + * Types and properties used by the tests + */ + private static final String TEST_VALUE_NAME = "myDocument.doc"; + private static final String TEST_VALUE_2 = "testValue2"; + private static final String TEST_VALUE_3 = "testValue3"; + private static final QName PROP_NAME_QNAME = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "name"); + private static final QName PROP2_QNAME = ContentModel.PROP_DESCRIPTION; + private static final String CONTENT_1 = "This is some content"; + private static final String CONTENT_2 = "This is the cotent modified."; /** * User details @@ -104,53 +116,56 @@ public class CheckOutCheckInServiceImplTest extends BaseSpringTest //private static final String USER_NAME = "cociTest" + GUID.generate(); private String userName; private static final String PWD = "password"; - - /** - * On setup in transaction implementation - */ - @Override - protected void onSetUpInTransaction() - throws Exception - { - // Set the services - this.nodeService = (NodeService)this.applicationContext.getBean("nodeService"); - this.cociService = (CheckOutCheckInService)this.applicationContext.getBean("checkOutCheckInService"); - this.contentService = (ContentService)this.applicationContext.getBean("contentService"); - this.versionService = (VersionService)this.applicationContext.getBean("versionService"); + + /** + * On setup in transaction implementation + */ + @Override + protected void onSetUpInTransaction() + throws Exception + { + // Set the services + this.cociService = (CheckOutCheckInService)this.applicationContext.getBean("checkOutCheckInService"); + this.contentService = (ContentService)this.applicationContext.getBean("contentService"); + this.versionService = (VersionService)this.applicationContext.getBean("versionService"); this.authenticationService = (MutableAuthenticationService)this.applicationContext.getBean("authenticationService"); this.lockService = (LockService)this.applicationContext.getBean("lockService"); this.transactionService = (TransactionService)this.applicationContext.getBean("transactionComponent"); this.permissionService = (PermissionService)this.applicationContext.getBean("permissionService"); this.copyService = (CopyService)this.applicationContext.getBean("copyService"); + this.personService = (PersonService) this.applicationContext.getBean("PersonService"); + ServiceRegistry serviceRegistry = (ServiceRegistry) this.applicationContext.getBean("ServiceRegistry"); + this.fileFolderService = serviceRegistry.getFileFolderService(); + this.nodeService = serviceRegistry.getNodeService(); // Authenticate as system to create initial test data set AuthenticationComponent authenticationComponent = (AuthenticationComponent)this.applicationContext.getBean("authenticationComponent"); authenticationComponent.setSystemUserAsCurrentUser(); - - // Create the store and get the root node reference - this.storeRef = nodeService.createStore(StoreRef.PROTOCOL_WORKSPACE, "Test_" + System.currentTimeMillis()); - this.rootNodeRef = nodeService.getRootNode(storeRef); - - // Create the node used for tests - ChildAssociationRef childAssocRef = nodeService.createNode( - rootNodeRef, - ContentModel.ASSOC_CHILDREN, - QName.createQName("test"), - ContentModel.TYPE_CONTENT); - this.nodeRef = childAssocRef.getChildRef(); + + // Create the store and get the root node reference + this.storeRef = nodeService.createStore(StoreRef.PROTOCOL_WORKSPACE, "Test_" + System.currentTimeMillis()); + this.rootNodeRef = nodeService.getRootNode(storeRef); + + // Create the node used for tests + ChildAssociationRef childAssocRef = nodeService.createNode( + rootNodeRef, + ContentModel.ASSOC_CHILDREN, + QName.createQName("test"), + ContentModel.TYPE_CONTENT); + this.nodeRef = childAssocRef.getChildRef(); nodeService.addAspect(this.nodeRef, ContentModel.ASPECT_TITLED, null); nodeService.setProperty(this.nodeRef, ContentModel.PROP_NAME, TEST_VALUE_NAME); nodeService.setProperty(this.nodeRef, PROP2_QNAME, TEST_VALUE_2); - // Add the initial content to the node - ContentWriter contentWriter = this.contentService.getWriter(this.nodeRef, ContentModel.PROP_CONTENT, true); + // Add the initial content to the node + ContentWriter contentWriter = this.contentService.getWriter(this.nodeRef, ContentModel.PROP_CONTENT, true); contentWriter.setMimetype("text/plain"); contentWriter.setEncoding("UTF-8"); - contentWriter.putContent(CONTENT_1); - - // Add the lock and version aspects to the created node - nodeService.addAspect(this.nodeRef, ContentModel.ASPECT_VERSIONABLE, null); - nodeService.addAspect(this.nodeRef, ContentModel.ASPECT_LOCKABLE, null); + contentWriter.putContent(CONTENT_1); + + // Add the lock and version aspects to the created node + nodeService.addAspect(this.nodeRef, ContentModel.ASPECT_VERSIONABLE, null); + nodeService.addAspect(this.nodeRef, ContentModel.ASPECT_LOCKABLE, null); // Create and authenticate the user this.userName = "cociTest" + GUID.generate(); @@ -177,53 +192,53 @@ public class CheckOutCheckInServiceImplTest extends BaseSpringTest contentWriter.setMimetype("text/plain"); contentWriter.setEncoding("UTF-8"); contentWriter.putContent(CONTENT_1); - } - - /** - * Helper method that creates a bag of properties for the test type - * - * @return bag of properties - */ - private Map createTypePropertyBag() - { - Map result = new HashMap(); - result.put(PROP_NAME_QNAME, TEST_VALUE_NAME); - return result; - } - - /** - * Test checkout - */ - public void testCheckOut() - { - checkout(); - } - - /** - * - * @return - */ - private NodeRef checkout() - { - // Check out the node - NodeRef workingCopy = cociService.checkout( - this.nodeRef, - this.rootNodeRef, - ContentModel.ASSOC_CHILDREN, - QName.createQName("workingCopy")); - assertNotNull(workingCopy); - + } + + /** + * Helper method that creates a bag of properties for the test type + * + * @return bag of properties + */ + private Map createTypePropertyBag() + { + Map result = new HashMap(); + result.put(PROP_NAME_QNAME, TEST_VALUE_NAME); + return result; + } + + /** + * Test checkout + */ + public void testCheckOut() + { + checkout(); + } + + /** + * + * @return + */ + private NodeRef checkout() + { + // Check out the node + NodeRef workingCopy = cociService.checkout( + this.nodeRef, + this.rootNodeRef, + ContentModel.ASSOC_CHILDREN, + QName.createQName("workingCopy")); + assertNotNull(workingCopy); + //System.out.println(NodeStoreInspector.dumpNodeStore(this.nodeService, this.storeRef)); - // Ensure that the working copy and copy aspect has been applied - assertTrue(nodeService.hasAspect(workingCopy, ContentModel.ASPECT_WORKING_COPY)); - assertTrue(nodeService.hasAspect(workingCopy, ContentModel.ASPECT_COPIEDFROM)); - - // Check that the working copy owner has been set correctly - assertEquals(this.userNodeRef, nodeService.getProperty(workingCopy, ContentModel.PROP_WORKING_COPY_OWNER)); + // Ensure that the working copy and copy aspect has been applied + assertTrue(nodeService.hasAspect(workingCopy, ContentModel.ASPECT_WORKING_COPY)); + assertTrue(nodeService.hasAspect(workingCopy, ContentModel.ASPECT_COPIEDFROM)); + + // Check that the working copy owner has been set correctly + assertEquals(this.userNodeRef, nodeService.getProperty(workingCopy, ContentModel.PROP_WORKING_COPY_OWNER)); - - // Check that the working copy name has been set correctly + + // Check that the working copy name has been set correctly String name = (String)this.nodeService.getProperty(this.nodeRef, PROP_NAME_QNAME); String expectedWorkingCopyLabel = I18NUtil.getMessage("coci_service.working_copy_label"); String expectedWorkingCopyName = CheckOutCheckInServiceImpl.createWorkingCopyName(name, expectedWorkingCopyLabel); @@ -234,83 +249,83 @@ public class CheckOutCheckInServiceImplTest extends BaseSpringTest "No record of working copy label kept", expectedWorkingCopyLabel, nodeService.getProperty(workingCopy, ContentModel.PROP_WORKING_COPY_LABEL)); - - // Ensure that the content has been copied correctly - ContentReader contentReader = this.contentService.getReader(this.nodeRef, ContentModel.PROP_CONTENT); - assertNotNull(contentReader); - ContentReader contentReader2 = this.contentService.getReader(workingCopy, ContentModel.PROP_CONTENT); - assertNotNull(contentReader2); - assertEquals( - "The content string of the working copy should match the original immediatly after checkout.", - contentReader.getContentString(), - contentReader2.getContentString()); - return workingCopy; - } - - /** - * Test checkIn - */ - public void testCheckIn() - { - NodeRef workingCopy = checkout(); - - // Test standard check-in - Map versionProperties = new HashMap(); - versionProperties.put(Version.PROP_DESCRIPTION, "This is a test version"); - cociService.checkin(workingCopy, versionProperties); - - // Test check-in with content + // Ensure that the content has been copied correctly + ContentReader contentReader = this.contentService.getReader(this.nodeRef, ContentModel.PROP_CONTENT); + assertNotNull(contentReader); + ContentReader contentReader2 = this.contentService.getReader(workingCopy, ContentModel.PROP_CONTENT); + assertNotNull(contentReader2); + assertEquals( + "The content string of the working copy should match the original immediatly after checkout.", + contentReader.getContentString(), + contentReader2.getContentString()); + + return workingCopy; + } + + /** + * Test checkIn + */ + public void testCheckIn() + { + NodeRef workingCopy = checkout(); + + // Test standard check-in + Map versionProperties = new HashMap(); + versionProperties.put(Version.PROP_DESCRIPTION, "This is a test version"); + cociService.checkin(workingCopy, versionProperties); + + // Test check-in with content NodeRef workingCopy3 = checkout(); - nodeService.setProperty(workingCopy3, PROP_NAME_QNAME, TEST_VALUE_2); - nodeService.setProperty(workingCopy3, PROP2_QNAME, TEST_VALUE_3); + nodeService.setProperty(workingCopy3, PROP_NAME_QNAME, TEST_VALUE_2); + nodeService.setProperty(workingCopy3, PROP2_QNAME, TEST_VALUE_3); ContentWriter tempWriter = this.contentService.getWriter(workingCopy3, ContentModel.PROP_CONTENT, false); - assertNotNull(tempWriter); - tempWriter.putContent(CONTENT_2); - String contentUrl = tempWriter.getContentUrl(); - Map versionProperties3 = new HashMap(); - versionProperties3.put(Version.PROP_DESCRIPTION, "description"); - versionProperties3.put(VersionModel.PROP_VERSION_TYPE, VersionType.MAJOR); - NodeRef origNodeRef = cociService.checkin(workingCopy3, versionProperties3, contentUrl, true); - assertNotNull(origNodeRef); - - // Check the checked in content - ContentReader contentReader = this.contentService.getReader(origNodeRef, ContentModel.PROP_CONTENT); - assertNotNull(contentReader); - assertEquals(CONTENT_2, contentReader.getContentString()); - - // Check that the version history is correct - Version version = this.versionService.getCurrentVersion(origNodeRef); - assertNotNull(version); - assertEquals("description", version.getDescription()); - assertEquals(VersionType.MAJOR, version.getVersionType()); - NodeRef versionNodeRef = version.getFrozenStateNodeRef(); - assertNotNull(versionNodeRef); - - // Check the verioned content - ContentReader versionContentReader = this.contentService.getReader(versionNodeRef, ContentModel.PROP_CONTENT); - assertNotNull(versionContentReader); + assertNotNull(tempWriter); + tempWriter.putContent(CONTENT_2); + String contentUrl = tempWriter.getContentUrl(); + Map versionProperties3 = new HashMap(); + versionProperties3.put(Version.PROP_DESCRIPTION, "description"); + versionProperties3.put(VersionModel.PROP_VERSION_TYPE, VersionType.MAJOR); + NodeRef origNodeRef = cociService.checkin(workingCopy3, versionProperties3, contentUrl, true); + assertNotNull(origNodeRef); + + // Check the checked in content + ContentReader contentReader = this.contentService.getReader(origNodeRef, ContentModel.PROP_CONTENT); + assertNotNull(contentReader); + assertEquals(CONTENT_2, contentReader.getContentString()); + + // Check that the version history is correct + Version version = this.versionService.getCurrentVersion(origNodeRef); + assertNotNull(version); + assertEquals("description", version.getDescription()); + assertEquals(VersionType.MAJOR, version.getVersionType()); + NodeRef versionNodeRef = version.getFrozenStateNodeRef(); + assertNotNull(versionNodeRef); + + // Check the verioned content + ContentReader versionContentReader = this.contentService.getReader(versionNodeRef, ContentModel.PROP_CONTENT); + assertNotNull(versionContentReader); assertEquals(CONTENT_2, versionContentReader.getContentString()); - - // Check that the name is not updated during the check-in - assertEquals(TEST_VALUE_2, nodeService.getProperty(versionNodeRef, PROP_NAME_QNAME)); - assertEquals(TEST_VALUE_2, nodeService.getProperty(origNodeRef, PROP_NAME_QNAME)); - - // Check that the other properties are updated during the check-in - assertEquals(TEST_VALUE_3, nodeService.getProperty(versionNodeRef, PROP2_QNAME)); - assertEquals(TEST_VALUE_3, nodeService.getProperty(origNodeRef, PROP2_QNAME)); - - // Cancel the check out after is has been left checked out - cociService.cancelCheckout(workingCopy3); - - // Test keep checked out flag - NodeRef workingCopy2 = checkout(); - Map versionProperties2 = new HashMap(); - versionProperties2.put(Version.PROP_DESCRIPTION, "Another version test"); - this.cociService.checkin(workingCopy2, versionProperties2, null, true); - this.cociService.checkin(workingCopy2, new HashMap(), null, true); - } + + // Check that the name is not updated during the check-in + assertEquals(TEST_VALUE_2, nodeService.getProperty(versionNodeRef, PROP_NAME_QNAME)); + assertEquals(TEST_VALUE_2, nodeService.getProperty(origNodeRef, PROP_NAME_QNAME)); + + // Check that the other properties are updated during the check-in + assertEquals(TEST_VALUE_3, nodeService.getProperty(versionNodeRef, PROP2_QNAME)); + assertEquals(TEST_VALUE_3, nodeService.getProperty(origNodeRef, PROP2_QNAME)); + + // Cancel the check out after is has been left checked out + cociService.cancelCheckout(workingCopy3); + + // Test keep checked out flag + NodeRef workingCopy2 = checkout(); + Map versionProperties2 = new HashMap(); + versionProperties2.put(Version.PROP_DESCRIPTION, "Another version test"); + this.cociService.checkin(workingCopy2, versionProperties2, null, true); + this.cociService.checkin(workingCopy2, new HashMap(), null, true); + } public void testCheckInVersionedNode_MNT_8789() { @@ -451,10 +466,10 @@ public class CheckOutCheckInServiceImplTest extends BaseSpringTest assertEquals("cm:modified should not change on the copied node when deleting the original", wcModBefore, wcModAfter); } - public void testCheckOutCheckInWithDifferentLocales() - { - // Check-out nodeRef using the locale fr_FR - Locale.setDefault(Locale.FRANCE); + public void testCheckOutCheckInWithDifferentLocales() + { + // Check-out nodeRef using the locale fr_FR + Locale.setDefault(Locale.FRANCE); NodeRef workingCopy = this.cociService.checkout( this.nodeRef, this.rootNodeRef, @@ -474,9 +489,9 @@ public class CheckOutCheckInServiceImplTest extends BaseSpringTest String name = (String) nodeService.getProperty(nodeRef, PROP_NAME_QNAME); assertEquals("Working copy label was not removed.", "myDocument.doc", name); - } - - public void testCheckOutCheckInWithAlteredWorkingCopyName() + } + + public void testCheckOutCheckInWithAlteredWorkingCopyName() { // Check-out nodeRef using the locale fr_FR Locale.setDefault(Locale.FRANCE); @@ -503,7 +518,7 @@ public class CheckOutCheckInServiceImplTest extends BaseSpringTest String name = (String) nodeService.getProperty(nodeRef, PROP_NAME_QNAME); assertEquals("File not renamed correctly.", "newName.doc", name); } - + public void testCheckInWithNameChange() { // Check out the file @@ -519,65 +534,65 @@ public class CheckOutCheckInServiceImplTest extends BaseSpringTest cociService.checkin(fileWorkingCopyNodeRef, null); } - public void testCheckOutCheckInWithTranslatableAspect() - { - // Create a node to be used as the translation - NodeRef translationNodeRef = nodeService.createNode( - rootNodeRef, - ContentModel.ASSOC_CHILDREN, - QName.createQName("translation"), - ContentModel.TYPE_CONTENT).getChildRef(); - - nodeService.addAspect(this.nodeRef, QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "translatable"), null); - nodeService.createAssociation(this.nodeRef, translationNodeRef, QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "translations")); - - // Check it out - NodeRef workingCopy = cociService.checkout( - this.nodeRef, - this.rootNodeRef, - ContentModel.ASSOC_CHILDREN, - QName.createQName("workingCopy")); - - - // Check it back in again - Map versionProperties = new HashMap(); - versionProperties.put(Version.PROP_DESCRIPTION, "This is a test version"); - cociService.checkin(workingCopy, versionProperties); - } - - /** - * Test when the aspect is not set when check-in is performed - */ - public void testVersionAspectNotSetOnCheckIn() - { - // Create a bag of props + public void testCheckOutCheckInWithTranslatableAspect() + { + // Create a node to be used as the translation + NodeRef translationNodeRef = nodeService.createNode( + rootNodeRef, + ContentModel.ASSOC_CHILDREN, + QName.createQName("translation"), + ContentModel.TYPE_CONTENT).getChildRef(); + + nodeService.addAspect(this.nodeRef, QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "translatable"), null); + nodeService.createAssociation(this.nodeRef, translationNodeRef, QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "translations")); + + // Check it out + NodeRef workingCopy = cociService.checkout( + this.nodeRef, + this.rootNodeRef, + ContentModel.ASSOC_CHILDREN, + QName.createQName("workingCopy")); + + + // Check it back in again + Map versionProperties = new HashMap(); + versionProperties.put(Version.PROP_DESCRIPTION, "This is a test version"); + cociService.checkin(workingCopy, versionProperties); + } + + /** + * Test when the aspect is not set when check-in is performed + */ + public void testVersionAspectNotSetOnCheckIn() + { + // Create a bag of props Map bagOfProps = createTypePropertyBag(); bagOfProps.put(ContentModel.PROP_CONTENT, new ContentData(null, MimetypeMap.MIMETYPE_TEXT_PLAIN, 0L, "UTF-8")); - // Create a new node - ChildAssociationRef childAssocRef = nodeService.createNode( - rootNodeRef, - ContentModel.ASSOC_CHILDREN, - QName.createQName("test"), - ContentModel.TYPE_CONTENT, - bagOfProps); - NodeRef noVersionNodeRef = childAssocRef.getChildRef(); - - // Check out and check in - NodeRef workingCopy = cociService.checkout(noVersionNodeRef); - cociService.checkin(workingCopy, new HashMap()); - - // Check that the origional node has no version history dispite sending verion props - assertNull(this.versionService.getVersionHistory(noVersionNodeRef)); - } - - /** - * Test cancel checkOut - */ - public void testCancelCheckOut() - { - NodeRef workingCopy = checkout(); - assertNotNull(workingCopy); + // Create a new node + ChildAssociationRef childAssocRef = nodeService.createNode( + rootNodeRef, + ContentModel.ASSOC_CHILDREN, + QName.createQName("test"), + ContentModel.TYPE_CONTENT, + bagOfProps); + NodeRef noVersionNodeRef = childAssocRef.getChildRef(); + + // Check out and check in + NodeRef workingCopy = cociService.checkout(noVersionNodeRef); + cociService.checkin(workingCopy, new HashMap()); + + // Check that the origional node has no version history dispite sending verion props + assertNull(this.versionService.getVersionHistory(noVersionNodeRef)); + } + + /** + * Test cancel checkOut + */ + public void testCancelCheckOut() + { + NodeRef workingCopy = checkout(); + assertNotNull(workingCopy); try { @@ -588,20 +603,20 @@ public class CheckOutCheckInServiceImplTest extends BaseSpringTest { // Good the origional is locked } - - NodeRef origNodeRef = cociService.cancelCheckout(workingCopy); - assertEquals(this.nodeRef, origNodeRef); - // The origional should no longer be locked + NodeRef origNodeRef = cociService.cancelCheckout(workingCopy); + assertEquals(this.nodeRef, origNodeRef); + + // The origional should no longer be locked this.lockService.checkForLock(origNodeRef); - } + } /** * Test the deleting a wokring copy node removed the lock on the original node */ public void testAutoCancelCheckOut() { - Date modifiedDateBeforeCheckOut = (Date) this.nodeService.getProperty(this.nodeRef, ContentModel.PROP_MODIFIED); + Date modifiedDateBeforeCheckOut = (Date) this.nodeService.getProperty(this.nodeRef, ContentModel.PROP_MODIFIED); NodeRef workingCopy = checkout(); assertNotNull(workingCopy); @@ -730,28 +745,28 @@ public class CheckOutCheckInServiceImplTest extends BaseSpringTest public void testAR1056() { - // Check out the node - NodeRef workingCopy = cociService.checkout( - this.nodeRef, - this.rootNodeRef, - ContentModel.ASSOC_CHILDREN, - QName.createQName("workingCopy")); - assertNotNull(workingCopy); - - // Try and check the same node out again - try - { - cociService.checkout( - this.nodeRef, - this.rootNodeRef, - ContentModel.ASSOC_CHILDREN, - QName.createQName("workingCopy2")); - fail("This document has been checked out twice."); - } - catch (Exception exception) - { - // Good because we shouldn't be able to checkout a document twice - } + // Check out the node + NodeRef workingCopy = cociService.checkout( + this.nodeRef, + this.rootNodeRef, + ContentModel.ASSOC_CHILDREN, + QName.createQName("workingCopy")); + assertNotNull(workingCopy); + + // Try and check the same node out again + try + { + cociService.checkout( + this.nodeRef, + this.rootNodeRef, + ContentModel.ASSOC_CHILDREN, + QName.createQName("workingCopy2")); + fail("This document has been checked out twice."); + } + catch (Exception exception) + { + // Good because we shouldn't be able to checkout a document twice + } } public void testMultipleCheckoutsCheckInsWithPropChange() @@ -1051,4 +1066,371 @@ public class CheckOutCheckInServiceImplTest extends BaseSpringTest return node; } + /** + * MNT-2641 + *

+ * Creating a document and working copy. Then try to move working copy to another place. Test is passed, if a working copy was moved to another place with original + * document. Only the lock owner can move documents. + */ + public void testMoveOriginalWithWorkingCopy() + { + // Create a FolderA + final NodeRef folderA = createFolder("MoveOriginalWithWorkingCopy_" + GUID.generate()); + + // Create a FolderB + final NodeRef folderB = createFolder("MoveOriginalWithWorkingCopy_" + GUID.generate()); + + // Create content in FolderA, that allowed to move for current user + NodeRef origAllowed = createContent("original_" + GUID.generate(), folderA); + + // Check out the document, that allowed to move for current user + NodeRef workingCopyAllowed = this.cociService.checkout(origAllowed); + assertNotNull(workingCopyAllowed); + + // Create content in FolderA, that doesn't allowed to move for other users + final NodeRef origDenied = createContent("original_" + GUID.generate(), folderA); + + // Check out the document, that doesn't allowed to move for other users + final NodeRef workingCopyDenied = this.cociService.checkout(origDenied); + assertNotNull(workingCopyDenied); + + // Move working copy to folderB + NodeRef movedWorkingCopyAllowed = null; + try + { + movedWorkingCopyAllowed = fileFolderService.moveFrom(workingCopyAllowed, folderA, folderB, null).getNodeRef(); + } + catch (Exception e) + { + // do nothing. Assert condition checks it further + } + + assertNotNull(movedWorkingCopyAllowed); + + // check a parent of moved working copy - it must be folderB + assertEquals(folderB, nodeService.getPrimaryParent(movedWorkingCopyAllowed).getParentRef()); + + boolean thrown = false; + + // check a parent of original document - it must be folderA + assertEquals(folderA, nodeService.getPrimaryParent(origAllowed).getParentRef()); + + // try to move original - action must be denied + try + { + fileFolderService.moveFrom(origAllowed, folderA, folderB, null).getNodeRef(); + } + catch (NodeLockedException e1) + { + thrown = true; + } + catch (Exception e) + { + // do nothing. Assert condition checks it further + } + assertTrue(thrown); + + //////////////////////////////////////////////// + // testing "move" actions with non-owner user // + //////////////////////////////////////////////// + + // create another person + final String denyUser = "COCITestUser123"; + createPerson(denyUser); + + // try to move a working copy. User hasn't permissions to move + thrown = false; + try + { + AuthenticationUtil.runAs(new RunAsWork() + { + @Override + public NodeRef doWork() throws Exception + { + return fileFolderService.moveFrom(workingCopyDenied, folderA, folderB, null).getNodeRef(); + } + }, denyUser); + } + catch (AccessDeniedException e) + { + thrown = true; + } + catch (org.alfresco.repo.security.permissions.AccessDeniedException e) + { + thrown = true; + } + assertTrue(thrown); + + //try to move a original file. User hasn't permissions to move + thrown = false; + try + { + AuthenticationUtil.runAs(new RunAsWork() + { + @Override + public NodeRef doWork() throws Exception + { + return fileFolderService.moveFrom(origDenied, folderA, folderB, null).getNodeRef(); + } + }, denyUser); + } + catch (AccessDeniedException e) + { + thrown = true; + } + catch (org.alfresco.repo.security.permissions.AccessDeniedException e) + { + thrown = true; + } + assertTrue(thrown); + } + + /** + * MNT-2641 + *

+ * Original cannot be deleted while it is checked out. No one should be able to delete or update the original. + */ + public void testDeleteUpdateOriginalOfCheckedOutDocument() + { + // Create a FolderA + final NodeRef folderA = createFolder("DeleteUpdateOriginalOfCheckedOutDocument_" + GUID.generate()); + + // Create content in FolderA + final NodeRef orig = createContent("original_" + GUID.generate(), folderA); + + // Check out the document + NodeRef workingCopy = this.cociService.checkout(orig); + assertNotNull(workingCopy); + + boolean thrown = false; + + // try to delete original, that has working copy - must be denied + try + { + fileFolderService.delete(orig); + } + catch (NodeLockedException e) + { + thrown = true; + } + assertTrue("No one should be able to delete the original", thrown); + + // creating a properties + final Map propsToPersist = new HashMap(3); + MLText value = new MLText(Locale.ENGLISH, GUID.generate() + ""); + propsToPersist.put(ContentModel.PROP_DESCRIPTION, value); + value = new MLText(Locale.ENGLISH, null); + propsToPersist.put(ContentModel.PROP_TITLE, value); + + // try to modify properties of original, that has working copy - must be denied + thrown = false; + try + { + nodeService.addProperties(orig, propsToPersist); + } + catch (NodeLockedException e) + { + thrown = true; + } + assertTrue("No one should be able to update the original", thrown); + + // //////////////////////////////////////////////////////////// + // testing "delete" and "update" actions with non-owner user // + // //////////////////////////////////////////////////////////// + + // create another person + final String denyUser = "COCITestUser123"; + createPerson(denyUser); + + // try to delete original, that has working copy - must be denied + thrown = false; + try + { + AuthenticationUtil.runAs(new RunAsWork() + { + @Override + public NodeRef doWork() throws Exception + { + fileFolderService.delete(orig); + return null; + } + }, denyUser); + } + catch (AccessDeniedException e) + { + thrown = true; + } + catch (org.alfresco.repo.security.permissions.AccessDeniedException e) + { + thrown = true; + } + assertTrue(thrown); + + // try to delete original, that has working copy - must be denied + thrown = false; + try + { + AuthenticationUtil.runAs(new RunAsWork() + { + @Override + public Void doWork() throws Exception + { + nodeService.addProperties(orig, propsToPersist); + return null; + } + }, denyUser); + } + catch (AccessDeniedException e) + { + thrown = true; + } + catch (org.alfresco.repo.security.permissions.AccessDeniedException e) + { + thrown = true; + } + catch (NodeLockedException e) { + thrown = true; + } + assertTrue(thrown); + } + + /** + * MNT-2641 + * The working copy delete is equivalent to "cancelCheckout". This should fail for everyone except the lock owner. + */ + public void testDeleteOfWorkingCopy() + { + // Create a FolderA + final NodeRef folderA = createFolder("DeleteOfWorkingCopy_" + GUID.generate()); + + // Create content in FolderA + final NodeRef orig = createContent("original_" + GUID.generate(), folderA); + + // Check out the document + NodeRef workingCopy = this.cociService.checkout(orig); + assertNotNull(workingCopy); + + // deleting of working copy + fileFolderService.delete(workingCopy); + assertFalse(nodeService.exists(workingCopy)); + + assertNull(cociService.getWorkingCopy(orig)); + assertFalse(cociService.isCheckedOut(orig)); + } + + /** + * MNT-2641: The {@link ContentModel#ASPECT_WORKING_COPY} aspect cannot be removed from a working copy + */ + public void testDeleteWorkingCopyAspect() + { + // Create a FolderA + final NodeRef folderA = createFolder("DeleteCopiedFromAspectFromWorkingCopy_" + GUID.generate()); + + // Create content in FolderA + final NodeRef orig = createContent("original_" + GUID.generate(), folderA); + + // Check out the document + NodeRef workingCopy = this.cociService.checkout(orig); + assertNotNull(workingCopy); + + assertTrue("cm:workingCopy aspect not found on working copy.", + nodeService.hasAspect(workingCopy, ContentModel.ASPECT_WORKING_COPY)); + assertTrue("cm:copiedFrom aspect not found on working copy.", + nodeService.hasAspect(workingCopy, ContentModel.ASPECT_COPIEDFROM)); + + setComplete(); + endTransaction(); + + // try to delete cm:copiedfrom aspect from working copy - must be allowed + nodeService.removeAspect(workingCopy, ContentModel.ASPECT_COPIEDFROM); + // Try to delete cm:workingcopy aspect from working copy - must be denied + try + { + nodeService.removeAspect(workingCopy, ContentModel.ASPECT_WORKING_COPY); + fail("Should not be able to remove cm:workingcopy"); + } + catch (UnsupportedOperationException e) + { + // Expected + } + } + + /** + * MNT-2641 The cm:workingcopylink association cannot be removed + */ + public void testDeleteWorkingCopyLinkAssociation() + { + // Create a FolderA + final NodeRef folderA = createFolder("DeleteOriginalAssociationFromCopy_" + GUID.generate()); + + // Create content in FolderA + final NodeRef orig = createContent("original_" + GUID.generate(), folderA); + + // Check out the document + NodeRef workingCopy = this.cociService.checkout(orig); + assertNotNull(workingCopy); + + // Check that the cm:original association is present + assertEquals("Did not find cm:workingcopylink", + 1, nodeService.getSourceAssocs(workingCopy, ContentModel.ASSOC_WORKING_COPY_LINK).size()); + + setComplete(); + endTransaction(); + + // try to delete cm:workingcopylink association - must be denied + try + { + nodeService.removeAssociation(orig, workingCopy, ContentModel.ASSOC_WORKING_COPY_LINK); + fail("Should not have been allowed to remove the association from working copy to original"); + } + catch (IntegrityException e) + { + // Expected + } + } + + private NodeRef createFolder(String fName) + { + return nodeService.createNode(rootNodeRef, ContentModel.ASSOC_CHILDREN, QName.createQName(fName), ContentModel.TYPE_FOLDER).getChildRef(); + } + + private NodeRef createContent(String contentName, NodeRef parentRef) + { + return nodeService.createNode(parentRef, ContentModel.ASSOC_CONTAINS, QName.createQName(contentName), ContentModel.TYPE_CONTENT).getChildRef(); + } + + private void createPerson(String userName) + { + // if user with given user name doesn't already exist then create user + if (this.authenticationService.authenticationExists(userName) == false) + { + // create user + this.authenticationService.createAuthentication(userName, "password".toCharArray()); + } + + // if person node with given user name doesn't already exist then create + // person + if (this.personService.personExists(userName) == false) + { + // create person properties + final PropertyMap personProps = new PropertyMap(); + personProps.put(ContentModel.PROP_USERNAME, userName); + personProps.put(ContentModel.PROP_FIRSTNAME, userName); + personProps.put(ContentModel.PROP_LASTNAME, userName); + personProps.put(ContentModel.PROP_EMAIL, userName + "@gmail.com"); + personProps.put(ContentModel.PROP_JOBTITLE, "jobtitle"); + personProps.put(ContentModel.PROP_ORGANIZATION, "org"); + + // create person node for user + AuthenticationUtil.runAsSystem(new RunAsWork() + { + @Override + public NodeRef doWork() throws Exception + { + return personService.createPerson(personProps); + } + }); + } + } + } diff --git a/source/test-java/org/alfresco/repo/node/integrity/IntegrityTest.java b/source/test-java/org/alfresco/repo/node/integrity/IntegrityTest.java index a9fe9bc6e0..b43ae20b84 100644 --- a/source/test-java/org/alfresco/repo/node/integrity/IntegrityTest.java +++ b/source/test-java/org/alfresco/repo/node/integrity/IntegrityTest.java @@ -80,6 +80,7 @@ public class IntegrityTest extends TestCase public static final QName TEST_ASPECT_WITH_PROPERTIES = QName.createQName(NAMESPACE, "aspectWithProperties"); public static final QName TEST_ASPECT_WITH_ASSOC = QName.createQName(NAMESPACE, "aspectWithAssoc"); + public static final QName TEST_ASPECT_WITH_ASPECT = QName.createQName(NAMESPACE, "aspectWithAspect"); public static final QName TEST_PROP_TEXT_A = QName.createQName(NAMESPACE, "prop-text-a"); public static final QName TEST_PROP_TEXT_B = QName.createQName(NAMESPACE, "prop-text-b"); @@ -289,6 +290,19 @@ public class IntegrityTest extends TestCase checkIntegrityExpectFailure("Failed to removal of mandatory aspect", 1); } + public void testCreateWithAspectForAspect() throws Exception + { + NodeRef nodeRef = createNode("abc", TEST_TYPE_WITHOUT_ANYTHING, null); + // Add the aspect + nodeService.addAspect(nodeRef, TEST_ASPECT_WITH_ASPECT, allProperties); + assertTrue("Mandatory aspect missing", nodeService.hasAspect(nodeRef, TEST_ASPECT_WITH_PROPERTIES)); + checkIntegrityNoFailure(); + + // Remove the implied mandatory aspect + nodeService.removeAspect(nodeRef, TEST_ASPECT_WITH_PROPERTIES); + checkIntegrityExpectFailure("Failed to detect missing aspect for aspect", 1); + } + public void testCreateTargetOfAssocsWithMandatorySourcesPresent() throws Exception { // this is the target of 3 assoc types where the source cardinality is 1..1 @@ -383,35 +397,29 @@ public class IntegrityTest extends TestCase checkIntegrityExpectFailure("Failed to detect missing assoc targets", 3); } - /** - * TODO: Reactivate once cascade delete notifications are back on - *

- * Does nothing. - */ public void testRemoveTargetsOfMandatoryAssocs() throws Exception { -// NodeRef source = createNode("abc", TEST_TYPE_WITH_ASSOCS, null); -// NodeRef target = createNode("target", TEST_TYPE_WITHOUT_ANYTHING, null); -// nodeService.createAssociation(source, target, TEST_ASSOC_NODE_ONE_ONE); -// -// NodeRef parent = createNode("parent", TEST_TYPE_WITH_CHILD_ASSOCS, null); -// NodeRef child = createNode("child", TEST_TYPE_WITHOUT_ANYTHING, null); -// nodeService.addChild(parent, child, TEST_ASSOC_CHILD_ONE_ONE, QName.createQName(NAMESPACE, "one-to-one")); -// -// NodeRef aspectSource = createNode("aspectSource", TEST_TYPE_WITHOUT_ANYTHING, null); -// nodeService.addAspect(aspectSource, TEST_ASPECT_WITH_ASSOC, null); -// NodeRef aspectTarget = createNode("aspectTarget", TEST_TYPE_WITHOUT_ANYTHING, null); -// nodeService.createAssociation(aspectSource, aspectTarget, TEST_ASSOC_ASPECT_ONE_ONE); -// -// checkIntegrityNoFailure(); -// -// // remove target nodes -// nodeService.deleteNode(target); -// nodeService.deleteNode(child); -// nodeService.deleteNode(aspectTarget); -// -// checkIntegrityExpectFailure("Failed to detect removal of mandatory assoc targets", 3); - logger.error("Method commented out: testRemoveTargetsOfMandatoryAssocs"); + NodeRef source = createNode("abc", TEST_TYPE_WITH_ASSOCS, null); + NodeRef target = createNode("target", TEST_TYPE_WITHOUT_ANYTHING, null); + nodeService.createAssociation(source, target, TEST_ASSOC_NODE_ONE_ONE); + + NodeRef parent = createNode("parent", TEST_TYPE_WITH_CHILD_ASSOCS, null); + NodeRef child = createNode("child", TEST_TYPE_WITHOUT_ANYTHING, null); + nodeService.addChild(parent, child, TEST_ASSOC_CHILD_ONE_ONE, QName.createQName(NAMESPACE, "one-to-one")); + + NodeRef aspectSource = createNode("aspectSource", TEST_TYPE_WITHOUT_ANYTHING, null); + nodeService.addAspect(aspectSource, TEST_ASPECT_WITH_ASSOC, null); + NodeRef aspectTarget = createNode("aspectTarget", TEST_TYPE_WITHOUT_ANYTHING, null); + nodeService.createAssociation(aspectSource, aspectTarget, TEST_ASSOC_ASPECT_ONE_ONE); + + checkIntegrityNoFailure(); + + // remove target nodes + nodeService.deleteNode(target); + nodeService.deleteNode(child); + nodeService.deleteNode(aspectTarget); + + checkIntegrityExpectFailure("Failed to detect removal of mandatory assoc targets", 3); } public void testExcessTargetsOfOneToOneAssocs() throws Exception diff --git a/source/test-resources/org/alfresco/repo/node/integrity/IntegrityTest_model.xml b/source/test-resources/org/alfresco/repo/node/integrity/IntegrityTest_model.xml index 8fc1ece87c..508069ac7d 100644 --- a/source/test-resources/org/alfresco/repo/node/integrity/IntegrityTest_model.xml +++ b/source/test-resources/org/alfresco/repo/node/integrity/IntegrityTest_model.xml @@ -191,6 +191,13 @@ + + + Aspect with aspects + + test:aspectWithProperties + +