diff --git a/config/alfresco/application-context-core.xml b/config/alfresco/application-context-core.xml index 80a4795bbe..1589b5c05f 100644 --- a/config/alfresco/application-context-core.xml +++ b/config/alfresco/application-context-core.xml @@ -25,7 +25,6 @@ - diff --git a/config/alfresco/bootstrap-context.xml b/config/alfresco/bootstrap-context.xml index 4ffb89842b..30224b04f3 100644 --- a/config/alfresco/bootstrap-context.xml +++ b/config/alfresco/bootstrap-context.xml @@ -42,6 +42,12 @@ + + + + + + @@ -469,8 +475,8 @@ - - + + @@ -750,6 +756,12 @@ + + + + + + diff --git a/config/alfresco/cmis-api-context.xml b/config/alfresco/cmis-api-context.xml index 6b355448cc..f996aabf7d 100644 --- a/config/alfresco/cmis-api-context.xml +++ b/config/alfresco/cmis-api-context.xml @@ -57,22 +57,18 @@ - - - - - - - - - - - - - - - - + + + + + + search.CMISQueryService + + + + org.alfresco.cmis.CMISQueryService + + @@ -141,58 +137,5 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - org.alfresco.repo.search.impl.querymodel.QueryEngine - - - - - - - - - - - - - - - - - - org.alfresco.repo.search.impl.querymodel.QueryEngine.executeQuery=ACL_ALLOW,AFTER_ACL_NODE.sys:base.Read - org.alfresco.repo.search.impl.querymodel.QueryEngine.getQueryModelFactory=ACL_ALLOW - - - \ No newline at end of file diff --git a/config/alfresco/core-services-context.xml b/config/alfresco/core-services-context.xml index 1283b70848..66a8b5e04a 100644 --- a/config/alfresco/core-services-context.xml +++ b/config/alfresco/core-services-context.xml @@ -503,454 +503,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - org.alfresco.repo.search.impl.lucene.LuceneIndexerAndSearcher - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - org.alfresco.service.cmr.search.CategoryService - - - - - - - - - - - - - - - - - - - - - - indexThread - - - 10 - - - 20 - - - 5 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ${dir.indexes} - - - ${dir.indexes.lock} - - - ${lucene.maxAtomicTransformationTime} - - - ${lucene.query.maxClauses} - - - ${lucene.indexer.batchSize} - - - - ${lucene.indexer.cacheEnabled} - - - ${lucene.indexer.maxDocIdCacheSize} - - - ${lucene.indexer.maxDocumentCacheSize} - - - ${lucene.indexer.maxIsCategoryCacheSize} - - - ${lucene.indexer.maxLinkAspectCacheSize} - - - ${lucene.indexer.maxParentCacheSize} - - - ${lucene.indexer.maxPathCacheSize} - - - ${lucene.indexer.maxTypeCacheSize} - - - - ${lucene.indexer.mergerMaxMergeDocs} - - - ${lucene.indexer.mergerMergeFactor} - - - ${lucene.indexer.mergerMaxBufferedDocs} - - - ${lucene.indexer.mergerRamBufferSizeMb} - - - - ${lucene.indexer.writerMaxMergeDocs} - - - ${lucene.indexer.writerMergeFactor} - - - ${lucene.indexer.writerMaxBufferedDocs} - - - ${lucene.indexer.writerRamBufferSizeMb} - - - - ${lucene.indexer.mergerTargetIndexCount} - - - ${lucene.indexer.mergerTargetOverlayCount} - - - ${lucene.indexer.mergerTargetOverlaysBlockingFactor} - - - ${lucene.indexer.maxDocsForInMemoryMerge} - - - ${lucene.indexer.maxRamInMbForInMemoryMerge} - - - ${lucene.indexer.maxDocsForInMemoryIndex} - - - ${lucene.indexer.maxRamInMbForInMemoryIndex} - - - - ${lucene.indexer.termIndexInterval} - - - ${lucene.indexer.useNioMemoryMapping} - - - ${lucene.indexer.postSortDateTime} - - - ${lucene.indexer.defaultMLIndexAnalysisMode} - - - ${lucene.indexer.defaultMLSearchAnalysisMode} - - - ${lucene.indexer.maxFieldLength} - - - ${lucene.indexer.fairLocking} - - - ${lucene.write.lock.timeout} - - - ${lucene.commit.lock.timeout} - - - ${lucene.lock.poll.interval} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1234,19 +786,6 @@ - - - - - - - - - - - - - @@ -1303,70 +842,7 @@ - - - - - org.alfresco.repo.search.impl.lucene.fts.FullTextSearchIndexer - - - - - - - - - - ${server.transaction.mode.default} - - - - - - - - - - ${fts.indexer.batchSize} - - - - - - - - - - - - - - - - - - ${dir.indexes.backup} - - - true - - - - - - - - - - - - - - - - + @@ -1555,4 +1031,311 @@ + + + + + + + + + true + + + Search + + + ${index.subsystem.name} + + + + manager + + + + + + + + false + + + Search + + + solr + + + + managed + solr + + + + + + + false + + + Search + + + lucene + + + + managed + lucene + + + + + + + + + + search.indexerAndSearcherFactory + + + + org.alfresco.repo.search.IndexerAndSearcher + + + + + + + + + + search.admSearchService + + + + org.alfresco.service.cmr.search.SearchService + + + + + + + + + + search.versionSearchService + + + + org.alfresco.service.cmr.search.SearchService + + + + + + + + + + search.searchService + + + + org.alfresco.service.cmr.search.SearchService + + + + + + + + + + search.avmLuceneIndexerAndSearcherFactory + + + + org.alfresco.repo.search.IndexerAndSearcher + org.alfresco.repo.search.impl.lucene.LuceneConfig + + + + + + + + + + search.admLuceneIndexerAndSearcherFactory + + + + org.alfresco.repo.search.IndexerAndSearcher + org.alfresco.repo.search.impl.lucene.LuceneConfig + + + + + + + + + + search.admLuceneUnIndexedIndexerAndSearcherFactory + + + + org.alfresco.repo.search.IndexerAndSearcher + org.alfresco.repo.search.impl.lucene.LuceneConfig + + + + + + + + + + + search.indexerComponent + + + + org.alfresco.repo.search.Indexer + + + + + + + + + + search.queryRegisterComponent + + + + org.alfresco.repo.search.QueryRegisterComponent + + + + + + + + + + search.categoryService + + + + org.alfresco.service.cmr.search.CategoryService + + + + + + + + + + search.indexRecoveryComponent + + + + org.alfresco.repo.node.index.IndexRecovery + + + + + + + + + + search.avmIndexRecoveryComponent + + + + org.alfresco.repo.node.index.IndexRecovery + + + + + + + + + + + + search.LuceneFullTextSearchIndexer + + + + org.alfresco.repo.search.impl.lucene.fts.FullTextSearchIndexer + + + + + + + + + + + search.ftsIndexerTrigger + + + + org.alfresco.util.TriggerBeanSPI + org.springframework.beans.factory.InitializingBean + org.springframework.beans.factory.DisposableBean + + + + + + + + + + search.adm.luceneQueryEngineImpl + + + + org.alfresco.repo.search.impl.querymodel.QueryEngine + + + + + + + + + + search.indexConfigurationChecker + + + + org.alfresco.repo.admin.IndexConfigurationChecker + + + + + + + + + + search.solrTrackingComponent + + + + org.alfresco.repo.solr.SOLRTrackingComponent + + + + diff --git a/config/alfresco/opencmis-context.xml b/config/alfresco/opencmis-context.xml index 82c22fa697..925245c797 100644 --- a/config/alfresco/opencmis-context.xml +++ b/config/alfresco/opencmis-context.xml @@ -80,70 +80,25 @@ - - - - - - - + + + + + + search.OpenCMISQueryService + + + + org.alfresco.opencmis.search.CMISQueryService + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - org.alfresco.repo.search.impl.querymodel.QueryEngine - - - - - - - - - - - - - - - - - - org.alfresco.repo.search.impl.querymodel.QueryEngine.executeQuery=ACL_ALLOW,AFTER_ACL_NODE.sys:base.Read - org.alfresco.repo.search.impl.querymodel.QueryEngine.getQueryModelFactory=ACL_ALLOW - - - + \ No newline at end of file diff --git a/config/alfresco/repository.properties b/config/alfresco/repository.properties index 07c3403825..511f272199 100644 --- a/config/alfresco/repository.properties +++ b/config/alfresco/repository.properties @@ -42,6 +42,8 @@ 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 +index.subsystem.name=lucene + # ######################################### # # Index Recovery and Tracking Configuration # # ######################################### # @@ -281,6 +283,8 @@ lucene.write.lock.timeout=10000 lucene.commit.lock.timeout=100000 lucene.lock.poll.interval=100 +index.backup.cronExpression=0 0 3 * * ? + lucene.defaultAnalyserResourceBundleName=alfresco/model/dataTypeAnalyzers diff --git a/config/alfresco/scheduled-jobs-context.xml b/config/alfresco/scheduled-jobs-context.xml index 6286ef1e32..bc7f17c39f 100644 --- a/config/alfresco/scheduled-jobs-context.xml +++ b/config/alfresco/scheduled-jobs-context.xml @@ -6,60 +6,8 @@ - - - - - org.alfresco.repo.search.impl.lucene.fts.FTSIndexerJob - - - - - - - - - - - - - - - 1 - - - 1 - - - - + @@ -157,31 +105,6 @@ - - - org.alfresco.repo.search.impl.lucene.AbstractLuceneIndexerAndSearcherFactory$LuceneIndexBackupJob - - - - - - - - - - - - - - - - - - - 0 0 3 * * ? - - - diff --git a/config/alfresco/subsystems/Search/common-search-context.xml b/config/alfresco/subsystems/Search/common-search-context.xml new file mode 100644 index 0000000000..6ea9820784 --- /dev/null +++ b/config/alfresco/subsystems/Search/common-search-context.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + ${search.solrTrackingSupport.enabled} + + + + + + + + + + + + + + + + diff --git a/config/alfresco/subsystems/Search/lucene/bootstrap-context.xml b/config/alfresco/subsystems/Search/lucene/bootstrap-context.xml new file mode 100644 index 0000000000..032914b4c3 --- /dev/null +++ b/config/alfresco/subsystems/Search/lucene/bootstrap-context.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ${system.bootstrap.config_check.strict} + + + ${dir.root} + + + + + + + + + + + + + + diff --git a/config/alfresco/subsystems/Search/lucene/cmis-api-context.xml b/config/alfresco/subsystems/Search/lucene/cmis-api-context.xml new file mode 100644 index 0000000000..1265517017 --- /dev/null +++ b/config/alfresco/subsystems/Search/lucene/cmis-api-context.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + org.alfresco.repo.search.impl.querymodel.QueryEngine + + + + + + + + + + + + + + + + + + org.alfresco.repo.search.impl.querymodel.QueryEngine.executeQuery=ACL_ALLOW,AFTER_ACL_NODE.sys:base.Read + org.alfresco.repo.search.impl.querymodel.QueryEngine.getQueryModelFactory=ACL_ALLOW + + + + + \ No newline at end of file diff --git a/config/alfresco/subsystems/Search/lucene/common-search.properties b/config/alfresco/subsystems/Search/lucene/common-search.properties new file mode 100644 index 0000000000..d315f426f9 --- /dev/null +++ b/config/alfresco/subsystems/Search/lucene/common-search.properties @@ -0,0 +1,2 @@ +search.solrTrackingSupport.enabled=true + diff --git a/config/alfresco/index-recovery-context.xml b/config/alfresco/subsystems/Search/lucene/index-recovery-context.xml similarity index 84% rename from config/alfresco/index-recovery-context.xml rename to config/alfresco/subsystems/Search/lucene/index-recovery-context.xml index d95f8d23af..93090f8718 100644 --- a/config/alfresco/index-recovery-context.xml +++ b/config/alfresco/subsystems/Search/lucene/index-recovery-context.xml @@ -6,7 +6,7 @@ - + indexTrackerThread @@ -21,21 +21,21 @@ - + - + - + - + - + @@ -61,9 +61,9 @@ + parent="search.indexRecoveryComponentBase"> ${index.recovery.mode} @@ -74,14 +74,14 @@ ${index.tracking.maxTransactionsPerLuceneCommit} - + + parent="search.indexRecoveryComponentBase"> ${index.recovery.mode} @@ -100,9 +100,9 @@ is required. --> + parent="search.indexRecoveryComponentBase"> @@ -124,7 +124,7 @@ - + @@ -133,7 +133,7 @@ - + ${alfresco.cluster.name} @@ -155,9 +155,9 @@ + parent="search.indexRecoveryComponentBase"> @@ -167,7 +167,7 @@ - + @@ -176,7 +176,7 @@ - + ${alfresco.cluster.name} @@ -201,16 +201,16 @@ nint: Not Indexed No Transformation --> + parent="search.indexRecoveryComponentBase"> - + @@ -219,7 +219,7 @@ - + ${alfresco.cluster.name} diff --git a/config/alfresco/subsystems/Search/lucene/index-recovery.properties b/config/alfresco/subsystems/Search/lucene/index-recovery.properties new file mode 100644 index 0000000000..3ce098e56e --- /dev/null +++ b/config/alfresco/subsystems/Search/lucene/index-recovery.properties @@ -0,0 +1,11 @@ +index.recovery.maximumPoolSize=5 +index.recovery.mode=VALIDATE +index.recovery.stopOnError=false +index.tracking.maxTransactionsPerLuceneCommit=100 +index.tracking.maxTxnDurationMinutes=10 +index.tracking.reindexLagMs=1000 +index.tracking.maxRecordSetSize=1000 +index.tracking.disableInTransactionIndexing=false +index.tracking.adm.cronExpression=0/5 * * * * ? +index.tracking.avm.cronExpression=0/5 * * * * ? +index.reindexMissingContent.cronExpression=* * * * * ? 2099 \ No newline at end of file diff --git a/config/alfresco/subsystems/Search/lucene/lucene-search-context.xml b/config/alfresco/subsystems/Search/lucene/lucene-search-context.xml new file mode 100644 index 0000000000..c7c642f499 --- /dev/null +++ b/config/alfresco/subsystems/Search/lucene/lucene-search-context.xml @@ -0,0 +1,516 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + org.alfresco.repo.search.impl.lucene.LuceneIndexerAndSearcher + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + org.alfresco.service.cmr.search.CategoryService + + + + + + + + + + + + + + + + + + + + + + indexThread + + + 10 + + + 20 + + + 5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ${dir.indexes} + + + ${dir.indexes.lock} + + + ${lucene.maxAtomicTransformationTime} + + + ${lucene.query.maxClauses} + + + ${lucene.indexer.batchSize} + + + + ${lucene.indexer.cacheEnabled} + + + ${lucene.indexer.maxDocIdCacheSize} + + + ${lucene.indexer.maxDocumentCacheSize} + + + ${lucene.indexer.maxIsCategoryCacheSize} + + + ${lucene.indexer.maxLinkAspectCacheSize} + + + ${lucene.indexer.maxParentCacheSize} + + + ${lucene.indexer.maxPathCacheSize} + + + ${lucene.indexer.maxTypeCacheSize} + + + + ${lucene.indexer.mergerMaxMergeDocs} + + + ${lucene.indexer.mergerMergeFactor} + + + ${lucene.indexer.mergerMaxBufferedDocs} + + + ${lucene.indexer.mergerRamBufferSizeMb} + + + + ${lucene.indexer.writerMaxMergeDocs} + + + ${lucene.indexer.writerMergeFactor} + + + ${lucene.indexer.writerMaxBufferedDocs} + + + ${lucene.indexer.writerRamBufferSizeMb} + + + + ${lucene.indexer.mergerTargetIndexCount} + + + ${lucene.indexer.mergerTargetOverlayCount} + + + ${lucene.indexer.mergerTargetOverlaysBlockingFactor} + + + ${lucene.indexer.maxDocsForInMemoryMerge} + + + ${lucene.indexer.maxRamInMbForInMemoryMerge} + + + ${lucene.indexer.maxDocsForInMemoryIndex} + + + ${lucene.indexer.maxRamInMbForInMemoryIndex} + + + + ${lucene.indexer.termIndexInterval} + + + ${lucene.indexer.useNioMemoryMapping} + + + ${lucene.indexer.postSortDateTime} + + + ${lucene.indexer.defaultMLIndexAnalysisMode} + + + ${lucene.indexer.defaultMLSearchAnalysisMode} + + + ${lucene.indexer.maxFieldLength} + + + ${lucene.indexer.fairLocking} + + + ${lucene.write.lock.timeout} + + + ${lucene.commit.lock.timeout} + + + ${lucene.lock.poll.interval} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + org.alfresco.repo.search.impl.lucene.fts.FullTextSearchIndexer + + + + + + + + + + ${server.transaction.mode.default} + + + + + + + + + + ${fts.indexer.batchSize} + + + + + + + + + + + + + + + + + + ${dir.indexes.backup} + + + true + + + + + + ${index.recovery.mode} + + + + + + + + + + + + + diff --git a/config/alfresco/subsystems/Search/lucene/lucene-search.properties b/config/alfresco/subsystems/Search/lucene/lucene-search.properties new file mode 100644 index 0000000000..f3d6332119 --- /dev/null +++ b/config/alfresco/subsystems/Search/lucene/lucene-search.properties @@ -0,0 +1,52 @@ +dir.indexes=${dir.root}/lucene-indexes +dir.indexes.lock=${dir.indexes}/locks + +lucene.maxAtomicTransformationTime=20 +lucene.query.maxClauses=10000 +lucene.indexer.batchSize=1000000 + +lucene.indexer.cacheEnabled=true +lucene.indexer.maxDocIdCacheSize=10000 +lucene.indexer.maxDocumentCacheSize=100 +lucene.indexer.maxIsCategoryCacheSize=-1 +lucene.indexer.maxLinkAspectCacheSize=10000 +lucene.indexer.maxParentCacheSize=10000 +lucene.indexer.maxPathCacheSize=10000 +lucene.indexer.maxTypeCacheSize=10000 + +lucene.indexer.mergerMaxMergeDocs=1000000 +lucene.indexer.mergerMergeFactor=5 +lucene.indexer.mergerMaxBufferedDocs=-1 +lucene.indexer.mergerRamBufferSizeMb=16 + +lucene.indexer.writerMaxMergeDocs=1000000 +lucene.indexer.writerMergeFactor=5 +lucene.indexer.writerMaxBufferedDocs=-1 +lucene.indexer.writerRamBufferSizeMb=16 + +lucene.indexer.mergerTargetIndexCount=5 +lucene.indexer.mergerTargetOverlayCount=5 +lucene.indexer.mergerTargetOverlaysBlockingFactor=2 +lucene.indexer.maxDocsForInMemoryMerge=10000 +lucene.indexer.maxRamInMbForInMemoryMerge=16 +lucene.indexer.maxDocsForInMemoryIndex=10000 +lucene.indexer.maxRamInMbForInMemoryIndex=16 + +lucene.indexer.termIndexInterval=128 +lucene.indexer.useNioMemoryMapping=true + +lucene.indexer.postSortDateTime=true +lucene.indexer.defaultMLIndexAnalysisMode=EXACT_LANGUAGE_AND_ALL +lucene.indexer.defaultMLSearchAnalysisMode=EXACT_LANGUAGE_AND_ALL + +lucene.indexer.maxFieldLength=10000 + +lucene.indexer.fairLocking=true + +lucene.write.lock.timeout=10000 +lucene.commit.lock.timeout=100000 +lucene.lock.poll.interval=100 + +fts.indexer.batchSize=1000 + +dir.indexes.backup=${dir.root}/backup-lucene-indexes \ No newline at end of file diff --git a/config/alfresco/subsystems/Search/lucene/opencmis-context.xml b/config/alfresco/subsystems/Search/lucene/opencmis-context.xml new file mode 100644 index 0000000000..43e606ac76 --- /dev/null +++ b/config/alfresco/subsystems/Search/lucene/opencmis-context.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + org.alfresco.repo.search.impl.querymodel.QueryEngine + + + + + + + + + + + + + + + + + + org.alfresco.repo.search.impl.querymodel.QueryEngine.executeQuery=ACL_ALLOW,AFTER_ACL_NODE.sys:base.Read + org.alfresco.repo.search.impl.querymodel.QueryEngine.getQueryModelFactory=ACL_ALLOW + + + + \ No newline at end of file diff --git a/config/alfresco/subsystems/Search/lucene/scheduled-jobs-context.xml b/config/alfresco/subsystems/Search/lucene/scheduled-jobs-context.xml new file mode 100644 index 0000000000..172f42e807 --- /dev/null +++ b/config/alfresco/subsystems/Search/lucene/scheduled-jobs-context.xml @@ -0,0 +1,62 @@ + + + + + + + + + + org.alfresco.repo.search.impl.lucene.fts.FTSIndexerJob + + + + + + + + + + + + + + + 1 + + + 1 + + + + + + + + + org.alfresco.repo.search.impl.lucene.AbstractLuceneIndexerAndSearcherFactory$LuceneIndexBackupJob + + + + + + + + + + + + + + + + + + + + ${index.backup.cronExpression} + + + + + diff --git a/config/alfresco/subsystems/Search/lucene/scheduled-jobs.properties b/config/alfresco/subsystems/Search/lucene/scheduled-jobs.properties new file mode 100644 index 0000000000..341cf60ceb --- /dev/null +++ b/config/alfresco/subsystems/Search/lucene/scheduled-jobs.properties @@ -0,0 +1 @@ +index.backup.cronExpression=0 0 3 * * ? \ No newline at end of file diff --git a/config/alfresco/subsystems/Search/solr/cmis-api-context.xml b/config/alfresco/subsystems/Search/solr/cmis-api-context.xml new file mode 100644 index 0000000000..e21c7c909d --- /dev/null +++ b/config/alfresco/subsystems/Search/solr/cmis-api-context.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/config/alfresco/subsystems/Search/solr/common-search.properties b/config/alfresco/subsystems/Search/solr/common-search.properties new file mode 100644 index 0000000000..d315f426f9 --- /dev/null +++ b/config/alfresco/subsystems/Search/solr/common-search.properties @@ -0,0 +1,2 @@ +search.solrTrackingSupport.enabled=true + diff --git a/config/alfresco/subsystems/Search/solr/opencmis-context.xml b/config/alfresco/subsystems/Search/solr/opencmis-context.xml new file mode 100644 index 0000000000..c07b32a0d5 --- /dev/null +++ b/config/alfresco/subsystems/Search/solr/opencmis-context.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + cmis-strict + + + + + + + + + + + + + + + + + cmis-alfresco + + + + \ No newline at end of file diff --git a/config/alfresco/subsystems/Search/solr/solr-search-context.xml b/config/alfresco/subsystems/Search/solr/solr-search-context.xml new file mode 100644 index 0000000000..407514f45c --- /dev/null +++ b/config/alfresco/subsystems/Search/solr/solr-search-context.xml @@ -0,0 +1,161 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + lucene + + + + + + + + + + + + + + + + + + + fts-alfresco + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + org.alfresco.repo.search.IndexerAndSearcher + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/source/java/org/alfresco/repo/admin/ConfigurationChecker.java b/source/java/org/alfresco/repo/admin/ConfigurationChecker.java index c69f4d8091..1b31610e54 100644 --- a/source/java/org/alfresco/repo/admin/ConfigurationChecker.java +++ b/source/java/org/alfresco/repo/admin/ConfigurationChecker.java @@ -71,12 +71,11 @@ public class ConfigurationChecker extends AbstractLifecycleBean private static final String WARN_RELATIVE_DIR_ROOT = "system.config_check.warn.dir_root"; private static final String MSG_DIR_ROOT = "system.config_check.msg.dir_root"; - private static final String ERR_DUPLICATE_ROOT_NODE = "system.config_check.err.indexes.duplicate_root_node"; - private static final String ERR_MISSING_INDEXES = "system.config_check.err.missing_index"; + static final String ERR_MISSING_INDEXES = "system.config_check.err.missing_index"; private static final String ERR_MISSING_CONTENT = "system.config_check.err.missing_content"; - private static final String ERR_FIX_DIR_ROOT = "system.config_check.err.fix_dir_root"; - private static final String MSG_HOWTO_INDEX_RECOVER = "system.config_check.msg.howto_index_recover"; - private static final String WARN_STARTING_WITH_ERRORS = "system.config_check.warn.starting_with_errors"; + static final String ERR_FIX_DIR_ROOT = "system.config_check.err.fix_dir_root"; + static final String MSG_HOWTO_INDEX_RECOVER = "system.config_check.msg.howto_index_recover"; + static final String WARN_STARTING_WITH_ERRORS = "system.config_check.warn.starting_with_errors"; private boolean strict; private RecoveryMode indexRecoveryMode; @@ -88,7 +87,7 @@ public class ConfigurationChecker extends AbstractLifecycleBean private NodeService nodeService; private SearchService searchService; private ContentService contentService; - private AVMSnapShotTriggeredIndexingMethodInterceptor avmSnapShotTriggeredIndexingMethodInterceptor; + private IndexConfigurationChecker indexConfigurationChecker; public ConfigurationChecker() { @@ -165,11 +164,11 @@ public class ConfigurationChecker extends AbstractLifecycleBean this.contentService = contentService; } - public void setAvmSnapShotTriggeredIndexingMethodInterceptor(AVMSnapShotTriggeredIndexingMethodInterceptor avmSnapShotTriggeredIndexingMethodInterceptor) + public void setIndexConfigurationChecker(IndexConfigurationChecker indexConfigurationChecker) { - this.avmSnapShotTriggeredIndexingMethodInterceptor = avmSnapShotTriggeredIndexingMethodInterceptor; + this.indexConfigurationChecker = indexConfigurationChecker; } - + @Override protected void onBootstrap(ApplicationEvent event) { @@ -205,90 +204,7 @@ public class ConfigurationChecker extends AbstractLifecycleBean String msgDirRoot = I18NUtil.getMessage(MSG_DIR_ROOT, dirRootFile); logger.info(msgDirRoot); - // get all root nodes from the NodeService, i.e. database - List storeRefs = nodeService.getStores(); - List missingIndexStoreRefs = new ArrayList(0); - for (StoreRef storeRef : storeRefs) - { - @SuppressWarnings("unused") - NodeRef rootNodeRef = null; - try - { - rootNodeRef = nodeService.getRootNode(storeRef); - } - catch (InvalidStoreRefException e) - { - // the store is invalid and will therefore not have a root node entry - continue; - } - if (indexRecoveryMode != RecoveryMode.FULL) - { - if (storeRef.getProtocol().equals(StoreRef.PROTOCOL_AVM)) - { - if (avmSnapShotTriggeredIndexingMethodInterceptor.isIndexingEnabled()) - { - IndexMode storeIndexMode = avmSnapShotTriggeredIndexingMethodInterceptor.getIndexMode(storeRef.getIdentifier()); - if (storeIndexMode.equals(IndexMode.UNINDEXED)) - { - if (logger.isDebugEnabled()) - { - logger.debug("Skipping index check for store: " + storeRef + " (unindexed AVM store)"); - } - continue; - } - } - else - { - if (logger.isDebugEnabled()) - { - logger.debug("Skipping index check for store: " + storeRef + " (AVM indexing is disabled)"); - } - continue; - } - } - - if (logger.isDebugEnabled()) - { - logger.debug("Checking index for store: " + storeRef); - } - - // perform a Lucene query for the root node - SearchParameters sp = new SearchParameters(); - sp.addStore(storeRef); - sp.setLanguage(SearchService.LANGUAGE_LUCENE); - sp.setQuery("ISROOT:T"); - - ResultSet results = null; - int size = 0; - try - { - results = searchService.query(sp); - size = results.length(); - } - finally - { - try { results.close(); } catch (Throwable e) {} - } - - if (size == 0) - { - // indexes missing for root node - missingIndexStoreRefs.add(storeRef); - // debug - if (logger.isDebugEnabled()) - { - logger.debug("Index missing for store: \n" + - " store: " + storeRef); - } - } - else if (size > 1) - { - // there are duplicates - String msg = I18NUtil.getMessage(ERR_DUPLICATE_ROOT_NODE, storeRef); - throw new AlfrescoRuntimeException(msg); - } - } - } + List missingIndexStoreRefs = indexConfigurationChecker.checkIndexConfiguration(); // check for the system version properties content snippet boolean versionPropertiesContentAvailable = true; NodeRef descriptorNodeRef = getSystemDescriptor(); @@ -338,6 +254,8 @@ public class ConfigurationChecker extends AbstractLifecycleBean } } } + + /** * @return Returns the system descriptor node or null diff --git a/source/java/org/alfresco/repo/admin/DummyIndexConfigurationCheckerImpl.java b/source/java/org/alfresco/repo/admin/DummyIndexConfigurationCheckerImpl.java new file mode 100644 index 0000000000..aa1cbbbaa5 --- /dev/null +++ b/source/java/org/alfresco/repo/admin/DummyIndexConfigurationCheckerImpl.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2005-2010 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ +package org.alfresco.repo.admin; + +import java.util.Collections; +import java.util.List; + +import org.alfresco.service.cmr.repository.StoreRef; + +/** + * @author Andy + * + */ +public class DummyIndexConfigurationCheckerImpl implements IndexConfigurationChecker +{ + + /* (non-Javadoc) + * @see org.alfresco.repo.admin.IndexConfigurationChecker#checkIndexConfiguration() + */ + @Override + public List checkIndexConfiguration() + { + return Collections.emptyList(); + } + +} diff --git a/source/java/org/alfresco/repo/admin/IndexConfigurationChecker.java b/source/java/org/alfresco/repo/admin/IndexConfigurationChecker.java new file mode 100644 index 0000000000..0a0a7a432f --- /dev/null +++ b/source/java/org/alfresco/repo/admin/IndexConfigurationChecker.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2005-2010 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ +package org.alfresco.repo.admin; + +import java.util.List; + +import org.alfresco.service.cmr.repository.StoreRef; + +/** + * @author Andy + * + */ +public interface IndexConfigurationChecker +{ + /** + * Check that the index contains root entries for all the stores that would be expected + * @return - the stores with missing indexes + */ + public List checkIndexConfiguration(); +} diff --git a/source/java/org/alfresco/repo/admin/IndexConfigurationCheckerBootstrapBean.java b/source/java/org/alfresco/repo/admin/IndexConfigurationCheckerBootstrapBean.java new file mode 100644 index 0000000000..18a7d696ce --- /dev/null +++ b/source/java/org/alfresco/repo/admin/IndexConfigurationCheckerBootstrapBean.java @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2005-2010 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ +package org.alfresco.repo.admin; + +import java.io.File; +import java.util.List; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.model.ContentModel; +import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; +import org.alfresco.service.cmr.repository.ContentReader; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.transaction.TransactionService; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.context.ApplicationEvent; +import org.springframework.extensions.surf.util.AbstractLifecycleBean; +import org.springframework.extensions.surf.util.I18NUtil; + +public class IndexConfigurationCheckerBootstrapBean extends AbstractLifecycleBean +{ + private static Log logger = LogFactory.getLog(IndexConfigurationCheckerBootstrapBean.class); + + private IndexConfigurationChecker indexConfigurationChecker; + + private RepositoryState repositoryState; + + private TransactionService transactionService; + + private boolean strict; + + private String dirRoot; + + @Override + protected void onBootstrap(ApplicationEvent event) + { + RetryingTransactionCallback checkWork = new RetryingTransactionCallback() + { + public Object execute() throws Exception + { + // reindex + if((repositoryState == null) || (false == repositoryState.isBootstrapping())) + { + log.info("Checking/Recovering indexes ..."); + check(); + } + return null; + } + }; + transactionService.getRetryingTransactionHelper().doInTransaction(checkWork, true); + + + + } + + private void check() + { + if (logger.isDebugEnabled()) + { + logger.debug("Starting index configuration check: " + this); + } + + + File dirRootFile = new File(dirRoot); + + + List missingIndexStoreRefs = indexConfigurationChecker.checkIndexConfiguration(); + + // check for missing indexes + int missingStoreIndexes = missingIndexStoreRefs.size(); + if (missingStoreIndexes > 0) + { + String msg = I18NUtil.getMessage(ConfigurationChecker.ERR_MISSING_INDEXES, missingStoreIndexes); + logger.error(msg); + String msgRecover = I18NUtil.getMessage(ConfigurationChecker.MSG_HOWTO_INDEX_RECOVER); + logger.info(msgRecover); + } + + // handle either content or indexes missing + if (missingStoreIndexes > 0) + { + String msg = I18NUtil.getMessage(ConfigurationChecker.ERR_FIX_DIR_ROOT, dirRootFile); + logger.error(msg); + + // Now determine the failure behaviour + if (strict) + { + throw new AlfrescoRuntimeException(msg); + } + else + { + String warn = I18NUtil.getMessage(ConfigurationChecker.WARN_STARTING_WITH_ERRORS); + logger.warn(warn); + } + } + } + + @Override + protected void onShutdown(ApplicationEvent event) + { + // Nothing to do + } + + + + public IndexConfigurationChecker getIndexConfigurationChecker() + { + return indexConfigurationChecker; + } + + public void setIndexConfigurationChecker(IndexConfigurationChecker indexConfigurationChecker) + { + this.indexConfigurationChecker = indexConfigurationChecker; + } + + public RepositoryState getRepositoryState() + { + return repositoryState; + } + + public void setRepositoryState(RepositoryState repositoryState) + { + this.repositoryState = repositoryState; + } + + public void setStrict(boolean strict) + { + this.strict = strict; + } + + public void setDirRoot(String dirRoot) + { + this.dirRoot = dirRoot; + } + + public void setTransactionService(TransactionService transactionService) + { + this.transactionService = transactionService; + } + + +} diff --git a/source/java/org/alfresco/repo/admin/IndexConfigurationCheckerImpl.java b/source/java/org/alfresco/repo/admin/IndexConfigurationCheckerImpl.java new file mode 100644 index 0000000000..b43660d85c --- /dev/null +++ b/source/java/org/alfresco/repo/admin/IndexConfigurationCheckerImpl.java @@ -0,0 +1,188 @@ +/* + * Copyright (C) 2005-2010 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ +package org.alfresco.repo.admin; + +import java.util.ArrayList; +import java.util.List; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.repo.node.index.FullIndexRecoveryComponent.RecoveryMode; +import org.alfresco.repo.search.AVMSnapShotTriggeredIndexingMethodInterceptor; +import org.alfresco.repo.search.IndexMode; +import org.alfresco.service.cmr.repository.InvalidStoreRefException; +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.search.ResultSet; +import org.alfresco.service.cmr.search.SearchParameters; +import org.alfresco.service.cmr.search.SearchService; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.extensions.surf.util.I18NUtil; + +/** + * @author Andy + * + */ +public class IndexConfigurationCheckerImpl implements IndexConfigurationChecker +{ + private static Log logger = LogFactory.getLog(IndexConfigurationCheckerImpl.class); + + private static final String ERR_DUPLICATE_ROOT_NODE = "system.config_check.err.indexes.duplicate_root_node"; + + private RecoveryMode indexRecoveryMode; + private NodeService nodeService; + private SearchService searchService; + private AVMSnapShotTriggeredIndexingMethodInterceptor avmSnapShotTriggeredIndexingMethodInterceptor; + + /** + * Set the index recovert mode + * @param indexRecoveryMode + */ + public void setIndexRecoveryMode(RecoveryMode indexRecoveryMode) + { + this.indexRecoveryMode = indexRecoveryMode; + } + + + + /** + * Set the node service + * @param nodeService + */ + public void setNodeService(NodeService nodeService) + { + this.nodeService = nodeService; + } + + + /** + * Set the search service + * @param searchService + */ + public void setSearchService(SearchService searchService) + { + this.searchService = searchService; + } + + /** + * avm trigger + * @param avmSnapShotTriggeredIndexingMethodInterceptor + */ + public void setAvmSnapShotTriggeredIndexingMethodInterceptor(AVMSnapShotTriggeredIndexingMethodInterceptor avmSnapShotTriggeredIndexingMethodInterceptor) + { + this.avmSnapShotTriggeredIndexingMethodInterceptor = avmSnapShotTriggeredIndexingMethodInterceptor; + } + + + + /* (non-Javadoc) + * @see org.alfresco.repo.admin.IndexConfigurationChecker#checkIndexConfiguration() + */ + @Override + public List checkIndexConfiguration() + { + // get all root nodes from the NodeService, i.e. database + List storeRefs = nodeService.getStores(); + List missingIndexStoreRefs = new ArrayList(0); + for (StoreRef storeRef : storeRefs) + { + @SuppressWarnings("unused") + NodeRef rootNodeRef = null; + try + { + rootNodeRef = nodeService.getRootNode(storeRef); + } + catch (InvalidStoreRefException e) + { + // the store is invalid and will therefore not have a root node entry + continue; + } + if (indexRecoveryMode != RecoveryMode.FULL) + { + if (storeRef.getProtocol().equals(StoreRef.PROTOCOL_AVM)) + { + if (avmSnapShotTriggeredIndexingMethodInterceptor.isIndexingEnabled()) + { + IndexMode storeIndexMode = avmSnapShotTriggeredIndexingMethodInterceptor.getIndexMode(storeRef.getIdentifier()); + if (storeIndexMode.equals(IndexMode.UNINDEXED)) + { + if (logger.isDebugEnabled()) + { + logger.debug("Skipping index check for store: " + storeRef + " (unindexed AVM store)"); + } + continue; + } + } + else + { + if (logger.isDebugEnabled()) + { + logger.debug("Skipping index check for store: " + storeRef + " (AVM indexing is disabled)"); + } + continue; + } + } + + if (logger.isDebugEnabled()) + { + logger.debug("Checking index for store: " + storeRef); + } + + // perform a Lucene query for the root node + SearchParameters sp = new SearchParameters(); + sp.addStore(storeRef); + sp.setLanguage(SearchService.LANGUAGE_LUCENE); + sp.setQuery("ISROOT:T"); + + ResultSet results = null; + int size = 0; + try + { + results = searchService.query(sp); + size = results.length(); + } + finally + { + try { results.close(); } catch (Throwable e) {} + } + + if (size == 0) + { + // indexes missing for root node + missingIndexStoreRefs.add(storeRef); + // debug + if (logger.isDebugEnabled()) + { + logger.debug("Index missing for store: \n" + + " store: " + storeRef); + } + } + else if (size > 1) + { + // there are duplicates + String msg = I18NUtil.getMessage(ERR_DUPLICATE_ROOT_NODE, storeRef); + throw new AlfrescoRuntimeException(msg); + } + } + } + return missingIndexStoreRefs; + } + +} diff --git a/source/java/org/alfresco/repo/admin/RepositoryEndBootstrapBean.java b/source/java/org/alfresco/repo/admin/RepositoryEndBootstrapBean.java new file mode 100644 index 0000000000..3e742af058 --- /dev/null +++ b/source/java/org/alfresco/repo/admin/RepositoryEndBootstrapBean.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2005-2010 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ +package org.alfresco.repo.admin; + +import org.springframework.context.ApplicationEvent; +import org.springframework.extensions.surf.util.AbstractLifecycleBean; + +/** + * Track repo bootstrap so sub systems do not duplciate stuff or do it too early ... eg index rebuild/check + * + * @author andyh + */ +public class RepositoryEndBootstrapBean extends AbstractLifecycleBean +{ + private RepositoryState repositoryState; + + public RepositoryState getRepositoryState() + { + return repositoryState; + } + + public void setRepositoryState(RepositoryState repositoryState) + { + this.repositoryState = repositoryState; + } + + @Override + protected void onBootstrap(ApplicationEvent event) + { + repositoryState.setBootstrapping(false); + } + + @Override + protected void onShutdown(ApplicationEvent event) + { + // NOOP + } +} \ No newline at end of file diff --git a/source/java/org/alfresco/repo/admin/RepositoryStartBootstrapBean.java b/source/java/org/alfresco/repo/admin/RepositoryStartBootstrapBean.java new file mode 100644 index 0000000000..e7ed08ba09 --- /dev/null +++ b/source/java/org/alfresco/repo/admin/RepositoryStartBootstrapBean.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2005-2010 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ +package org.alfresco.repo.admin; + +import org.springframework.context.ApplicationEvent; +import org.springframework.extensions.surf.util.AbstractLifecycleBean; + +/** + * Track repo bootstrap so sub systems do not duplciate stuff or do it too early ... eg index rebuild/check + * + * @author andyh + */ +public class RepositoryStartBootstrapBean extends AbstractLifecycleBean +{ + private RepositoryState repositoryState; + + public RepositoryState getRepositoryState() + { + return repositoryState; + } + + public void setRepositoryState(RepositoryState repositoryState) + { + this.repositoryState = repositoryState; + } + + @Override + protected void onBootstrap(ApplicationEvent event) + { + repositoryState.setBootstrapping(true); + } + + @Override + protected void onShutdown(ApplicationEvent event) + { + // NOOP + } +} \ No newline at end of file diff --git a/source/java/org/alfresco/repo/admin/RepositoryState.java b/source/java/org/alfresco/repo/admin/RepositoryState.java new file mode 100644 index 0000000000..97519efa9a --- /dev/null +++ b/source/java/org/alfresco/repo/admin/RepositoryState.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2005-2010 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ +package org.alfresco.repo.admin; + +/** + * @author Andy + * + */ +public class RepositoryState +{ + private boolean bootstrapping; + + public boolean isBootstrapping() + { + return bootstrapping; + } + + public void setBootstrapping(boolean bootstrapping) + { + this.bootstrapping = bootstrapping; + } + + +} diff --git a/source/java/org/alfresco/repo/avm/AVMServiceIndexTest.java b/source/java/org/alfresco/repo/avm/AVMServiceIndexTest.java index c1d95cfe5d..91e8579a81 100644 --- a/source/java/org/alfresco/repo/avm/AVMServiceIndexTest.java +++ b/source/java/org/alfresco/repo/avm/AVMServiceIndexTest.java @@ -27,6 +27,9 @@ import org.alfresco.service.cmr.repository.StoreRef; import org.alfresco.service.cmr.search.ResultSet; import org.alfresco.service.cmr.search.SearchService; import org.alfresco.util.TriggerBean; +import org.alfresco.util.TriggerBeanSPI; +import org.springframework.beans.factory.DisposableBean; +import org.springframework.beans.factory.InitializingBean; /** * Test AVMService indexing @@ -51,15 +54,16 @@ public class AVMServiceIndexTest extends AVMServiceTestBase // // override default schedule to speed up this unit test (by reducing the sleep time) // + DisposableBean dispBean = (DisposableBean)fContext.getBean("ftsIndexerTrigger"); + InitializingBean initBean = (InitializingBean)fContext.getBean("ftsIndexerTrigger"); + TriggerBeanSPI triggerBeanSPI = (TriggerBeanSPI)fContext.getBean("ftsIndexerTrigger"); + + dispBean.destroy(); // unschedule - TriggerBean ftsIndexerTrigger = (TriggerBean)fContext.getBean("ftsIndexerTrigger"); + triggerBeanSPI.setStartDelay(START_DELAY_MSECS); + triggerBeanSPI.setRepeatInterval(REPEAT_INTERVAL_MSECS); - ftsIndexerTrigger.destroy(); // unschedule - - ftsIndexerTrigger.setStartDelay(START_DELAY_MSECS); - ftsIndexerTrigger.setRepeatInterval(REPEAT_INTERVAL_MSECS); - - ftsIndexerTrigger.afterPropertiesSet(); // re-schedule + initBean.afterPropertiesSet(); // re-schedule } /** diff --git a/source/java/org/alfresco/repo/management/subsystems/ChildApplicationContextFactory.java b/source/java/org/alfresco/repo/management/subsystems/ChildApplicationContextFactory.java index bbf952804d..710f2d583b 100644 --- a/source/java/org/alfresco/repo/management/subsystems/ChildApplicationContextFactory.java +++ b/source/java/org/alfresco/repo/management/subsystems/ChildApplicationContextFactory.java @@ -154,7 +154,7 @@ public class ChildApplicationContextFactory extends AbstractPropertyBackedBean i /** * Default constructor for container construction. */ - protected ChildApplicationContextFactory() + public ChildApplicationContextFactory() { } diff --git a/source/java/org/alfresco/repo/node/index/IndexRecoveryBootstrapBean.java b/source/java/org/alfresco/repo/node/index/IndexRecoveryBootstrapBean.java index c4fc30685c..319a9ed80d 100644 --- a/source/java/org/alfresco/repo/node/index/IndexRecoveryBootstrapBean.java +++ b/source/java/org/alfresco/repo/node/index/IndexRecoveryBootstrapBean.java @@ -19,6 +19,7 @@ package org.alfresco.repo.node.index; import org.springframework.extensions.surf.util.AbstractLifecycleBean; +import org.alfresco.repo.admin.RepositoryState; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.context.ApplicationEvent; @@ -28,13 +29,18 @@ public class IndexRecoveryBootstrapBean extends AbstractLifecycleBean protected final static Log log = LogFactory.getLog(IndexRecoveryBootstrapBean.class); IndexRecovery indexRecoveryComponent; + + RepositoryState repositoryState; @Override protected void onBootstrap(ApplicationEvent event) { // reindex - log.info("Checking/Recovering indexes ..."); - indexRecoveryComponent.reindex(); + if((repositoryState == null) || (false == repositoryState.isBootstrapping())) + { + log.info("Checking/Recovering indexes ..."); + indexRecoveryComponent.reindex(); + } } @Override @@ -53,4 +59,15 @@ public class IndexRecoveryBootstrapBean extends AbstractLifecycleBean this.indexRecoveryComponent = indexRecoveryComponent; } + public RepositoryState getRepositoryState() + { + return repositoryState; + } + + public void setRepositoryState(RepositoryState repositoryState) + { + this.repositoryState = repositoryState; + } + + } diff --git a/source/java/org/alfresco/repo/search/IndexerAndSearcher.java b/source/java/org/alfresco/repo/search/IndexerAndSearcher.java index d86e17f75c..78841c2042 100644 --- a/source/java/org/alfresco/repo/search/IndexerAndSearcher.java +++ b/source/java/org/alfresco/repo/search/IndexerAndSearcher.java @@ -18,6 +18,9 @@ */ package org.alfresco.repo.search; +import java.util.Map; + +import org.alfresco.repo.search.impl.lucene.LuceneQueryLanguageSPI; import org.alfresco.service.cmr.repository.StoreRef; import org.alfresco.service.cmr.search.SearchService; @@ -56,4 +59,14 @@ public interface IndexerAndSearcher * */ public abstract void flush(); + + /** + * @param luceneAlfrescoFtsQueryLanguage + */ + public abstract void registerQueryLanguage(LuceneQueryLanguageSPI luceneQueryLanguageSPI); + + /** + * @return + */ + public abstract Map getQueryLanguages(); } diff --git a/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneCategoryTest.java b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneCategoryTest.java index 281ed35b84..08fc9ea5b9 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneCategoryTest.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneCategoryTest.java @@ -35,6 +35,7 @@ import org.alfresco.repo.dictionary.IndexTokenisationMode; import org.alfresco.repo.dictionary.M2Aspect; import org.alfresco.repo.dictionary.M2Model; import org.alfresco.repo.dictionary.M2Property; +import org.alfresco.repo.search.IndexerAndSearcher; import org.alfresco.repo.search.impl.lucene.fts.FullTextSearchIndexer; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.tenant.TenantService; @@ -104,11 +105,13 @@ public class ADMLuceneCategoryTest extends TestCase private NodeRef catRTwo; private NodeRef catRThree; private SearchService searcher; - private LuceneIndexerAndSearcher indexerAndSearcher; + private IndexerAndSearcher indexerAndSearcher; private TenantService tenantService; private CategoryService categoryService; + private LuceneConfig luceneConfig; + /** * Simple test constructor * @@ -134,7 +137,8 @@ public class ADMLuceneCategoryTest extends TestCase luceneFTS = (FullTextSearchIndexer) ctx.getBean("LuceneFullTextSearchIndexer"); dictionaryDAO = (DictionaryDAO) ctx.getBean("dictionaryDAO"); searcher = (SearchService) ctx.getBean("searchService"); - indexerAndSearcher = (LuceneIndexerAndSearcher) ctx.getBean("admLuceneIndexerAndSearcherFactory"); + indexerAndSearcher = (IndexerAndSearcher) ctx.getBean("admLuceneIndexerAndSearcherFactory"); + luceneConfig = (LuceneConfig) ctx.getBean("admLuceneIndexerAndSearcherFactory"); categoryService = (CategoryService) ctx.getBean("categoryService"); serviceRegistry = (ServiceRegistry) ctx.getBean(ServiceRegistry.SERVICE_REGISTRY); tenantService = (TenantService) ctx.getBean("tenantService"); @@ -334,7 +338,7 @@ public class ADMLuceneCategoryTest extends TestCase private void buildBaseIndex() { - ADMLuceneIndexerImpl indexer = ADMLuceneIndexerImpl.getUpdateIndexer(rootNodeRef.getStoreRef(), "delta" + System.currentTimeMillis() + "_" + (new Random().nextInt()), indexerAndSearcher); + ADMLuceneIndexerImpl indexer = ADMLuceneIndexerImpl.getUpdateIndexer(rootNodeRef.getStoreRef(), "delta" + System.currentTimeMillis() + "_" + (new Random().nextInt()), luceneConfig); indexer.setNodeService(nodeService); //indexer.setLuceneIndexLock(luceneIndexLock); indexer.setDictionaryService(dictionaryService); @@ -375,12 +379,12 @@ public class ADMLuceneCategoryTest extends TestCase private ADMLuceneSearcherImpl buildSearcher() { - ADMLuceneSearcherImpl searcher = ADMLuceneSearcherImpl.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); + ADMLuceneSearcherImpl searcher = ADMLuceneSearcherImpl.getSearcher(rootNodeRef.getStoreRef(), luceneConfig); searcher.setNodeService(nodeService); searcher.setDictionaryService(dictionaryService); searcher.setTenantService(tenantService); searcher.setNamespacePrefixResolver(getNamespacePrefixReolsver("")); - searcher.setQueryLanguages(((AbstractLuceneIndexerAndSearcherFactory) indexerAndSearcher).queryLanguages); + searcher.setQueryLanguages(indexerAndSearcher.getQueryLanguages()); return searcher; } diff --git a/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneIndexerAndSearcherFactory.java b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneIndexerAndSearcherFactory.java index 2ccdca2c83..70a08c509a 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneIndexerAndSearcherFactory.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneIndexerAndSearcherFactory.java @@ -118,7 +118,7 @@ public class ADMLuceneIndexerAndSearcherFactory extends AbstractLuceneIndexerAnd searcher.setDictionaryService(dictionaryService); searcher.setQueryRegister(getQueryRegister()); searcher.setDictionaryService(dictionaryService); - searcher.setQueryLanguages(queryLanguages); + searcher.setQueryLanguages(getQueryLanguages()); return searcher; } @@ -131,7 +131,7 @@ public class ADMLuceneIndexerAndSearcherFactory extends AbstractLuceneIndexerAnd searcher.setDictionaryService(dictionaryService); searcher.setQueryRegister(getQueryRegister()); searcher.setDictionaryService(dictionaryService); - searcher.setQueryLanguages(queryLanguages); + searcher.setQueryLanguages(getQueryLanguages()); return searcher; } diff --git a/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneTest.java b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneTest.java index e9ebb4894d..54858b2889 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneTest.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneTest.java @@ -55,6 +55,7 @@ import org.alfresco.repo.dictionary.M2Model; import org.alfresco.repo.dictionary.NamespaceDAOImpl; import org.alfresco.repo.node.BaseNodeServiceTest; import org.alfresco.repo.node.NodeBulkLoader; +import org.alfresco.repo.search.IndexerAndSearcher; import org.alfresco.repo.search.MLAnalysisMode; import org.alfresco.repo.search.QueryParameterDefImpl; import org.alfresco.repo.search.QueryRegisterComponent; @@ -201,7 +202,7 @@ public class ADMLuceneTest extends TestCase implements DictionaryListener private DictionaryNamespaceComponent namespacePrefixResolver; - private LuceneIndexerAndSearcher indexerAndSearcher; + private IndexerAndSearcher indexerAndSearcher; private ServiceRegistry serviceRegistry; @@ -226,6 +227,8 @@ public class ADMLuceneTest extends TestCase implements DictionaryListener // TODO: pending replacement private Dialect dialect; + private LuceneConfig luceneConfig; + /** * */ @@ -267,8 +270,9 @@ public class ADMLuceneTest extends TestCase implements DictionaryListener contentService = (ContentService) ctx.getBean("contentService"); queryRegisterComponent = (QueryRegisterComponent) ctx.getBean("queryRegisterComponent"); namespacePrefixResolver = (DictionaryNamespaceComponent) ctx.getBean("namespaceService"); - indexerAndSearcher = (LuceneIndexerAndSearcher) ctx.getBean("admLuceneIndexerAndSearcherFactory"); - ((AbstractLuceneIndexerAndSearcherFactory) indexerAndSearcher).setMaxAtomicTransformationTime(1000000); + indexerAndSearcher = (IndexerAndSearcher) ctx.getBean("admLuceneIndexerAndSearcherFactory"); + luceneConfig = (LuceneConfig)ctx.getBean("admLuceneIndexerAndSearcherFactory"); + ((LuceneConfig) indexerAndSearcher).setMaxAtomicTransformationTime(1000000); transactionService = (TransactionService) ctx.getBean("transactionComponent"); retryingTransactionHelper = (RetryingTransactionHelper) ctx.getBean("retryingTransactionHelper"); tenantService = (TenantService) ctx.getBean("tenantService"); @@ -1768,13 +1772,13 @@ public class ADMLuceneTest extends TestCase implements DictionaryListener private ADMLuceneSearcherImpl buildSearcher() { - ADMLuceneSearcherImpl searcher = ADMLuceneSearcherImpl.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); + ADMLuceneSearcherImpl searcher = ADMLuceneSearcherImpl.getSearcher(rootNodeRef.getStoreRef(), luceneConfig); searcher.setNodeService(nodeService); searcher.setDictionaryService(dictionaryService); searcher.setTenantService(tenantService); searcher.setNamespacePrefixResolver(getNamespacePrefixResolver("namespace")); searcher.setQueryRegister(queryRegisterComponent); - searcher.setQueryLanguages(((AbstractLuceneIndexerAndSearcherFactory) indexerAndSearcher).queryLanguages); + searcher.setQueryLanguages(indexerAndSearcher.getQueryLanguages()); return searcher; } @@ -3718,7 +3722,7 @@ public class ADMLuceneTest extends TestCase implements DictionaryListener public void testNoOp() throws Exception { luceneFTS.pause(); - ADMLuceneIndexerImpl indexer = ADMLuceneIndexerImpl.getUpdateIndexer(rootNodeRef.getStoreRef(), "delta" + System.currentTimeMillis() + "_1", indexerAndSearcher); + ADMLuceneIndexerImpl indexer = ADMLuceneIndexerImpl.getUpdateIndexer(rootNodeRef.getStoreRef(), "delta" + System.currentTimeMillis() + "_1", luceneConfig); indexer.setMaxAtomicTransformationTime(1000000); indexer.setNodeService(nodeService); // indexer.setLuceneIndexLock(luceneIndexLock); @@ -3742,7 +3746,7 @@ public class ADMLuceneTest extends TestCase implements DictionaryListener public void testStandAloneIndexerCommit() throws Exception { luceneFTS.pause(); - ADMLuceneIndexerImpl indexer = ADMLuceneIndexerImpl.getUpdateIndexer(rootNodeRef.getStoreRef(), "delta" + System.currentTimeMillis() + "_1", indexerAndSearcher); + ADMLuceneIndexerImpl indexer = ADMLuceneIndexerImpl.getUpdateIndexer(rootNodeRef.getStoreRef(), "delta" + System.currentTimeMillis() + "_1", luceneConfig); indexer.setMaxAtomicTransformationTime(1000000); indexer.setNodeService(nodeService); @@ -3925,7 +3929,7 @@ public class ADMLuceneTest extends TestCase implements DictionaryListener private void buildBaseIndex() { ADMLuceneIndexerImpl indexer = ADMLuceneIndexerImpl.getUpdateIndexer(rootNodeRef.getStoreRef(), "delta" + System.currentTimeMillis() + "_" + (new Random().nextInt()), - indexerAndSearcher); + luceneConfig); indexer.setMaxAtomicTransformationTime(1000000); indexer.setNodeService(nodeService); // indexer.setLuceneIndexLock(luceneIndexLock); @@ -6406,7 +6410,7 @@ public class ADMLuceneTest extends TestCase implements DictionaryListener runBaseTests(); - ADMLuceneIndexerImpl indexer = ADMLuceneIndexerImpl.getUpdateIndexer(rootNodeRef.getStoreRef(), "delta" + System.currentTimeMillis(), indexerAndSearcher); + ADMLuceneIndexerImpl indexer = ADMLuceneIndexerImpl.getUpdateIndexer(rootNodeRef.getStoreRef(), "delta" + System.currentTimeMillis(), luceneConfig); indexer.setMaxAtomicTransformationTime(1000000); indexer.setNodeService(nodeService); // indexer.setLuceneIndexLock(luceneIndexLock); @@ -6665,7 +6669,7 @@ public class ADMLuceneTest extends TestCase implements DictionaryListener buildBaseIndex(); runBaseTests(); - ADMLuceneIndexerImpl indexer = ADMLuceneIndexerImpl.getUpdateIndexer(rootNodeRef.getStoreRef(), "delta" + System.currentTimeMillis(), indexerAndSearcher); + ADMLuceneIndexerImpl indexer = ADMLuceneIndexerImpl.getUpdateIndexer(rootNodeRef.getStoreRef(), "delta" + System.currentTimeMillis(), luceneConfig); indexer.setMaxAtomicTransformationTime(1000000); indexer.setNodeService(nodeService); // indexer.setLuceneIndexLock(luceneIndexLock); @@ -6696,7 +6700,7 @@ public class ADMLuceneTest extends TestCase implements DictionaryListener buildBaseIndex(); runBaseTests(); - ADMLuceneIndexerImpl indexer = ADMLuceneIndexerImpl.getUpdateIndexer(rootNodeRef.getStoreRef(), "delta" + System.currentTimeMillis(), indexerAndSearcher); + ADMLuceneIndexerImpl indexer = ADMLuceneIndexerImpl.getUpdateIndexer(rootNodeRef.getStoreRef(), "delta" + System.currentTimeMillis(), luceneConfig); indexer.setMaxAtomicTransformationTime(1000000); indexer.setNodeService(nodeService); // indexer.setLuceneIndexLock(luceneIndexLock); @@ -6729,7 +6733,7 @@ public class ADMLuceneTest extends TestCase implements DictionaryListener runBaseTests(); testTX.commit(); - ADMLuceneIndexerImpl indexer = ADMLuceneIndexerImpl.getUpdateIndexer(rootNodeRef.getStoreRef(), "delta" + System.currentTimeMillis(), indexerAndSearcher); + ADMLuceneIndexerImpl indexer = ADMLuceneIndexerImpl.getUpdateIndexer(rootNodeRef.getStoreRef(), "delta" + System.currentTimeMillis(), luceneConfig); indexer.setNodeService(nodeService); // indexer.setLuceneIndexLock(luceneIndexLock); indexer.setDictionaryService(dictionaryService); @@ -6945,7 +6949,7 @@ public class ADMLuceneTest extends TestCase implements DictionaryListener buildBaseIndex(); runBaseTests(); - ADMLuceneIndexerImpl indexer = ADMLuceneIndexerImpl.getUpdateIndexer(rootNodeRef.getStoreRef(), "delta" + System.currentTimeMillis(), indexerAndSearcher); + ADMLuceneIndexerImpl indexer = ADMLuceneIndexerImpl.getUpdateIndexer(rootNodeRef.getStoreRef(), "delta" + System.currentTimeMillis(), luceneConfig); indexer.setMaxAtomicTransformationTime(1000000); indexer.setNodeService(nodeService); // indexer.setLuceneIndexLock(luceneIndexLock); @@ -7156,7 +7160,7 @@ public class ADMLuceneTest extends TestCase implements DictionaryListener assertEquals(1, results.length()); results.close(); - indexer = ADMLuceneIndexerImpl.getUpdateIndexer(rootNodeRef.getStoreRef(), "delta" + System.currentTimeMillis(), indexerAndSearcher); + indexer = ADMLuceneIndexerImpl.getUpdateIndexer(rootNodeRef.getStoreRef(), "delta" + System.currentTimeMillis(), luceneConfig); indexer.setMaxAtomicTransformationTime(1000000); indexer.setNodeService(nodeService); // indexer.setLuceneIndexLock(luceneIndexLock); @@ -7197,7 +7201,7 @@ public class ADMLuceneTest extends TestCase implements DictionaryListener assertEquals(0, results.length()); results.close(); - ADMLuceneIndexerImpl indexer = ADMLuceneIndexerImpl.getUpdateIndexer(rootNodeRef.getStoreRef(), "delta" + System.currentTimeMillis(), indexerAndSearcher); + ADMLuceneIndexerImpl indexer = ADMLuceneIndexerImpl.getUpdateIndexer(rootNodeRef.getStoreRef(), "delta" + System.currentTimeMillis(), luceneConfig); indexer.setMaxAtomicTransformationTime(1000000); indexer.setNodeService(nodeService); // indexer.setLuceneIndexLock(luceneIndexLock); @@ -7260,7 +7264,7 @@ public class ADMLuceneTest extends TestCase implements DictionaryListener // Do index ADMLuceneIndexerImpl indexer = ADMLuceneIndexerImpl.getUpdateIndexer(rootNodeRef.getStoreRef(), "delta" + System.currentTimeMillis() + "_" + (new Random().nextInt()), - indexerAndSearcher); + luceneConfig); indexer.setMaxAtomicTransformationTime(1000000); indexer.setNodeService(nodeService); // indexer.setLuceneIndexLock(luceneIndexLock); @@ -7329,7 +7333,7 @@ public class ADMLuceneTest extends TestCase implements DictionaryListener results.close(); ADMLuceneIndexerImpl indexer = ADMLuceneIndexerImpl.getUpdateIndexer(rootNodeRef.getStoreRef(), "delta" + System.currentTimeMillis() + "_" + (new Random().nextInt()), - indexerAndSearcher); + luceneConfig); indexer.setMaxAtomicTransformationTime(1000000); indexer.setNodeService(nodeService); // indexer.setLuceneIndexLock(luceneIndexLock); @@ -7730,7 +7734,7 @@ public class ADMLuceneTest extends TestCase implements DictionaryListener private void runPerformanceTest(double time, boolean clear) { ADMLuceneIndexerImpl indexer = ADMLuceneIndexerImpl.getUpdateIndexer(rootNodeRef.getStoreRef(), "delta" + System.currentTimeMillis() + "_" + (new Random().nextInt()), - indexerAndSearcher); + luceneConfig); indexer.setMaxAtomicTransformationTime(1000000); indexer.setNodeService(nodeService); // indexer.setLuceneIndexLock(luceneIndexLock); diff --git a/source/java/org/alfresco/repo/search/impl/lucene/AVMLuceneIndexerAndSearcherFactory.java b/source/java/org/alfresco/repo/search/impl/lucene/AVMLuceneIndexerAndSearcherFactory.java index fc8aa289bd..519f50527e 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/AVMLuceneIndexerAndSearcherFactory.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/AVMLuceneIndexerAndSearcherFactory.java @@ -169,7 +169,7 @@ public class AVMLuceneIndexerAndSearcherFactory extends AbstractLuceneIndexerAnd searcher.setDictionaryService(dictionaryService); searcher.setQueryRegister(getQueryRegister()); searcher.setDictionaryService(dictionaryService); - searcher.setQueryLanguages(queryLanguages); + searcher.setQueryLanguages(getQueryLanguages()); return searcher; } diff --git a/source/java/org/alfresco/repo/search/impl/lucene/AbstractIndexerAndSearcher.java b/source/java/org/alfresco/repo/search/impl/lucene/AbstractIndexerAndSearcher.java new file mode 100644 index 0000000000..16fd05133e --- /dev/null +++ b/source/java/org/alfresco/repo/search/impl/lucene/AbstractIndexerAndSearcher.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2005-2010 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ +package org.alfresco.repo.search.impl.lucene; + +import java.util.HashMap; +import java.util.Map; + +import org.alfresco.repo.search.Indexer; +import org.alfresco.repo.search.IndexerAndSearcher; +import org.alfresco.repo.search.IndexerException; +import org.alfresco.repo.search.SearcherException; +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.cmr.search.SearchService; + +/** + * @author Andy + * + */ +public abstract class AbstractIndexerAndSearcher implements IndexerAndSearcher +{ + + private Map queryLanguages = new HashMap(); + + @Override + public void registerQueryLanguage(LuceneQueryLanguageSPI queryLanguage) + { + this.queryLanguages.put(queryLanguage.getName().toLowerCase(), queryLanguage); + } + + + @Override + public Map getQueryLanguages() + { + return queryLanguages; + } + +} diff --git a/source/java/org/alfresco/repo/search/impl/lucene/AbstractLuceneIndexerAndSearcherFactory.java b/source/java/org/alfresco/repo/search/impl/lucene/AbstractLuceneIndexerAndSearcherFactory.java index bf204986ae..853cd7d8a0 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/AbstractLuceneIndexerAndSearcherFactory.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/AbstractLuceneIndexerAndSearcherFactory.java @@ -80,7 +80,7 @@ import org.springframework.transaction.support.TransactionSynchronizationManager * @author andyh */ -public abstract class AbstractLuceneIndexerAndSearcherFactory implements LuceneIndexerAndSearcher, XAResource, ApplicationContextAware +public abstract class AbstractLuceneIndexerAndSearcherFactory extends AbstractIndexerAndSearcher implements LuceneIndexerAndSearcher, XAResource, ApplicationContextAware { private static Log logger = LogFactory.getLog(AbstractLuceneIndexerAndSearcherFactory.class); @@ -88,8 +88,6 @@ public abstract class AbstractLuceneIndexerAndSearcherFactory implements LuceneI private int indexerBatchSize; - protected Map queryLanguages = new HashMap(); - /** * A map of active global transactions . It contains all the indexers a transaction has used, with at most one * indexer for each store within a transaction @@ -278,6 +276,7 @@ public abstract class AbstractLuceneIndexerAndSearcherFactory implements LuceneI * @param maxAtomicTransformationTime * the maximum average time that a text transformation may take in order to be performed atomically. */ + @Override public void setMaxAtomicTransformationTime(long maxAtomicTransformationTime) { this.maxAtomicTransformationTime = maxAtomicTransformationTime; @@ -288,6 +287,7 @@ public abstract class AbstractLuceneIndexerAndSearcherFactory implements LuceneI * * @return - milliseconds as a long */ + @Override public long getMaxTransformationTime() { return maxAtomicTransformationTime; @@ -869,11 +869,13 @@ public abstract class AbstractLuceneIndexerAndSearcherFactory implements LuceneI } } + @Override public String getIndexRootLocation() { return indexRootLocation; } + @Override public int getIndexerBatchSize() { return indexerBatchSize; @@ -884,6 +886,7 @@ public abstract class AbstractLuceneIndexerAndSearcherFactory implements LuceneI * * @param indexerBatchSize */ + @Override public void setIndexerBatchSize(int indexerBatchSize) { this.indexerBatchSize = indexerBatchSize; @@ -930,6 +933,7 @@ public abstract class AbstractLuceneIndexerAndSearcherFactory implements LuceneI } } + @Override public int getQueryMaxClauses() { return queryMaxClauses; @@ -940,6 +944,7 @@ public abstract class AbstractLuceneIndexerAndSearcherFactory implements LuceneI * * @param queryMaxClauses */ + @Override public void setQueryMaxClauses(int queryMaxClauses) { this.queryMaxClauses = queryMaxClauses; @@ -951,6 +956,7 @@ public abstract class AbstractLuceneIndexerAndSearcherFactory implements LuceneI * * @param timeout */ + @Override public void setWriteLockTimeout(long timeout) { this.writeLockTimeout = timeout; @@ -961,6 +967,7 @@ public abstract class AbstractLuceneIndexerAndSearcherFactory implements LuceneI * * @param timeout */ + @Override public void setCommitLockTimeout(long timeout) { this.commitLockTimeout = timeout; @@ -971,6 +978,7 @@ public abstract class AbstractLuceneIndexerAndSearcherFactory implements LuceneI * * @return - the timeout */ + @Override public long getCommitLockTimeout() { return commitLockTimeout; @@ -981,6 +989,7 @@ public abstract class AbstractLuceneIndexerAndSearcherFactory implements LuceneI * * @return - the timeout in ms */ + @Override public long getWriteLockTimeout() { return writeLockTimeout; @@ -991,6 +1000,7 @@ public abstract class AbstractLuceneIndexerAndSearcherFactory implements LuceneI * * @param time */ + @Override public void setLockPollInterval(long time) { Lock.LOCK_POLL_INTERVAL = time; @@ -1001,6 +1011,7 @@ public abstract class AbstractLuceneIndexerAndSearcherFactory implements LuceneI * * @return - the max tokens considered. */ + @Override public int getIndexerMaxFieldLength() { return indexerMaxFieldLength; @@ -1011,6 +1022,7 @@ public abstract class AbstractLuceneIndexerAndSearcherFactory implements LuceneI * * @param indexerMaxFieldLength */ + @Override public void setIndexerMaxFieldLength(int indexerMaxFieldLength) { this.indexerMaxFieldLength = indexerMaxFieldLength; @@ -1567,6 +1579,7 @@ public abstract class AbstractLuceneIndexerAndSearcherFactory implements LuceneI } } + @Override public MLAnalysisMode getDefaultMLIndexAnalysisMode() { return defaultMLIndexAnalysisMode; @@ -1577,12 +1590,14 @@ public abstract class AbstractLuceneIndexerAndSearcherFactory implements LuceneI * * @param mode */ + @Override public void setDefaultMLIndexAnalysisMode(MLAnalysisMode mode) { // defaultMLIndexAnalysisMode = MLAnalysisMode.getMLAnalysisMode(mode); defaultMLIndexAnalysisMode = mode; } + @Override public MLAnalysisMode getDefaultMLSearchAnalysisMode() { return defaultMLSearchAnalysisMode; @@ -1593,241 +1608,281 @@ public abstract class AbstractLuceneIndexerAndSearcherFactory implements LuceneI * * @param mode */ + @Override public void setDefaultMLSearchAnalysisMode(MLAnalysisMode mode) { // defaultMLSearchAnalysisMode = MLAnalysisMode.getMLAnalysisMode(mode); defaultMLSearchAnalysisMode = mode; } + @Override public int getMaxDocIdCacheSize() { return maxDocIdCacheSize; } + @Override public void setMaxDocIdCacheSize(int maxDocIdCacheSize) { this.maxDocIdCacheSize = maxDocIdCacheSize; } + @Override public int getMaxDocsForInMemoryMerge() { return maxDocsForInMemoryMerge; } + @Override public void setMaxDocsForInMemoryMerge(int maxDocsForInMemoryMerge) { this.maxDocsForInMemoryMerge = maxDocsForInMemoryMerge; } + @Override public int getMaxDocumentCacheSize() { return maxDocumentCacheSize; } + @Override public void setMaxDocumentCacheSize(int maxDocumentCacheSize) { this.maxDocumentCacheSize = maxDocumentCacheSize; } + @Override public int getMaxIsCategoryCacheSize() { return maxIsCategoryCacheSize; } + @Override public void setMaxIsCategoryCacheSize(int maxIsCategoryCacheSize) { this.maxIsCategoryCacheSize = maxIsCategoryCacheSize; } + @Override public int getMaxLinkAspectCacheSize() { return maxLinkAspectCacheSize; } + @Override public void setMaxLinkAspectCacheSize(int maxLinkAspectCacheSize) { this.maxLinkAspectCacheSize = maxLinkAspectCacheSize; } + @Override public int getMaxParentCacheSize() { return maxParentCacheSize; } + @Override public void setMaxParentCacheSize(int maxParentCacheSize) { this.maxParentCacheSize = maxParentCacheSize; } + @Override public int getMaxPathCacheSize() { return maxPathCacheSize; } + @Override public void setMaxPathCacheSize(int maxPathCacheSize) { this.maxPathCacheSize = maxPathCacheSize; } + @Override public int getMaxTypeCacheSize() { return maxTypeCacheSize; } + @Override public void setMaxTypeCacheSize(int maxTypeCacheSize) { this.maxTypeCacheSize = maxTypeCacheSize; } + @Override public int getMergerMaxMergeDocs() { return mergerMaxMergeDocs; } + @Override public void setMergerMaxMergeDocs(int mergerMaxMergeDocs) { this.mergerMaxMergeDocs = mergerMaxMergeDocs; } + @Override public int getMergerMergeFactor() { return mergerMergeFactor; } + @Override public void setMergerMergeFactor(int mergerMergeFactor) { this.mergerMergeFactor = mergerMergeFactor; } - + @Override public int getMergerMaxBufferedDocs() { return mergerMaxBufferedDocs; } + @Override public void setMergerMaxBufferedDocs(int mergerMaxBufferedDocs) { this.mergerMaxBufferedDocs = mergerMaxBufferedDocs; } + @Override public int getMergerTargetIndexCount() { return mergerTargetIndexCount; } + @Override public void setMergerTargetIndexCount(int mergerTargetIndexCount) { this.mergerTargetIndexCount = mergerTargetIndexCount; } + @Override public int getMergerTargetOverlayCount() { return mergerTargetOverlayCount; } + @Override public void setMergerTargetOverlayCount(int mergerTargetOverlayCount) { this.mergerTargetOverlayCount = mergerTargetOverlayCount; } + @Override public int getMergerTargetOverlaysBlockingFactor() { return mergerTargetOverlaysBlockingFactor; } + @Override public void setMergerTargetOverlaysBlockingFactor(int mergerTargetOverlaysBlockingFactor) { this.mergerTargetOverlaysBlockingFactor = mergerTargetOverlaysBlockingFactor; } + @Override public boolean getFairLocking() { return this.fairLocking; } + @Override public void setFairLocking(boolean fairLocking) { this.fairLocking = fairLocking; } + @Override public int getTermIndexInterval() { return termIndexInterval; } + @Override public void setTermIndexInterval(int termIndexInterval) { this.termIndexInterval = termIndexInterval; } + @Override public boolean getUseNioMemoryMapping() { return useNioMemoryMapping; } + @Override public void setUseNioMemoryMapping(boolean useNioMemoryMapping) { this.useNioMemoryMapping = useNioMemoryMapping; } + @Override public int getWriterMaxMergeDocs() { return writerMaxMergeDocs; } + @Override public void setWriterMaxMergeDocs(int writerMaxMergeDocs) { this.writerMaxMergeDocs = writerMaxMergeDocs; } + @Override public int getWriterMergeFactor() { return writerMergeFactor; } + @Override public void setWriterMergeFactor(int writerMergeFactor) { this.writerMergeFactor = writerMergeFactor; } + @Override public int getWriterMaxBufferedDocs() { return writerMaxBufferedDocs; } + @Override public void setWriterMaxBufferedDocs(int writerMaxBufferedDocs) { this.writerMaxBufferedDocs = writerMaxBufferedDocs; } + @Override public boolean isCacheEnabled() { return cacheEnabled; } + @Override public void setCacheEnabled(boolean cacheEnabled) { this.cacheEnabled = cacheEnabled; } + @Override public boolean getPostSortDateTime() { return postSortDateTime; } + @Override public void setPostSortDateTime(boolean postSortDateTime) { this.postSortDateTime = postSortDateTime; } - public void registerQueryLanguage(LuceneQueryLanguageSPI queryLanguage) - { - this.queryLanguages.put(queryLanguage.getName().toLowerCase(), queryLanguage); - } - /** * @return the maxDocsForInMemoryIndex */ + @Override public int getMaxDocsForInMemoryIndex() { return maxDocsForInMemoryIndex; @@ -1837,6 +1892,7 @@ public abstract class AbstractLuceneIndexerAndSearcherFactory implements LuceneI * @param maxDocsForInMemoryIndex * the maxDocsForInMemoryIndex to set */ + @Override public void setMaxDocsForInMemoryIndex(int maxDocsForInMemoryIndex) { this.maxDocsForInMemoryIndex = maxDocsForInMemoryIndex; @@ -1845,6 +1901,7 @@ public abstract class AbstractLuceneIndexerAndSearcherFactory implements LuceneI /** * @return the maxRamInMbForInMemoryMerge */ + @Override public double getMaxRamInMbForInMemoryMerge() { return maxRamInMbForInMemoryMerge; @@ -1854,6 +1911,7 @@ public abstract class AbstractLuceneIndexerAndSearcherFactory implements LuceneI * @param maxRamInMbForInMemoryMerge * the maxRamInMbForInMemoryMerge to set */ + @Override public void setMaxRamInMbForInMemoryMerge(double maxRamInMbForInMemoryMerge) { this.maxRamInMbForInMemoryMerge = maxRamInMbForInMemoryMerge; @@ -1862,6 +1920,7 @@ public abstract class AbstractLuceneIndexerAndSearcherFactory implements LuceneI /** * @return the maxRamInMbForInMemoryIndex */ + @Override public double getMaxRamInMbForInMemoryIndex() { return maxRamInMbForInMemoryIndex; @@ -1871,6 +1930,7 @@ public abstract class AbstractLuceneIndexerAndSearcherFactory implements LuceneI * @param maxRamInMbForInMemoryIndex * the maxRamInMbForInMemoryIndex to set */ + @Override public void setMaxRamInMbForInMemoryIndex(double maxRamInMbForInMemoryIndex) { this.maxRamInMbForInMemoryIndex = maxRamInMbForInMemoryIndex; @@ -1879,6 +1939,7 @@ public abstract class AbstractLuceneIndexerAndSearcherFactory implements LuceneI /** * @return the mergerRamBufferSizeMb */ + @Override public double getMergerRamBufferSizeMb() { return mergerRamBufferSizeMb; @@ -1888,6 +1949,7 @@ public abstract class AbstractLuceneIndexerAndSearcherFactory implements LuceneI * @param mergerRamBufferSizeMb * the mergerRamBufferSizeMb to set */ + @Override public void setMergerRamBufferSizeMb(double mergerRamBufferSizeMb) { this.mergerRamBufferSizeMb = mergerRamBufferSizeMb; @@ -1896,6 +1958,7 @@ public abstract class AbstractLuceneIndexerAndSearcherFactory implements LuceneI /** * @return the writerRamBufferSizeMb */ + @Override public double getWriterRamBufferSizeMb() { return writerRamBufferSizeMb; @@ -1905,6 +1968,7 @@ public abstract class AbstractLuceneIndexerAndSearcherFactory implements LuceneI * @param writerRamBufferSizeMb * the writerRamBufferSizeMb to set */ + @Override public void setWriterRamBufferSizeMb(double writerRamBufferSizeMb) { this.writerRamBufferSizeMb = writerRamBufferSizeMb; @@ -1912,7 +1976,7 @@ public abstract class AbstractLuceneIndexerAndSearcherFactory implements LuceneI protected LuceneQueryLanguageSPI getQueryLanguage(String name) { - return this.queryLanguages.get(name); + return getQueryLanguages().get(name); } protected abstract List getAllStores(); diff --git a/source/java/org/alfresco/repo/search/impl/lucene/AbstractLuceneQueryLanguage.java b/source/java/org/alfresco/repo/search/impl/lucene/AbstractLuceneQueryLanguage.java new file mode 100644 index 0000000000..cb45d82d66 --- /dev/null +++ b/source/java/org/alfresco/repo/search/impl/lucene/AbstractLuceneQueryLanguage.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2005-2010 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ +package org.alfresco.repo.search.impl.lucene; + +import java.util.List; + +import org.alfresco.repo.search.IndexerAndSearcher; +import org.springframework.beans.factory.InitializingBean; + +/** + * @author Andy + * + */ +public abstract class AbstractLuceneQueryLanguage implements LuceneQueryLanguageSPI, InitializingBean +{ + private String name; + + private List factories; + + /* (non-Javadoc) + * @see org.alfresco.repo.search.impl.lucene.LuceneQueryLanguageSPI#setFactories(java.util.List) + */ + @Override + final public void setFactories(List factories) + { + this.factories = factories; + } + + @Override + public void afterPropertiesSet() throws Exception + { + for (IndexerAndSearcher factory : factories) + { + factory.registerQueryLanguage(this); + } + + } + + public final String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + } + + public List getFactories() + { + return factories; + } + + + +} diff --git a/source/java/org/alfresco/repo/search/impl/lucene/LuceneAlfrescoFtsQueryLanguage.java b/source/java/org/alfresco/repo/search/impl/lucene/LuceneAlfrescoFtsQueryLanguage.java index 64d6f54227..45d7073911 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/LuceneAlfrescoFtsQueryLanguage.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/LuceneAlfrescoFtsQueryLanguage.java @@ -23,6 +23,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import org.alfresco.repo.search.IndexerAndSearcher; import org.alfresco.repo.search.impl.parsers.AlfrescoFunctionEvaluationContext; import org.alfresco.repo.search.impl.parsers.FTSParser; import org.alfresco.repo.search.impl.parsers.FTSQueryParser; @@ -52,10 +53,15 @@ import org.alfresco.service.cmr.search.SearchParameters.SortDefinition.SortType; * * @author andyh */ -public class LuceneAlfrescoFtsQueryLanguage implements LuceneQueryLanguageSPI +public class LuceneAlfrescoFtsQueryLanguage extends AbstractLuceneQueryLanguage { QueryEngine queryEngine; + public LuceneAlfrescoFtsQueryLanguage() + { + this.setName(SearchService.LANGUAGE_FTS_ALFRESCO); + } + /** * Set the query engine * @@ -113,19 +119,6 @@ public class LuceneAlfrescoFtsQueryLanguage implements LuceneQueryLanguageSPI return resultSet; } - public String getName() - { - return SearchService.LANGUAGE_FTS_ALFRESCO; - } - - public void setFactories(List factories) - { - for (AbstractLuceneIndexerAndSearcherFactory factory : factories) - { - factory.registerQueryLanguage(this); - } - } - public List buildOrderings(QueryModelFactory factory, SearchParameters searchParameters) { List orderings = new ArrayList(searchParameters.getSortDefinitions().size()); diff --git a/source/java/org/alfresco/repo/search/impl/lucene/LuceneAlfrescoLuceneQueryLanguage.java b/source/java/org/alfresco/repo/search/impl/lucene/LuceneAlfrescoLuceneQueryLanguage.java index 5770d67b82..d8c2f472ed 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/LuceneAlfrescoLuceneQueryLanguage.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/LuceneAlfrescoLuceneQueryLanguage.java @@ -71,10 +71,15 @@ import org.apache.lucene.search.SortField; * * @author andyh */ -public class LuceneAlfrescoLuceneQueryLanguage implements LuceneQueryLanguageSPI +public class LuceneAlfrescoLuceneQueryLanguage extends AbstractLuceneQueryLanguage { static Log s_logger = LogFactory.getLog(LuceneAlfrescoLuceneQueryLanguage.class); + public LuceneAlfrescoLuceneQueryLanguage() + { + this.setName(SearchService.LANGUAGE_LUCENE); + } + public ResultSet executeQuery(SearchParameters searchParameters, ADMLuceneSearcherImpl admLuceneSearcher) { try @@ -249,16 +254,4 @@ public class LuceneAlfrescoLuceneQueryLanguage implements LuceneQueryLanguageSPI } } - public String getName() - { - return SearchService.LANGUAGE_LUCENE; - } - - public void setFactories(List factories) - { - for (AbstractLuceneIndexerAndSearcherFactory factory : factories) - { - factory.registerQueryLanguage(this); - } - } } diff --git a/source/java/org/alfresco/repo/search/impl/lucene/LuceneAlfrescoSqlQueryLanguage.java b/source/java/org/alfresco/repo/search/impl/lucene/LuceneAlfrescoSqlQueryLanguage.java index 64178e0d14..2dc3ccd278 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/LuceneAlfrescoSqlQueryLanguage.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/LuceneAlfrescoSqlQueryLanguage.java @@ -37,10 +37,15 @@ import org.alfresco.service.cmr.search.SearchService; * @author andyh * */ -public class LuceneAlfrescoSqlQueryLanguage implements LuceneQueryLanguageSPI +public class LuceneAlfrescoSqlQueryLanguage extends AbstractLuceneQueryLanguage { private CMISQueryService cmisQueryService; + public LuceneAlfrescoSqlQueryLanguage() + { + this.setName(SearchService.LANGUAGE_CMIS_ALFRESCO); + } + /** * Set the search service * @@ -80,17 +85,4 @@ public class LuceneAlfrescoSqlQueryLanguage implements LuceneQueryLanguageSPI return new ResultSetSPIWrapper(cmisQueryService.query(options)); } - public String getName() - { - return SearchService.LANGUAGE_CMIS_ALFRESCO; - } - - public void setFactories(List factories) - { - for (AbstractLuceneIndexerAndSearcherFactory factory : factories) - { - factory.registerQueryLanguage(this); - } - } - } diff --git a/source/java/org/alfresco/repo/search/impl/lucene/LuceneAlfrescoXPathQueryLanguage.java b/source/java/org/alfresco/repo/search/impl/lucene/LuceneAlfrescoXPathQueryLanguage.java index 4826130a13..37ab6e92b2 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/LuceneAlfrescoXPathQueryLanguage.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/LuceneAlfrescoXPathQueryLanguage.java @@ -61,9 +61,12 @@ import com.werken.saxpath.XPathReader; * * @author andyh */ -public class LuceneAlfrescoXPathQueryLanguage implements LuceneQueryLanguageSPI +public class LuceneAlfrescoXPathQueryLanguage extends AbstractLuceneQueryLanguage { - + public LuceneAlfrescoXPathQueryLanguage() + { + this.setName(SearchService.LANGUAGE_XPATH); + } public ResultSet executeQuery(SearchParameters searchParameters, ADMLuceneSearcherImpl admLuceneSearcher) { @@ -100,19 +103,4 @@ public class LuceneAlfrescoXPathQueryLanguage implements LuceneQueryLanguageSPI throw new SearcherException("IO exception during search", e); } } - - public String getName() - { - return SearchService.LANGUAGE_XPATH; - } - - public void setFactories(List factories) - { - for (AbstractLuceneIndexerAndSearcherFactory factory : factories) - { - factory.registerQueryLanguage(this); - } - } - - } diff --git a/source/java/org/alfresco/repo/search/impl/lucene/LuceneCmisStrictSqlQueryLanguage.java b/source/java/org/alfresco/repo/search/impl/lucene/LuceneCmisStrictSqlQueryLanguage.java index 52092efdf3..ce5edac5cc 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/LuceneCmisStrictSqlQueryLanguage.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/LuceneCmisStrictSqlQueryLanguage.java @@ -37,10 +37,15 @@ import org.alfresco.service.cmr.search.SearchService; * @author andyh * */ -public class LuceneCmisStrictSqlQueryLanguage implements LuceneQueryLanguageSPI +public class LuceneCmisStrictSqlQueryLanguage extends AbstractLuceneQueryLanguage { private CMISQueryService cmisQueryService; + public LuceneCmisStrictSqlQueryLanguage() + { + this.setName(SearchService.LANGUAGE_CMIS_STRICT); + } + /** * Set the search service * @@ -79,17 +84,4 @@ public class LuceneCmisStrictSqlQueryLanguage implements LuceneQueryLanguageSPI return new ResultSetSPIWrapper(cmisQueryService.query(options)); } - public String getName() - { - return SearchService.LANGUAGE_CMIS_STRICT; - } - - public void setFactories(List factories) - { - for (AbstractLuceneIndexerAndSearcherFactory factory : factories) - { - factory.registerQueryLanguage(this); - } - } - } diff --git a/source/java/org/alfresco/repo/search/impl/lucene/LuceneConfig.java b/source/java/org/alfresco/repo/search/impl/lucene/LuceneConfig.java index e87b0a0ab4..a755b15fb7 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/LuceneConfig.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/LuceneConfig.java @@ -268,4 +268,199 @@ public interface LuceneConfig */ public boolean getFairLocking(); + /** + * @param maxAtomicTransformationTime + */ + void setMaxAtomicTransformationTime(long maxAtomicTransformationTime); + + /** + * @return + */ + long getMaxTransformationTime(); + + /** + * @param indexerBatchSize + */ + void setIndexerBatchSize(int indexerBatchSize); + + /** + * @param queryMaxClauses + */ + void setQueryMaxClauses(int queryMaxClauses); + + /** + * @param timeout + */ + void setWriteLockTimeout(long timeout); + + /** + * @param timeout + */ + void setCommitLockTimeout(long timeout); + + /** + * @return + */ + long getCommitLockTimeout(); + + /** + * @return + */ + long getWriteLockTimeout(); + + /** + * @param time + */ + void setLockPollInterval(long time); + + /** + * @param indexerMaxFieldLength + */ + void setIndexerMaxFieldLength(int indexerMaxFieldLength); + + /** + * @param mode + */ + void setDefaultMLIndexAnalysisMode(MLAnalysisMode mode); + + /** + * @param mode + */ + void setDefaultMLSearchAnalysisMode(MLAnalysisMode mode); + + /** + * @param maxDocIdCacheSize + */ + void setMaxDocIdCacheSize(int maxDocIdCacheSize); + + /** + * @param maxDocsForInMemoryMerge + */ + void setMaxDocsForInMemoryMerge(int maxDocsForInMemoryMerge); + + /** + * @param maxDocumentCacheSize + */ + void setMaxDocumentCacheSize(int maxDocumentCacheSize); + + /** + * @param maxIsCategoryCacheSize + */ + void setMaxIsCategoryCacheSize(int maxIsCategoryCacheSize); + + /** + * @param maxLinkAspectCacheSize + */ + void setMaxLinkAspectCacheSize(int maxLinkAspectCacheSize); + + /** + * @param maxParentCacheSize + */ + void setMaxParentCacheSize(int maxParentCacheSize); + + /** + * @param maxPathCacheSize + */ + void setMaxPathCacheSize(int maxPathCacheSize); + + /** + * @param maxTypeCacheSize + */ + void setMaxTypeCacheSize(int maxTypeCacheSize); + + /** + * @param mergerMaxMergeDocs + */ + void setMergerMaxMergeDocs(int mergerMaxMergeDocs); + + /** + * @param mergerMergeFactor + */ + void setMergerMergeFactor(int mergerMergeFactor); + + /** + * @param mergerMaxBufferedDocs + */ + void setMergerMaxBufferedDocs(int mergerMaxBufferedDocs); + + /** + * @param mergerTargetIndexCount + */ + void setMergerTargetIndexCount(int mergerTargetIndexCount); + + /** + * @param mergerTargetOverlayCount + */ + void setMergerTargetOverlayCount(int mergerTargetOverlayCount); + + /** + * @param mergerTargetOverlaysBlockingFactor + */ + void setMergerTargetOverlaysBlockingFactor(int mergerTargetOverlaysBlockingFactor); + + /** + * @param fairLocking + */ + void setFairLocking(boolean fairLocking); + + /** + * @param termIndexInterval + */ + void setTermIndexInterval(int termIndexInterval); + + /** + * @param useNioMemoryMapping + */ + void setUseNioMemoryMapping(boolean useNioMemoryMapping); + + /** + * @param writerMaxMergeDocs + */ + void setWriterMaxMergeDocs(int writerMaxMergeDocs); + + /** + * @param writerMergeFactor + */ + void setWriterMergeFactor(int writerMergeFactor); + + /** + * @param writerMaxBufferedDocs + */ + void setWriterMaxBufferedDocs(int writerMaxBufferedDocs); + + /** + * @param cacheEnabled + */ + void setCacheEnabled(boolean cacheEnabled); + + /** + * @param postSortDateTime + */ + void setPostSortDateTime(boolean postSortDateTime); + + /** + * @param maxDocsForInMemoryIndex + */ + void setMaxDocsForInMemoryIndex(int maxDocsForInMemoryIndex); + + /** + * @param maxRamInMbForInMemoryMerge + */ + void setMaxRamInMbForInMemoryMerge(double maxRamInMbForInMemoryMerge); + + /** + * @param maxRamInMbForInMemoryIndex + */ + void setMaxRamInMbForInMemoryIndex(double maxRamInMbForInMemoryIndex); + + /** + * @param mergerRamBufferSizeMb + */ + void setMergerRamBufferSizeMb(double mergerRamBufferSizeMb); + + /** + * @param writerRamBufferSizeMb + */ + void setWriterRamBufferSizeMb(double writerRamBufferSizeMb); + } diff --git a/source/java/org/alfresco/repo/search/impl/lucene/LuceneOpenCMISAlfrescoSqlQueryLanguage.java b/source/java/org/alfresco/repo/search/impl/lucene/LuceneOpenCMISAlfrescoSqlQueryLanguage.java index a789df3b4e..709b1e50e0 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/LuceneOpenCMISAlfrescoSqlQueryLanguage.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/LuceneOpenCMISAlfrescoSqlQueryLanguage.java @@ -38,10 +38,15 @@ import org.alfresco.service.cmr.search.SearchService; * @author andyh * */ -public class LuceneOpenCMISAlfrescoSqlQueryLanguage implements LuceneQueryLanguageSPI +public class LuceneOpenCMISAlfrescoSqlQueryLanguage extends AbstractLuceneQueryLanguage { private CMISQueryService cmisQueryService; + public LuceneOpenCMISAlfrescoSqlQueryLanguage() + { + this.setName(SearchService.LANGUAGE_CMIS_ALFRESCO); + } + /** * Set the search service * @@ -81,18 +86,4 @@ public class LuceneOpenCMISAlfrescoSqlQueryLanguage implements LuceneQueryLangua return new ResultSetSPIWrapper(cmisQueryService.query(options)); } - - public String getName() - { - return SearchService.LANGUAGE_CMIS_ALFRESCO; - } - - public void setFactories(List factories) - { - for (AbstractLuceneIndexerAndSearcherFactory factory : factories) - { - factory.registerQueryLanguage(this); - } - } - } diff --git a/source/java/org/alfresco/repo/search/impl/lucene/LuceneOpenCMISStrictSqlQueryLanguage.java b/source/java/org/alfresco/repo/search/impl/lucene/LuceneOpenCMISStrictSqlQueryLanguage.java index 6057ff4a8c..7fc4a535bd 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/LuceneOpenCMISStrictSqlQueryLanguage.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/LuceneOpenCMISStrictSqlQueryLanguage.java @@ -38,10 +38,15 @@ import org.alfresco.service.cmr.search.SearchService; * @author andyh * */ -public class LuceneOpenCMISStrictSqlQueryLanguage implements LuceneQueryLanguageSPI +public class LuceneOpenCMISStrictSqlQueryLanguage extends AbstractLuceneQueryLanguage { private CMISQueryService cmisQueryService; + public LuceneOpenCMISStrictSqlQueryLanguage() + { + this.setName(SearchService.LANGUAGE_CMIS_STRICT); + } + /** * Set the search service * @@ -80,18 +85,4 @@ public class LuceneOpenCMISStrictSqlQueryLanguage implements LuceneQueryLanguage return new ResultSetSPIWrapper(cmisQueryService.query(options)); } - - public String getName() - { - return SearchService.LANGUAGE_CMIS_STRICT; - } - - public void setFactories(List factories) - { - for (AbstractLuceneIndexerAndSearcherFactory factory : factories) - { - factory.registerQueryLanguage(this); - } - } - } diff --git a/source/java/org/alfresco/repo/search/impl/lucene/LuceneQueryLanguageSPI.java b/source/java/org/alfresco/repo/search/impl/lucene/LuceneQueryLanguageSPI.java index 272a0e3354..4b1a026f38 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/LuceneQueryLanguageSPI.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/LuceneQueryLanguageSPI.java @@ -20,6 +20,7 @@ package org.alfresco.repo.search.impl.lucene; import java.util.List; +import org.alfresco.repo.search.IndexerAndSearcher; import org.alfresco.repo.search.impl.querymodel.QueryOptions; import org.alfresco.service.cmr.search.ResultSet; import org.alfresco.service.cmr.search.SearchParameters; @@ -48,5 +49,5 @@ public interface LuceneQueryLanguageSPI /** * Register */ - public void setFactories(List factories); + public void setFactories(List factories); } diff --git a/source/java/org/alfresco/repo/search/impl/lucene/SolrAlfrescoFTSQueryLanguage.java b/source/java/org/alfresco/repo/search/impl/solr/SolrAlfrescoFTSQueryLanguage.java similarity index 95% rename from source/java/org/alfresco/repo/search/impl/lucene/SolrAlfrescoFTSQueryLanguage.java rename to source/java/org/alfresco/repo/search/impl/solr/SolrAlfrescoFTSQueryLanguage.java index 87ce3a04bd..75adecfd9b 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/SolrAlfrescoFTSQueryLanguage.java +++ b/source/java/org/alfresco/repo/search/impl/solr/SolrAlfrescoFTSQueryLanguage.java @@ -16,7 +16,7 @@ * You should have received a copy of the GNU Lesser General Public License * along with Alfresco. If not, see . */ -package org.alfresco.repo.search.impl.lucene; +package org.alfresco.repo.search.impl.solr; import java.io.BufferedReader; import java.io.IOException; @@ -29,6 +29,10 @@ import java.util.Locale; import javax.servlet.http.HttpServletResponse; import org.alfresco.repo.domain.node.NodeDAO; +import org.alfresco.repo.search.impl.lucene.ADMLuceneSearcherImpl; +import org.alfresco.repo.search.impl.lucene.AbstractLuceneQueryLanguage; +import org.alfresco.repo.search.impl.lucene.LuceneQueryParserException; +import org.alfresco.repo.search.impl.lucene.SolrJSONResultSet; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; import org.alfresco.service.cmr.search.ResultSet; @@ -57,7 +61,7 @@ import org.springframework.extensions.surf.util.I18NUtil; /** * @author Andy */ -public class SolrAlfrescoFTSQueryLanguage implements LuceneQueryLanguageSPI +public class SolrAlfrescoFTSQueryLanguage extends AbstractLuceneQueryLanguage { static Log s_logger = LogFactory.getLog(SolrAlfrescoFTSQueryLanguage.class); @@ -65,6 +69,11 @@ public class SolrAlfrescoFTSQueryLanguage implements LuceneQueryLanguageSPI private PermissionService permissionService; + public SolrAlfrescoFTSQueryLanguage() + { + this.setName(SearchService.LANGUAGE_SOLR_FTS_ALFRESCO); + } + /** * @param nodeDAO the nodeDAO to set */ @@ -258,19 +267,6 @@ public class SolrAlfrescoFTSQueryLanguage implements LuceneQueryLanguageSPI } } - public String getName() - { - return SearchService.LANGUAGE_SOLR_FTS_ALFRESCO; - } - - public void setFactories(List factories) - { - for (AbstractLuceneIndexerAndSearcherFactory factory : factories) - { - factory.registerQueryLanguage(this); - } - } - public static void main(String[] args) { SolrAlfrescoFTSQueryLanguage solrAlfrescoFTSQueryLanguage = new SolrAlfrescoFTSQueryLanguage(); diff --git a/source/java/org/alfresco/repo/search/impl/lucene/SolrCMISQueryLanguage.java b/source/java/org/alfresco/repo/search/impl/solr/SolrCMISQueryLanguage.java similarity index 77% rename from source/java/org/alfresco/repo/search/impl/lucene/SolrCMISQueryLanguage.java rename to source/java/org/alfresco/repo/search/impl/solr/SolrCMISQueryLanguage.java index af91bf1385..e1507157ab 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/SolrCMISQueryLanguage.java +++ b/source/java/org/alfresco/repo/search/impl/solr/SolrCMISQueryLanguage.java @@ -16,26 +16,28 @@ * You should have received a copy of the GNU Lesser General Public License * along with Alfresco. If not, see . */ -package org.alfresco.repo.search.impl.lucene; +package org.alfresco.repo.search.impl.solr; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.Reader; import java.io.UnsupportedEncodingException; -import java.util.List; import java.util.Locale; import javax.servlet.http.HttpServletResponse; import org.alfresco.repo.domain.node.NodeDAO; -import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.search.impl.lucene.ADMLuceneSearcherImpl; +import org.alfresco.repo.search.impl.lucene.AbstractLuceneQueryLanguage; +import org.alfresco.repo.search.impl.lucene.LuceneQueryParserException; +import org.alfresco.repo.search.impl.lucene.SolrJSONResultSet; import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; import org.alfresco.service.cmr.search.ResultSet; import org.alfresco.service.cmr.search.ResultSetRow; import org.alfresco.service.cmr.search.SearchParameters; -import org.alfresco.service.cmr.search.SearchService; import org.alfresco.service.cmr.search.SearchParameters.SortDefinition; +import org.alfresco.service.cmr.search.SearchService; import org.alfresco.service.cmr.security.PermissionService; import org.apache.commons.codec.net.URLCodec; import org.apache.commons.httpclient.HttpClient; @@ -44,7 +46,6 @@ import org.apache.commons.httpclient.UsernamePasswordCredentials; import org.apache.commons.httpclient.auth.AuthScope; import org.apache.commons.httpclient.methods.ByteArrayRequestEntity; import org.apache.commons.httpclient.methods.PostMethod; -import org.apache.commons.httpclient.methods.RequestEntity; import org.apache.commons.httpclient.params.HttpClientParams; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -57,16 +58,22 @@ import org.springframework.extensions.surf.util.I18NUtil; /** * @author Andy */ -public class SolrCMISQueryLanguage implements LuceneQueryLanguageSPI +public class SolrCMISQueryLanguage extends AbstractLuceneQueryLanguage { static Log s_logger = LogFactory.getLog(SolrCMISQueryLanguage.class); - + private NodeDAO nodeDAO; - + private PermissionService permissionService; + + public SolrCMISQueryLanguage() + { + this.setName(SearchService.LANGUAGE_SOLR_CMIS); + } /** - * @param nodeDAO the nodeDAO to set + * @param nodeDAO + * the nodeDAO to set */ public void setNodeDAO(NodeDAO nodeDAO) { @@ -74,7 +81,8 @@ public class SolrCMISQueryLanguage implements LuceneQueryLanguageSPI } /** - * @param permissionService the permissionService to set + * @param permissionService + * the permissionService to set */ public void setPermissionService(PermissionService permissionService) { @@ -96,13 +104,13 @@ public class SolrCMISQueryLanguage implements LuceneQueryLanguageSPI httpClient.getState().setCredentials(new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT), new UsernamePasswordCredentials("admin", "admin")); StringBuilder url = new StringBuilder("http://localhost:8080/solr/alfresco/cmis"); - //duplicate the query in the URL + // duplicate the query in the URL url.append("?q="); URLCodec encoder = new URLCodec(); url.append(encoder.encode(searchParameters.getQuery(), "UTF-8")); url.append("&wt=json"); url.append("&fl=*,score"); - if(searchParameters.getMaxItems() > 0) + if (searchParameters.getMaxItems() > 0) { url.append("&rows=").append(searchParameters.getMaxItems()); } @@ -112,23 +120,22 @@ public class SolrCMISQueryLanguage implements LuceneQueryLanguageSPI } url.append("&df=").append(searchParameters.getDefaultFieldName()); url.append("&start=").append(searchParameters.getSkipCount()); - + Locale locale = I18NUtil.getLocale(); - if(searchParameters.getLocales().size() > 0) + if (searchParameters.getLocales().size() > 0) { locale = searchParameters.getLocales().get(0); } url.append("&locale="); encoder = new URLCodec(); url.append(encoder.encode(locale.toString(), "UTF-8")); - - + // Will use this search if not specified as part of the query )no order by clause) // If the query contains an order by clause this will be used instead. StringBuffer sortBuffer = new StringBuffer(); - for(SortDefinition sortDefinition : searchParameters.getSortDefinitions()) + for (SortDefinition sortDefinition : searchParameters.getSortDefinitions()) { - if(sortBuffer.length() == 0) + if (sortBuffer.length() == 0) { sortBuffer.append("&sort="); } @@ -137,7 +144,7 @@ public class SolrCMISQueryLanguage implements LuceneQueryLanguageSPI sortBuffer.append(", "); } sortBuffer.append(sortDefinition.getField()).append(" "); - if(sortDefinition.isAscending()) + if (sortDefinition.isAscending()) { sortBuffer.append("asc"); } @@ -145,53 +152,52 @@ public class SolrCMISQueryLanguage implements LuceneQueryLanguageSPI { sortBuffer.append("desc"); } - + } url.append(sortBuffer); - + // Authorities go over in body - + StringBuilder authQuery = new StringBuilder(); - for(String authority : permissionService.getAuthorisations()) + for (String authority : permissionService.getAuthorisations()) { - if(authQuery.length() > 0) + if (authQuery.length() > 0) { authQuery.append(" "); } authQuery.append("AUTHORITY:\"").append(authority).append("\""); } - - //url.append("&fq="); - //encoder = new URLCodec(); - //url.append(encoder.encode(authQuery.toString(), "UTF-8")); - + + // url.append("&fq="); + // encoder = new URLCodec(); + // url.append(encoder.encode(authQuery.toString(), "UTF-8")); + url.append("&fq="); url.append(encoder.encode("{!afts}", "UTF-8")); url.append("AUTHORITY_FILTER_FROM_JSON"); - + // facets would go on url? - + JSONObject body = new JSONObject(); body.put("query", searchParameters.getQuery()); - //body.put("defaultField", searchParameters.getDefaultFieldName()); - + // body.put("defaultField", searchParameters.getDefaultFieldName()); + body.put("filter", authQuery); - + JSONArray locales = new JSONArray(); - for(Locale currentLocale : searchParameters.getLocales()) + for (Locale currentLocale : searchParameters.getLocales()) { locales.put(DefaultTypeConverter.INSTANCE.convert(String.class, currentLocale)); } - if(locales.length() == 0) + if (locales.length() == 0) { locales.put(I18NUtil.getLocale()); } body.put("locales", locales); - - + // templates etc may affect CONTAINS() clause JSONArray templates = new JSONArray(); - for(String templateName : searchParameters.getQueryTemplates().keySet()) + for (String templateName : searchParameters.getQueryTemplates().keySet()) { JSONObject template = new JSONObject(); template.put("name", templateName); @@ -199,52 +205,50 @@ public class SolrCMISQueryLanguage implements LuceneQueryLanguageSPI templates.put(template); } body.put("templates", templates); - + JSONArray allAttributes = new JSONArray(); - for(String attribute : searchParameters.getAllAttributes()) + for (String attribute : searchParameters.getAllAttributes()) { allAttributes.put(attribute); } body.put("allAttributes", allAttributes); - + body.put("defaultFTSOperator", searchParameters.getDefaultFTSOperator()); body.put("defaultFTSFieldOperator", searchParameters.getDefaultFTSFieldOperator()); - if(searchParameters.getMlAnalaysisMode() != null) + if (searchParameters.getMlAnalaysisMode() != null) { body.put("mlAnalaysisMode", searchParameters.getMlAnalaysisMode().toString()); } body.put("defaultNamespace", searchParameters.getNamespace()); - - + JSONArray textAttributes = new JSONArray(); - for(String attribute : searchParameters.getTextAttributes()) + for (String attribute : searchParameters.getTextAttributes()) { textAttributes.put(attribute); } body.put("textAttributes", textAttributes); - + PostMethod post = new PostMethod(url.toString()); post.setRequestEntity(new ByteArrayRequestEntity(body.toString().getBytes("UTF-8"), "application/json")); - + httpClient.executeMethod(post); if (post.getStatusCode() != HttpServletResponse.SC_OK) { - throw new LuceneQueryParserException("Request failed " + post.getStatusCode()+" "+url.toString()); + throw new LuceneQueryParserException("Request failed " + post.getStatusCode() + " " + url.toString()); } - Reader reader = new BufferedReader(new InputStreamReader(post.getResponseBodyAsStream())); // TODO - replace with streaming-based solution e.g. SimpleJSON ContentHandler JSONObject json = new JSONObject(new JSONTokener(reader)); SolrJSONResultSet results = new SolrJSONResultSet(json, nodeDAO, searchParameters); - if(s_logger.isDebugEnabled()) + if (s_logger.isDebugEnabled()) { - s_logger.debug("Sent :"+url); - s_logger.debug(" with: "+body.toString()); - s_logger.debug("Got: "+results.getNumberFound()+ " in "+results.getQueryTime()+ " ms"); + s_logger.debug("Sent :" + url); + s_logger.debug(" with: " + body.toString()); + s_logger.debug("Got: " + results.getNumberFound() + " in " + results.getQueryTime() + " ms"); } - + return results; } catch (UnsupportedEncodingException e) @@ -265,19 +269,6 @@ public class SolrCMISQueryLanguage implements LuceneQueryLanguageSPI } } - public String getName() - { - return SearchService.LANGUAGE_SOLR_CMIS; - } - - public void setFactories(List factories) - { - for (AbstractLuceneIndexerAndSearcherFactory factory : factories) - { - factory.registerQueryLanguage(this); - } - } - public static void main(String[] args) { SolrCMISQueryLanguage solrAlfrescoFTSQueryLanguage = new SolrCMISQueryLanguage(); @@ -286,15 +277,15 @@ public class SolrCMISQueryLanguage implements LuceneQueryLanguageSPI sp.setMaxItems(100); sp.setSkipCount(12); ResultSet rs = solrAlfrescoFTSQueryLanguage.executeQuery(sp, null); - System.out.println("Found "+rs.length()); - System.out.println("More "+rs.hasMore()); - System.out.println("Start "+rs.getStart()); - - for(ResultSetRow row : rs) + System.out.println("Found " + rs.length()); + System.out.println("More " + rs.hasMore()); + System.out.println("Start " + rs.getStart()); + + for (ResultSetRow row : rs) { - System.out.println("Score "+row.getScore()); + System.out.println("Score " + row.getScore()); } rs.close(); } - + } diff --git a/source/java/org/alfresco/repo/search/impl/solr/SolrCMISQueryServiceImpl.java b/source/java/org/alfresco/repo/search/impl/solr/SolrCMISQueryServiceImpl.java new file mode 100644 index 0000000000..b7a2f645c3 --- /dev/null +++ b/source/java/org/alfresco/repo/search/impl/solr/SolrCMISQueryServiceImpl.java @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2005-2010 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ +package org.alfresco.repo.search.impl.solr; + +import org.alfresco.opencmis.search.CMISQueryOptions; +import org.alfresco.opencmis.search.CMISQueryService; +import org.alfresco.opencmis.search.CMISResultSet; +import org.alfresco.service.cmr.repository.StoreRef; +import org.apache.chemistry.opencmis.commons.enums.CapabilityJoin; +import org.apache.chemistry.opencmis.commons.enums.CapabilityQuery; + +/** + * @author Andy + * + */ +public class SolrCMISQueryServiceImpl implements CMISQueryService +{ + + /* (non-Javadoc) + * @see org.alfresco.opencmis.search.CMISQueryService#query(org.alfresco.opencmis.search.CMISQueryOptions) + */ + @Override + public CMISResultSet query(CMISQueryOptions options) + { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see org.alfresco.opencmis.search.CMISQueryService#query(java.lang.String, org.alfresco.service.cmr.repository.StoreRef) + */ + @Override + public CMISResultSet query(String query, StoreRef storeRef) + { + CMISQueryOptions options = new CMISQueryOptions(query, storeRef); + return query(options); + } + + public boolean getPwcSearchable() + { + return true; + } + + public boolean getAllVersionsSearchable() + { + return false; + } + + public CapabilityQuery getQuerySupport() + { + return CapabilityQuery.BOTHCOMBINED; + } + + public CapabilityJoin getJoinSupport() + { + return CapabilityJoin.NONE; + } + +} diff --git a/source/java/org/alfresco/repo/search/impl/solr/SolrIndexRecovery.java b/source/java/org/alfresco/repo/search/impl/solr/SolrIndexRecovery.java new file mode 100644 index 0000000000..37dfe0db86 --- /dev/null +++ b/source/java/org/alfresco/repo/search/impl/solr/SolrIndexRecovery.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2005-2010 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ +package org.alfresco.repo.search.impl.solr; + +import org.alfresco.repo.node.index.IndexRecovery; + +/** + * @author Andy + * + */ +public class SolrIndexRecovery implements IndexRecovery +{ + + /* (non-Javadoc) + * @see org.alfresco.repo.node.index.IndexRecovery#reindex() + */ + @Override + public void reindex() + { + // Nothing to do at the moment + // Should send check and recovery commands etc when we support them .... + } + +} diff --git a/source/java/org/alfresco/repo/search/impl/solr/SolrIndexerAndSearcherFactory.java b/source/java/org/alfresco/repo/search/impl/solr/SolrIndexerAndSearcherFactory.java new file mode 100644 index 0000000000..526cb4435c --- /dev/null +++ b/source/java/org/alfresco/repo/search/impl/solr/SolrIndexerAndSearcherFactory.java @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2005-2010 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ +package org.alfresco.repo.search.impl.solr; + +import org.alfresco.repo.search.Indexer; +import org.alfresco.repo.search.IndexerException; +import org.alfresco.repo.search.QueryRegisterComponent; +import org.alfresco.repo.search.SearcherException; +import org.alfresco.repo.search.impl.NoActionIndexer; +import org.alfresco.repo.search.impl.lucene.ADMLuceneSearcherImpl; +import org.alfresco.repo.search.impl.lucene.AbstractIndexerAndSearcher; +import org.alfresco.repo.tenant.TenantService; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.cmr.search.SearchService; +import org.alfresco.service.namespace.NamespacePrefixResolver; + +/** + * @author Andy + * + */ +public class SolrIndexerAndSearcherFactory extends AbstractIndexerAndSearcher +{ + + private DictionaryService dictionaryService; + private NamespacePrefixResolver namespacePrefixResolver; + private NodeService nodeService; + private QueryRegisterComponent queryRegister; + private TenantService tenantService; + + public DictionaryService getDictionaryService() + { + return dictionaryService; + } + + public void setDictionaryService(DictionaryService dictionaryService) + { + this.dictionaryService = dictionaryService; + } + + public NamespacePrefixResolver getNamespacePrefixResolver() + { + return namespacePrefixResolver; + } + + public void setNamespacePrefixResolver(NamespacePrefixResolver namespacePrefixResolver) + { + this.namespacePrefixResolver = namespacePrefixResolver; + } + + public NodeService getNodeService() + { + return nodeService; + } + + public void setNodeService(NodeService nodeService) + { + this.nodeService = nodeService; + } + + public QueryRegisterComponent getQueryRegister() + { + return queryRegister; + } + + public void setQueryRegister(QueryRegisterComponent queryRegister) + { + this.queryRegister = queryRegister; + } + + public TenantService getTenantService() + { + return tenantService; + } + + public void setTenantService(TenantService tenantService) + { + this.tenantService = tenantService; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.search.IndexerAndSearcher#getIndexer(org.alfresco.service.cmr.repository.StoreRef) + */ + @Override + public Indexer getIndexer(StoreRef storeRef) throws IndexerException + { + return new NoActionIndexer(); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.search.IndexerAndSearcher#getSearcher(org.alfresco.service.cmr.repository.StoreRef, boolean) + */ + @Override + public SearchService getSearcher(StoreRef storeRef, boolean searchDelta) throws SearcherException + { + //storeRef = tenantService.getName(storeRef); + + SolrSearchService searchService = new SolrSearchService(); + searchService.setDictionaryService(dictionaryService); + searchService.setNamespacePrefixResolver(namespacePrefixResolver); + searchService.setNodeService(nodeService); + searchService.setQueryLanguages(getQueryLanguages()); + searchService.setQueryRegister(queryRegister); + searchService.setTenantService(tenantService); + return searchService; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.search.IndexerAndSearcher#flush() + */ + @Override + public void flush() + { + // Nothing to do + } + +} diff --git a/source/java/org/alfresco/repo/search/impl/solr/SolrSearchService.java b/source/java/org/alfresco/repo/search/impl/solr/SolrSearchService.java new file mode 100644 index 0000000000..e33b4a4143 --- /dev/null +++ b/source/java/org/alfresco/repo/search/impl/solr/SolrSearchService.java @@ -0,0 +1,561 @@ +/* + * Copyright (C) 2005-2010 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ +package org.alfresco.repo.search.impl.solr; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import java.util.Set; + +import org.alfresco.repo.search.CannedQueryDef; +import org.alfresco.repo.search.QueryRegisterComponent; +import org.alfresco.repo.search.SearcherException; +import org.alfresco.repo.search.impl.NodeSearcher; +import org.alfresco.repo.search.impl.lucene.LuceneQueryLanguageSPI; +import org.alfresco.repo.search.impl.lucene.LuceneQueryParser; +import org.alfresco.repo.search.impl.lucene.QueryParameterisationException; +import org.alfresco.repo.tenant.TenantService; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.repository.InvalidNodeRefException; +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.repository.XPathException; +import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; +import org.alfresco.service.cmr.search.QueryParameter; +import org.alfresco.service.cmr.search.QueryParameterDefinition; +import org.alfresco.service.cmr.search.ResultSet; +import org.alfresco.service.cmr.search.SearchParameters; +import org.alfresco.service.cmr.search.SearchService; +import org.alfresco.service.cmr.search.SearchParameters.Operator; +import org.alfresco.service.namespace.NamespacePrefixResolver; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.ISO9075; +import org.alfresco.util.SearchLanguageConversion; + +/** + * @author Andy + */ +public class SolrSearchService implements SearchService +{ + + private NodeService nodeService; + + private TenantService tenantService; + + private NamespacePrefixResolver namespacePrefixResolver; + + private DictionaryService dictionaryService; + + private Map queryLanguages; + + private QueryRegisterComponent queryRegister; + + public NodeService getNodeService() + { + return nodeService; + } + + public void setNodeService(NodeService nodeService) + { + this.nodeService = nodeService; + } + + public TenantService getTenantService() + { + return tenantService; + } + + public void setTenantService(TenantService tenantService) + { + this.tenantService = tenantService; + } + + public NamespacePrefixResolver getNamespacePrefixResolver() + { + return namespacePrefixResolver; + } + + public void setNamespacePrefixResolver(NamespacePrefixResolver namespacePrefixResolver) + { + this.namespacePrefixResolver = namespacePrefixResolver; + } + + public DictionaryService getDictionaryService() + { + return dictionaryService; + } + + public void setDictionaryService(DictionaryService dictionaryService) + { + this.dictionaryService = dictionaryService; + } + + public Map getQueryLanguages() + { + return queryLanguages; + } + + public void setQueryLanguages(Map queryLanguages) + { + this.queryLanguages = queryLanguages; + } + + public QueryRegisterComponent getQueryRegister() + { + return queryRegister; + } + + public void setQueryRegister(QueryRegisterComponent queryRegister) + { + this.queryRegister = queryRegister; + } + + /* + * (non-Javadoc) + * @see org.alfresco.service.cmr.search.SearchService#query(org.alfresco.service.cmr.repository.StoreRef, + * java.lang.String, java.lang.String) + */ + @Override + public ResultSet query(StoreRef store, String language, String query) + { + return query(store, language, query, null); + } + + /* + * (non-Javadoc) + * @see org.alfresco.service.cmr.search.SearchService#query(org.alfresco.service.cmr.repository.StoreRef, + * java.lang.String, java.lang.String, org.alfresco.service.cmr.search.QueryParameterDefinition[]) + */ + @Override + public ResultSet query(StoreRef store, String language, String query, QueryParameterDefinition[] queryParameterDefinitions) + { + store = tenantService.getName(store); + + SearchParameters sp = new SearchParameters(); + sp.addStore(store); + sp.setLanguage(language); + sp.setQuery(query); + if (queryParameterDefinitions != null) + { + for (QueryParameterDefinition qpd : queryParameterDefinitions) + { + sp.addQueryParameterDefinition(qpd); + } + } + sp.excludeDataInTheCurrentTransaction(true); + + return query(sp); + } + + /* + * (non-Javadoc) + * @see org.alfresco.service.cmr.search.SearchService#query(org.alfresco.service.cmr.repository.StoreRef, + * org.alfresco.service.namespace.QName, org.alfresco.service.cmr.search.QueryParameter[]) + */ + @Override + public ResultSet query(StoreRef store, QName queryId, QueryParameter[] queryParameters) + { + CannedQueryDef definition = queryRegister.getQueryDefinition(queryId); + + // Do parameter replacement + // As lucene phrases are tokensied it is correct to just do straight + // string replacement. + // The string will be formatted by the tokeniser. + // + // For non phrase queries this is incorrect but string replacement is + // probably the best we can do. + // As numbers and text are indexed specially, direct term queries only + // make sense against textual data + + checkParameters(definition, queryParameters); + + String queryString = parameterise(definition.getQuery(), definition.getQueryParameterMap(), queryParameters, definition.getNamespacePrefixResolver()); + + return query(store, definition.getLanguage(), queryString, null); + } + + /** + * The definitions must provide a default value, or of not there must be a parameter to provide the value + * + * @param definition + * @param queryParameters + * @throws QueryParameterisationException + */ + private void checkParameters(CannedQueryDef definition, QueryParameter[] queryParameters) throws QueryParameterisationException + { + List missing = new ArrayList(); + + Set parameterQNameSet = new HashSet(); + if (queryParameters != null) + { + for (QueryParameter parameter : queryParameters) + { + parameterQNameSet.add(parameter.getQName()); + } + } + + for (QueryParameterDefinition parameterDefinition : definition.getQueryParameterDefs()) + { + if (!parameterDefinition.hasDefaultValue()) + { + if (!parameterQNameSet.contains(parameterDefinition.getQName())) + { + missing.add(parameterDefinition.getQName()); + } + } + } + + if (missing.size() > 0) + { + StringBuilder buffer = new StringBuilder(128); + buffer.append("The query is missing values for the following parameters: "); + for (QName qName : missing) + { + buffer.append(qName); + buffer.append(", "); + } + buffer.delete(buffer.length() - 1, buffer.length() - 1); + buffer.delete(buffer.length() - 1, buffer.length() - 1); + throw new QueryParameterisationException(buffer.toString()); + } + } + + /* + * Parameterise the query string - not sure if it is required to escape lucence spacials chars The parameters could + * be used to build the query - the contents of parameters should alread have been escaped if required. ... mush + * better to provide the parameters and work out what to do TODO: conditional query escapement - may be we should + * have a parameter type that is not escaped + */ + private String parameterise(String unparameterised, Map map, QueryParameter[] queryParameters, NamespacePrefixResolver nspr) + throws QueryParameterisationException + { + + Map> valueMap = new HashMap>(); + + if (queryParameters != null) + { + for (QueryParameter parameter : queryParameters) + { + List list = valueMap.get(parameter.getQName()); + if (list == null) + { + list = new ArrayList(); + valueMap.put(parameter.getQName(), list); + } + list.add(parameter.getValue()); + } + } + + Map> iteratorMap = new HashMap>(); + + List missing = new ArrayList(1); + StringBuilder buffer = new StringBuilder(unparameterised); + int index = 0; + while ((index = buffer.indexOf("${", index)) != -1) + { + int endIndex = buffer.indexOf("}", index); + String qNameString = buffer.substring(index + 2, endIndex); + QName key = QName.createQName(qNameString, nspr); + QueryParameterDefinition parameterDefinition = map.get(key); + if (parameterDefinition == null) + { + missing.add(key); + buffer.replace(index, endIndex + 1, ""); + } + else + { + ListIterator it = iteratorMap.get(key); + if ((it == null) || (!it.hasNext())) + { + List list = valueMap.get(key); + if ((list != null) && (list.size() > 0)) + { + it = list.listIterator(); + } + if (it != null) + { + iteratorMap.put(key, it); + } + } + String value; + if (it == null) + { + value = parameterDefinition.getDefault(); + } + else + { + value = DefaultTypeConverter.INSTANCE.convert(String.class, it.next()); + } + buffer.replace(index, endIndex + 1, value); + } + } + if (missing.size() > 0) + { + StringBuilder error = new StringBuilder(); + error.append("The query uses the following parameters which are not defined: "); + for (QName qName : missing) + { + error.append(qName); + error.append(", "); + } + error.delete(error.length() - 1, error.length() - 1); + error.delete(error.length() - 1, error.length() - 1); + throw new QueryParameterisationException(error.toString()); + } + return buffer.toString(); + } + + /* + * (non-Javadoc) + * @see org.alfresco.service.cmr.search.SearchService#query(org.alfresco.service.cmr.search.SearchParameters) + */ + @Override + public ResultSet query(SearchParameters searchParameters) + { + if (searchParameters.getStores().size() != 1) + { + throw new IllegalStateException("Only one store can be searched at present"); + } + + ArrayList stores = searchParameters.getStores(); + stores.set(0, tenantService.getName(searchParameters.getStores().get(0))); + + String parameterisedQueryString; + if (searchParameters.getQueryParameterDefinitions().size() > 0) + { + Map map = new HashMap(); + + for (QueryParameterDefinition qpd : searchParameters.getQueryParameterDefinitions()) + { + map.put(qpd.getQName(), qpd); + } + + parameterisedQueryString = parameterise(searchParameters.getQuery(), map, null, namespacePrefixResolver); + } + else + { + parameterisedQueryString = searchParameters.getQuery(); + } + // TODO: add another property so the set query is not changed ... + // May be good to return the query as run ?? + searchParameters.setQuery(parameterisedQueryString); + + LuceneQueryLanguageSPI language = queryLanguages.get(searchParameters.getLanguage().toLowerCase()); + if (language != null) + { + return language.executeQuery(searchParameters, null); + } + else + { + throw new SearcherException("Unknown query language: " + searchParameters.getLanguage()); + } + } + + /* + * (non-Javadoc) + * @see org.alfresco.service.cmr.search.SearchService#selectNodes(org.alfresco.service.cmr.repository.NodeRef, + * java.lang.String, org.alfresco.service.cmr.search.QueryParameterDefinition[], + * org.alfresco.service.namespace.NamespacePrefixResolver, boolean) + */ + @Override + public List selectNodes(NodeRef contextNodeRef, String xpath, QueryParameterDefinition[] parameters, NamespacePrefixResolver namespacePrefixResolver, + boolean followAllParentLinks) throws InvalidNodeRefException, XPathException + { + return selectNodes(contextNodeRef, xpath, parameters, namespacePrefixResolver, followAllParentLinks, SearchService.LANGUAGE_XPATH); + } + + /* + * (non-Javadoc) + * @see org.alfresco.service.cmr.search.SearchService#selectNodes(org.alfresco.service.cmr.repository.NodeRef, + * java.lang.String, org.alfresco.service.cmr.search.QueryParameterDefinition[], + * org.alfresco.service.namespace.NamespacePrefixResolver, boolean, java.lang.String) + */ + @Override + public List selectNodes(NodeRef contextNodeRef, String xpath, QueryParameterDefinition[] parameters, NamespacePrefixResolver namespacePrefixResolver, + boolean followAllParentLinks, String language) throws InvalidNodeRefException, XPathException + { + NodeSearcher nodeSearcher = new NodeSearcher(nodeService, dictionaryService, this); + return nodeSearcher.selectNodes(contextNodeRef, xpath, parameters, namespacePrefixResolver, followAllParentLinks, language); + + } + + /* + * (non-Javadoc) + * @see org.alfresco.service.cmr.search.SearchService#selectProperties(org.alfresco.service.cmr.repository.NodeRef, + * java.lang.String, org.alfresco.service.cmr.search.QueryParameterDefinition[], + * org.alfresco.service.namespace.NamespacePrefixResolver, boolean) + */ + @Override + public List selectProperties(NodeRef contextNodeRef, String xpath, QueryParameterDefinition[] parameters, NamespacePrefixResolver namespacePrefixResolver, + boolean followAllParentLinks) throws InvalidNodeRefException, XPathException + { + return selectProperties(contextNodeRef, xpath, parameters, namespacePrefixResolver, followAllParentLinks, SearchService.LANGUAGE_XPATH); + + } + + /* + * (non-Javadoc) + * @see org.alfresco.service.cmr.search.SearchService#selectProperties(org.alfresco.service.cmr.repository.NodeRef, + * java.lang.String, org.alfresco.service.cmr.search.QueryParameterDefinition[], + * org.alfresco.service.namespace.NamespacePrefixResolver, boolean, java.lang.String) + */ + @Override + public List selectProperties(NodeRef contextNodeRef, String xpath, QueryParameterDefinition[] parameters, NamespacePrefixResolver namespacePrefixResolver, + boolean followAllParentLinks, String language) throws InvalidNodeRefException, XPathException + { + NodeSearcher nodeSearcher = new NodeSearcher(nodeService, dictionaryService, this); + return nodeSearcher.selectProperties(contextNodeRef, xpath, parameters, namespacePrefixResolver, followAllParentLinks, language); + + } + + /* + * (non-Javadoc) + * @see org.alfresco.service.cmr.search.SearchService#contains(org.alfresco.service.cmr.repository.NodeRef, + * org.alfresco.service.namespace.QName, java.lang.String) + */ + @Override + public boolean contains(NodeRef nodeRef, QName propertyQName, String googleLikePattern) throws InvalidNodeRefException + { + return contains(nodeRef, propertyQName, googleLikePattern, SearchParameters.Operator.OR); + + } + + /* + * (non-Javadoc) + * @see org.alfresco.service.cmr.search.SearchService#contains(org.alfresco.service.cmr.repository.NodeRef, + * org.alfresco.service.namespace.QName, java.lang.String, + * org.alfresco.service.cmr.search.SearchParameters.Operator) + */ + @Override + public boolean contains(NodeRef nodeRef, QName propertyQName, String googleLikePattern, Operator defaultOperator) throws InvalidNodeRefException + { + ResultSet resultSet = null; + try + { + // build Lucene search string specific to the node + StringBuilder sb = new StringBuilder(); + sb.append("+ID:\"").append(nodeRef.toString()).append("\" +(TEXT:(").append(googleLikePattern.toLowerCase()).append(") "); + if (propertyQName != null) + { + sb.append(" OR @").append(LuceneQueryParser.escape(QName.createQName(propertyQName.getNamespaceURI(), ISO9075.encode(propertyQName.getLocalName())).toString())); + sb.append(":(").append(googleLikePattern.toLowerCase()).append(")"); + } + else + { + for (QName key : nodeService.getProperties(nodeRef).keySet()) + { + sb.append(" OR @").append(LuceneQueryParser.escape(QName.createQName(key.getNamespaceURI(), ISO9075.encode(key.getLocalName())).toString())); + sb.append(":(").append(googleLikePattern.toLowerCase()).append(")"); + } + } + sb.append(")"); + + SearchParameters sp = new SearchParameters(); + sp.setLanguage(SearchService.LANGUAGE_LUCENE); + sp.setQuery(sb.toString()); + sp.setDefaultOperator(defaultOperator); + sp.addStore(nodeRef.getStoreRef()); + + resultSet = this.query(sp); + boolean answer = resultSet.length() > 0; + return answer; + } + finally + { + if (resultSet != null) + { + resultSet.close(); + } + } + } + + /* + * (non-Javadoc) + * @see org.alfresco.service.cmr.search.SearchService#like(org.alfresco.service.cmr.repository.NodeRef, + * org.alfresco.service.namespace.QName, java.lang.String, boolean) + */ + @Override + public boolean like(NodeRef nodeRef, QName propertyQName, String sqlLikePattern, boolean includeFTS) throws InvalidNodeRefException + { + if (propertyQName == null) + { + throw new IllegalArgumentException("Property QName is mandatory for the like expression"); + } + + StringBuilder sb = new StringBuilder(sqlLikePattern.length() * 3); + + if (includeFTS) + { + // convert the SQL-like pattern into a Lucene-compatible string + String pattern = SearchLanguageConversion.convertXPathLikeToLucene(sqlLikePattern.toLowerCase()); + + // build Lucene search string specific to the node + sb = new StringBuilder(); + sb.append("+ID:\"").append(nodeRef.toString()).append("\" +("); + // FTS or attribute matches + if (includeFTS) + { + sb.append("TEXT:(").append(pattern).append(") "); + } + if (propertyQName != null) + { + sb.append(" @").append(LuceneQueryParser.escape(QName.createQName(propertyQName.getNamespaceURI(), ISO9075.encode(propertyQName.getLocalName())).toString())) + .append(":(").append(pattern).append(")"); + } + sb.append(")"); + + ResultSet resultSet = null; + try + { + resultSet = this.query(nodeRef.getStoreRef(), "lucene", sb.toString()); + boolean answer = resultSet.length() > 0; + return answer; + } + finally + { + if (resultSet != null) + { + resultSet.close(); + } + } + } + else + { + // convert the SQL-like pattern into a Lucene-compatible string + String pattern = SearchLanguageConversion.convertXPathLikeToRegex(sqlLikePattern.toLowerCase()); + + Serializable property = nodeService.getProperty(nodeRef, propertyQName); + if (property == null) + { + return false; + } + else + { + String propertyString = DefaultTypeConverter.INSTANCE.convert(String.class, nodeService.getProperty(nodeRef, propertyQName)); + return propertyString.toLowerCase().matches(pattern); + } + } + } + +} diff --git a/source/java/org/alfresco/repo/solr/SOLRTrackingComponent.java b/source/java/org/alfresco/repo/solr/SOLRTrackingComponent.java index 35eaa54519..d88ac2ef91 100644 --- a/source/java/org/alfresco/repo/solr/SOLRTrackingComponent.java +++ b/source/java/org/alfresco/repo/solr/SOLRTrackingComponent.java @@ -31,7 +31,7 @@ import org.alfresco.service.namespace.QName; * @since 4.0 */ public interface SOLRTrackingComponent -{ +{ /** * Get the ACL changesets for given range parameters * @@ -132,4 +132,14 @@ public interface SOLRTrackingComponent */ boolean handleNodeMetaData(NodeMetaData nodeMetaData); } + + /** + * @return + */ + boolean isEnabled(); + + /** + * @param enabled + */ + void setEnabled(boolean enabled); } diff --git a/source/java/org/alfresco/repo/solr/SOLRTrackingComponentImpl.java b/source/java/org/alfresco/repo/solr/SOLRTrackingComponentImpl.java index 44902463da..4215a9024f 100644 --- a/source/java/org/alfresco/repo/solr/SOLRTrackingComponentImpl.java +++ b/source/java/org/alfresco/repo/solr/SOLRTrackingComponentImpl.java @@ -25,6 +25,7 @@ import java.io.IOException; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.Iterator; import java.util.LinkedList; import java.util.List; @@ -75,6 +76,20 @@ public class SOLRTrackingComponentImpl implements SOLRTrackingComponent private OwnableService ownableService; private TenantService tenantService; private DictionaryService dictionaryService; + private boolean enabled = true; + + + @Override + public boolean isEnabled() + { + return enabled; + } + + @Override + public void setEnabled(boolean enabled) + { + this.enabled = enabled; + } public void setSolrDAO(SOLRDAO solrDAO) { @@ -136,42 +151,70 @@ public class SOLRTrackingComponentImpl implements SOLRTrackingComponent @Override public List getAclChangeSets(Long minAclChangeSetId, Long fromCommitTime, int maxResults) { - List changesets = solrDAO.getAclChangeSets(minAclChangeSetId, fromCommitTime, maxResults); - return changesets; + if(enabled) + { + List changesets = solrDAO.getAclChangeSets(minAclChangeSetId, fromCommitTime, maxResults); + return changesets; + } + else + { + return Collections.emptyList(); + } } @Override public List getAcls(List aclChangeSetIds, Long minAclId, int maxResults) { - List acls = solrDAO.getAcls(aclChangeSetIds, minAclId, maxResults); - return acls; + if(enabled) + { + List acls = solrDAO.getAcls(aclChangeSetIds, minAclId, maxResults); + return acls; + } + else + { + return Collections.emptyList(); + } } @Override public List getAclsReaders(List aclIds) { - /* - * This is an N+1 query that should, in theory, make use of cached ACL readers data. - */ - - List aclsReaders = new ArrayList(aclIds.size() * 10); - for (Long aclId : aclIds) + if(enabled) { - Set readersSet = permissionService.getReaders(aclId); - AclReaders readers = new AclReaders(); - readers.setAclId(aclId); - readers.setReaders(readersSet); - aclsReaders.add(readers); + /* + * This is an N+1 query that should, in theory, make use of cached ACL readers data. + */ + + List aclsReaders = new ArrayList(aclIds.size() * 10); + for (Long aclId : aclIds) + { + Set readersSet = permissionService.getReaders(aclId); + AclReaders readers = new AclReaders(); + readers.setAclId(aclId); + readers.setReaders(readersSet); + aclsReaders.add(readers); + } + + return aclsReaders; + } + else + { + return Collections.emptyList(); } - - return aclsReaders; } @Override public List getTransactions(Long minTxnId, Long fromCommitTime, int maxResults) { - List txns = solrDAO.getTransactions(minTxnId, fromCommitTime, maxResults); - return txns; + if(enabled) + { + List txns = solrDAO.getTransactions(minTxnId, fromCommitTime, maxResults); + return txns; + } + else + { + return Collections.emptyList(); + } } /** @@ -179,11 +222,14 @@ public class SOLRTrackingComponentImpl implements SOLRTrackingComponent */ public void getNodes(NodeParameters nodeParameters, NodeQueryCallback callback) { - List nodes = solrDAO.getNodes(nodeParameters); - - for (Node node : nodes) + if(enabled) { - callback.handleNode(node); + List nodes = solrDAO.getNodes(nodeParameters); + + for (Node node : nodes) + { + callback.handleNode(node); + } } } @@ -408,6 +454,11 @@ public class SOLRTrackingComponentImpl implements SOLRTrackingComponent MetaDataResultsFilter resultFilter, NodeMetaDataQueryCallback callback) { + if(false == enabled) + { + return; + } + NodeMetaDataQueryRowHandler rowHandler = new NodeMetaDataQueryRowHandler(callback); boolean includeType = (resultFilter == null ? true : resultFilter.getIncludeType()); boolean includeProperties = (resultFilter == null ? true : resultFilter.getIncludeProperties()); @@ -550,8 +601,15 @@ public class SOLRTrackingComponentImpl implements SOLRTrackingComponent */ public AlfrescoModel getModel(QName modelName) { - ModelDefinition modelDef = dictionaryService.getModel(modelName); - return (modelDef != null ? new AlfrescoModel(modelDef) : null); + if(enabled) + { + ModelDefinition modelDef = dictionaryService.getModel(modelName); + return (modelDef != null ? new AlfrescoModel(modelDef) : null); + } + else + { + return null; + } } /** @@ -559,6 +617,11 @@ public class SOLRTrackingComponentImpl implements SOLRTrackingComponent */ public List getModelDiffs(Map models) { + if(false == enabled) + { + return Collections.emptyList(); + } + List diffs = new ArrayList(); // get all models the repository knows about and add each to a list with its checksum