mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
SOLR bug fixes
- Fix SOLR web app shutdown - Lucene search sub-system can start and self-test without being live - Fix passing faceting parameters - Model deletion on update/removal - ALF-9798 Share - doc lib - favourites fails to show with SOLR - incorrect query .... - ID now uses hidden LID field if it is a NodeRef - QNAME and other related queries generated against AUX doc git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@29624 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -1012,31 +1012,16 @@
|
|||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean id="avmSnapShotTriggeredIndexingMethodInterceptor" class="org.alfresco.repo.search.AVMSnapShotTriggeredIndexingMethodInterceptor">
|
<bean id="avmSnapShotTriggeredIndexingMethodInterceptor" class="org.alfresco.repo.management.subsystems.SubsystemProxyFactory">
|
||||||
<property name="avmService">
|
<property name="sourceApplicationContextFactory">
|
||||||
<ref bean="avmService" />
|
<ref bean="Search" />
|
||||||
</property>
|
</property>
|
||||||
<property name="indexerAndSearcher">
|
<property name="sourceBeanName">
|
||||||
<ref bean="avmLuceneIndexerAndSearcherFactory" />
|
<value>search.avmSnapShotTriggeredIndexingMethodInterceptor</value>
|
||||||
</property>
|
</property>
|
||||||
<property name="enableIndexing">
|
<property name="interfaces">
|
||||||
<value>true</value>
|
|
||||||
</property>
|
|
||||||
<property name="defaultMode">
|
|
||||||
<value>SYNCHRONOUS</value>
|
|
||||||
</property>
|
|
||||||
<property name="indexingDefinitions">
|
|
||||||
<list>
|
<list>
|
||||||
<value>SYNCHRONOUS:TYPE:STAGING</value>
|
<value>org.alfresco.repo.search.AVMSnapShotTriggeredIndexingMethodInterceptor</value>
|
||||||
<value>UNINDEXED:TYPE:STAGING_PREVIEW</value>
|
|
||||||
<value>UNINDEXED:TYPE:AUTHOR</value>
|
|
||||||
<value>UNINDEXED:TYPE:AUTHOR_PREVIEW</value>
|
|
||||||
<value>UNINDEXED:TYPE:WORKFLOW</value>
|
|
||||||
<value>UNINDEXED:TYPE:WORKFLOW_PREVIEW</value>
|
|
||||||
<value>UNINDEXED:TYPE:AUTHOR_WORKFLOW</value>
|
|
||||||
<value>UNINDEXED:TYPE:AUTHOR_WORKFLOW_PREVIEW</value>
|
|
||||||
<value>ASYNCHRONOUS:NAME:avmAsynchronousTest</value>
|
|
||||||
<value>SYNCHRONOUS:NAME:.*</value>
|
|
||||||
</list>
|
</list>
|
||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
@@ -32,4 +32,33 @@
|
|||||||
<!-- Query collections should be loaded on demand using this component - once loaded thay are available for use -->
|
<!-- Query collections should be loaded on demand using this component - once loaded thay are available for use -->
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
<bean id="search.avmSnapShotTriggeredIndexingMethodInterceptor" class="org.alfresco.repo.search.AVMSnapShotTriggeredIndexingMethodInterceptorImpl">
|
||||||
|
<property name="avmService">
|
||||||
|
<ref bean="avmService" />
|
||||||
|
</property>
|
||||||
|
<property name="indexerAndSearcher">
|
||||||
|
<ref bean="search.avmLuceneIndexerAndSearcherFactory" />
|
||||||
|
</property>
|
||||||
|
<property name="enableIndexing">
|
||||||
|
<value>true</value>
|
||||||
|
</property>
|
||||||
|
<property name="defaultMode">
|
||||||
|
<value>SYNCHRONOUS</value>
|
||||||
|
</property>
|
||||||
|
<property name="indexingDefinitions">
|
||||||
|
<list>
|
||||||
|
<value>SYNCHRONOUS:TYPE:STAGING</value>
|
||||||
|
<value>UNINDEXED:TYPE:STAGING_PREVIEW</value>
|
||||||
|
<value>UNINDEXED:TYPE:AUTHOR</value>
|
||||||
|
<value>UNINDEXED:TYPE:AUTHOR_PREVIEW</value>
|
||||||
|
<value>UNINDEXED:TYPE:WORKFLOW</value>
|
||||||
|
<value>UNINDEXED:TYPE:WORKFLOW_PREVIEW</value>
|
||||||
|
<value>UNINDEXED:TYPE:AUTHOR_WORKFLOW</value>
|
||||||
|
<value>UNINDEXED:TYPE:AUTHOR_WORKFLOW_PREVIEW</value>
|
||||||
|
<value>ASYNCHRONOUS:NAME:avmAsynchronousTest</value>
|
||||||
|
<value>SYNCHRONOUS:NAME:.*</value>
|
||||||
|
</list>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
</beans>
|
</beans>
|
||||||
|
@@ -89,7 +89,7 @@
|
|||||||
<ref bean="avmService" />
|
<ref bean="avmService" />
|
||||||
</property>
|
</property>
|
||||||
<property name="avmSnapShotTriggeredIndexingMethodInterceptor">
|
<property name="avmSnapShotTriggeredIndexingMethodInterceptor">
|
||||||
<ref bean="avmSnapShotTriggeredIndexingMethodInterceptor" />
|
<ref bean="search.avmSnapShotTriggeredIndexingMethodInterceptor" />
|
||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
@@ -162,7 +162,7 @@
|
|||||||
<ref bean="avmService" />
|
<ref bean="avmService" />
|
||||||
</property>
|
</property>
|
||||||
<property name="avmSnapShotTriggeredIndexingMethodInterceptor">
|
<property name="avmSnapShotTriggeredIndexingMethodInterceptor">
|
||||||
<ref bean="avmSnapShotTriggeredIndexingMethodInterceptor" />
|
<ref bean="search.avmSnapShotTriggeredIndexingMethodInterceptor" />
|
||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
@@ -385,7 +385,7 @@
|
|||||||
<ref bean="search.indexThreadPoolExecutor"></ref>
|
<ref bean="search.indexThreadPoolExecutor"></ref>
|
||||||
</property>
|
</property>
|
||||||
<property name="avmSnapShotTriggeredIndexingMethodInterceptor">
|
<property name="avmSnapShotTriggeredIndexingMethodInterceptor">
|
||||||
<ref bean="avmSnapShotTriggeredIndexingMethodInterceptor" />
|
<ref bean="search.avmSnapShotTriggeredIndexingMethodInterceptor" />
|
||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
@@ -474,10 +474,10 @@
|
|||||||
<ref bean="nodeService"/>
|
<ref bean="nodeService"/>
|
||||||
</property>
|
</property>
|
||||||
<property name="searchService">
|
<property name="searchService">
|
||||||
<ref bean="searchService"/>
|
<ref bean="search.searchService"/>
|
||||||
</property>
|
</property>
|
||||||
<property name="avmSnapShotTriggeredIndexingMethodInterceptor">
|
<property name="avmSnapShotTriggeredIndexingMethodInterceptor">
|
||||||
<ref bean="avmSnapShotTriggeredIndexingMethodInterceptor"/>
|
<ref bean="search.avmSnapShotTriggeredIndexingMethodInterceptor"/>
|
||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
</beans>
|
</beans>
|
||||||
|
@@ -28,7 +28,7 @@ import org.springframework.extensions.surf.util.I18NUtil;
|
|||||||
import org.alfresco.model.ContentModel;
|
import org.alfresco.model.ContentModel;
|
||||||
import org.alfresco.repo.importer.ImporterBootstrap;
|
import org.alfresco.repo.importer.ImporterBootstrap;
|
||||||
import org.alfresco.repo.node.index.FullIndexRecoveryComponent.RecoveryMode;
|
import org.alfresco.repo.node.index.FullIndexRecoveryComponent.RecoveryMode;
|
||||||
import org.alfresco.repo.search.AVMSnapShotTriggeredIndexingMethodInterceptor;
|
import org.alfresco.repo.search.AVMSnapShotTriggeredIndexingMethodInterceptorImpl;
|
||||||
import org.alfresco.repo.search.IndexMode;
|
import org.alfresco.repo.search.IndexMode;
|
||||||
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||||
import org.alfresco.service.cmr.repository.ContentReader;
|
import org.alfresco.service.cmr.repository.ContentReader;
|
||||||
|
@@ -27,7 +27,7 @@ import org.alfresco.repo.admin.patch.AbstractPatch;
|
|||||||
import org.alfresco.repo.avm.AVMNodeConverter;
|
import org.alfresco.repo.avm.AVMNodeConverter;
|
||||||
import org.alfresco.repo.domain.PropertyValue;
|
import org.alfresco.repo.domain.PropertyValue;
|
||||||
import org.alfresco.repo.search.AVMSnapShotTriggeredIndexingMethodInterceptor;
|
import org.alfresco.repo.search.AVMSnapShotTriggeredIndexingMethodInterceptor;
|
||||||
import org.alfresco.repo.search.AVMSnapShotTriggeredIndexingMethodInterceptor.StoreType;
|
import org.alfresco.repo.search.AVMSnapShotTriggeredIndexingMethodInterceptorImpl.StoreType;
|
||||||
import org.alfresco.service.cmr.avm.AVMService;
|
import org.alfresco.service.cmr.avm.AVMService;
|
||||||
import org.alfresco.service.cmr.avm.AVMStoreDescriptor;
|
import org.alfresco.service.cmr.avm.AVMStoreDescriptor;
|
||||||
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
|
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
|
||||||
|
@@ -38,7 +38,7 @@ import org.alfresco.repo.domain.permissions.AclEntity;
|
|||||||
import org.alfresco.repo.domain.permissions.AclUpdateEntity;
|
import org.alfresco.repo.domain.permissions.AclUpdateEntity;
|
||||||
import org.alfresco.repo.domain.permissions.Authority;
|
import org.alfresco.repo.domain.permissions.Authority;
|
||||||
import org.alfresco.repo.domain.permissions.Permission;
|
import org.alfresco.repo.domain.permissions.Permission;
|
||||||
import org.alfresco.repo.search.AVMSnapShotTriggeredIndexingMethodInterceptor.StoreType;
|
import org.alfresco.repo.search.AVMSnapShotTriggeredIndexingMethodInterceptorImpl.StoreType;
|
||||||
import org.alfresco.repo.security.permissions.ACEType;
|
import org.alfresco.repo.security.permissions.ACEType;
|
||||||
import org.alfresco.repo.security.permissions.ACLType;
|
import org.alfresco.repo.security.permissions.ACLType;
|
||||||
import org.alfresco.repo.security.permissions.impl.SimplePermissionReference;
|
import org.alfresco.repo.security.permissions.impl.SimplePermissionReference;
|
||||||
|
@@ -33,7 +33,7 @@ import org.alfresco.repo.avm.util.AVMUtil;
|
|||||||
import org.alfresco.repo.domain.PropertyValue;
|
import org.alfresco.repo.domain.PropertyValue;
|
||||||
import org.alfresco.repo.domain.avm.AVMNodeDAO;
|
import org.alfresco.repo.domain.avm.AVMNodeDAO;
|
||||||
import org.alfresco.repo.domain.avm.AVMNodeEntity;
|
import org.alfresco.repo.domain.avm.AVMNodeEntity;
|
||||||
import org.alfresco.repo.search.AVMSnapShotTriggeredIndexingMethodInterceptor.StoreType;
|
import org.alfresco.repo.search.AVMSnapShotTriggeredIndexingMethodInterceptorImpl.StoreType;
|
||||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||||
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
||||||
import org.alfresco.repo.security.permissions.ACLType;
|
import org.alfresco.repo.security.permissions.ACLType;
|
||||||
|
@@ -18,37 +18,20 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.repo.search;
|
package org.alfresco.repo.search;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
import org.alfresco.error.AlfrescoRuntimeException;
|
|
||||||
import org.alfresco.repo.avm.AVMNodeConverter;
|
|
||||||
import org.alfresco.repo.domain.PropertyValue;
|
|
||||||
import org.alfresco.repo.search.impl.lucene.AVMLuceneIndexer;
|
import org.alfresco.repo.search.impl.lucene.AVMLuceneIndexer;
|
||||||
import org.alfresco.service.cmr.avm.AVMService;
|
import org.alfresco.service.cmr.avm.AVMService;
|
||||||
import org.alfresco.service.cmr.avm.AVMStoreDescriptor;
|
|
||||||
import org.alfresco.service.cmr.repository.StoreRef;
|
|
||||||
import org.alfresco.service.namespace.QName;
|
import org.alfresco.service.namespace.QName;
|
||||||
import org.aopalliance.intercept.MethodInterceptor;
|
import org.aopalliance.intercept.MethodInterceptor;
|
||||||
import org.aopalliance.intercept.MethodInvocation;
|
import org.aopalliance.intercept.MethodInvocation;
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method interceptor for atomic indexing of AVM entries The properties can defined how stores are indexed based on type
|
* @author Andy
|
||||||
* (as set by Alfresco the Web site management UI) or based on the name of the store. Creates and deletes are indexed
|
|
||||||
* synchronously. Updates may be asynchronous, synchronous or ignored by the index.
|
|
||||||
*
|
*
|
||||||
* @author andyh
|
|
||||||
*/
|
*/
|
||||||
public class AVMSnapShotTriggeredIndexingMethodInterceptor implements MethodInterceptor
|
public interface AVMSnapShotTriggeredIndexingMethodInterceptor extends MethodInterceptor
|
||||||
{
|
{
|
||||||
private static Log logger = LogFactory.getLog(AVMSnapShotTriggeredIndexingMethodInterceptor.class);
|
|
||||||
|
|
||||||
// Copy of store properties used to tag avm stores (a store propertry)
|
|
||||||
|
|
||||||
public final static QName PROP_SANDBOX_STAGING_MAIN = QName.createQName(null, ".sandbox.staging.main");
|
public final static QName PROP_SANDBOX_STAGING_MAIN = QName.createQName(null, ".sandbox.staging.main");
|
||||||
|
|
||||||
@@ -66,255 +49,69 @@ public class AVMSnapShotTriggeredIndexingMethodInterceptor implements MethodInte
|
|||||||
|
|
||||||
public final static QName PROP_SANDBOX_AUTHOR_WORKFLOW_PREVIEW = QName.createQName(null, ".sandbox.author.workflow.preview");
|
public final static QName PROP_SANDBOX_AUTHOR_WORKFLOW_PREVIEW = QName.createQName(null, ".sandbox.author.workflow.preview");
|
||||||
|
|
||||||
private AVMService avmService;
|
|
||||||
|
|
||||||
private IndexerAndSearcher indexerAndSearcher;
|
|
||||||
|
|
||||||
private boolean enableIndexing = true;
|
|
||||||
|
|
||||||
private IndexMode defaultMode = IndexMode.ASYNCHRONOUS;
|
|
||||||
|
|
||||||
private Map<String, IndexMode> modeCache = new HashMap<String, IndexMode>();
|
|
||||||
|
|
||||||
private List<IndexingDefinition> indexingDefinitions = new ArrayList<IndexingDefinition>();
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public Object invoke(MethodInvocation mi) throws Throwable
|
public abstract Object invoke(MethodInvocation mi) throws Throwable;
|
||||||
{
|
|
||||||
if (enableIndexing)
|
|
||||||
{
|
|
||||||
if (mi.getMethod().getName().equals("createSnapshot"))
|
|
||||||
{
|
|
||||||
// May cause any number of other stores to do snap shot under the covers via layering or do nothing
|
|
||||||
// So we have to watch what actually changes
|
|
||||||
|
|
||||||
Object returnValue = mi.proceed();
|
|
||||||
|
|
||||||
Map<String, Integer> snapShots = (Map<String, Integer>) returnValue;
|
|
||||||
|
|
||||||
// Index any stores that have moved on
|
|
||||||
for (String store : snapShots.keySet())
|
|
||||||
{
|
|
||||||
int after = snapShots.get(store).intValue();
|
|
||||||
indexSnapshot(store, after);
|
|
||||||
}
|
|
||||||
return returnValue;
|
|
||||||
}
|
|
||||||
else if (mi.getMethod().getName().equals("purgeStore"))
|
|
||||||
{
|
|
||||||
String store = (String) mi.getArguments()[0];
|
|
||||||
Object returnValue = mi.proceed();
|
|
||||||
|
|
||||||
if (getIndexMode(store) != IndexMode.UNINDEXED)
|
|
||||||
{
|
|
||||||
AVMLuceneIndexer avmIndexer = getIndexer(store);
|
|
||||||
if (avmIndexer != null)
|
|
||||||
{
|
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
{
|
|
||||||
logger.debug("purgeStore " + store, new Exception("Stack Trace"));
|
|
||||||
}
|
|
||||||
avmIndexer.deleteIndex(store, IndexMode.SYNCHRONOUS);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return returnValue;
|
|
||||||
}
|
|
||||||
else if (mi.getMethod().getName().equals("createStore"))
|
|
||||||
{
|
|
||||||
String store = (String) mi.getArguments()[0];
|
|
||||||
Object returnValue = mi.proceed();
|
|
||||||
if (getIndexMode(store) != IndexMode.UNINDEXED)
|
|
||||||
{
|
|
||||||
createIndex(store);
|
|
||||||
}
|
|
||||||
return returnValue;
|
|
||||||
}
|
|
||||||
else if (mi.getMethod().getName().equals("renameStore"))
|
|
||||||
{
|
|
||||||
String from = (String) mi.getArguments()[0];
|
|
||||||
String to = (String) mi.getArguments()[1];
|
|
||||||
Object returnValue = mi.proceed();
|
|
||||||
int after = avmService.getLatestSnapshotID(to);
|
|
||||||
|
|
||||||
if (getIndexMode(from) != IndexMode.UNINDEXED)
|
|
||||||
{
|
|
||||||
AVMLuceneIndexer avmIndexer = getIndexer(from);
|
|
||||||
if (avmIndexer != null)
|
|
||||||
{
|
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
{
|
|
||||||
logger.debug("renameStore deleteIndex " + from, new Exception("Stack Trace"));
|
|
||||||
}
|
|
||||||
avmIndexer.deleteIndex(from, IndexMode.SYNCHRONOUS);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getIndexMode(to) != IndexMode.UNINDEXED)
|
|
||||||
{
|
|
||||||
AVMLuceneIndexer avmIndexer = getIndexer(to);
|
|
||||||
if (avmIndexer != null)
|
|
||||||
{
|
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
{
|
|
||||||
logger.debug("renameStore createIndex " + to + "(0, " + after + ")", new Exception("Stack Trace"));
|
|
||||||
}
|
|
||||||
avmIndexer.createIndex(to, IndexMode.SYNCHRONOUS);
|
|
||||||
avmIndexer.index(to, 0, after, getIndexMode(to));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return returnValue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return mi.proceed();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return mi.proceed();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the AVM service
|
* Set the AVM service
|
||||||
*
|
*
|
||||||
* @param avmService
|
* @param avmService
|
||||||
*/
|
*/
|
||||||
public void setAvmService(AVMService avmService)
|
public abstract void setAvmService(AVMService avmService);
|
||||||
{
|
|
||||||
this.avmService = avmService;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the AVM indexer and searcher
|
* Set the AVM indexer and searcher
|
||||||
*
|
*
|
||||||
* @param indexerAndSearcher
|
* @param indexerAndSearcher
|
||||||
*/
|
*/
|
||||||
public void setIndexerAndSearcher(IndexerAndSearcher indexerAndSearcher)
|
public abstract void setIndexerAndSearcher(IndexerAndSearcher indexerAndSearcher);
|
||||||
{
|
|
||||||
this.indexerAndSearcher = indexerAndSearcher;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enable or disable indexing
|
* Enable or disable indexing
|
||||||
*
|
*
|
||||||
* @param enableIndexing
|
* @param enableIndexing
|
||||||
*/
|
*/
|
||||||
public void setEnableIndexing(boolean enableIndexing)
|
public abstract void setEnableIndexing(boolean enableIndexing);
|
||||||
{
|
|
||||||
this.enableIndexing = enableIndexing;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the index modes.... Strings of the form ... (ASYNCHRONOUS | SYNCHRONOUS | UNINDEXED):(NAME | TYPE):regexp
|
* Set the index modes.... Strings of the form ... (ASYNCHRONOUS | SYNCHRONOUS | UNINDEXED):(NAME | TYPE):regexp
|
||||||
*
|
*
|
||||||
* @param definitions
|
* @param definitions
|
||||||
*/
|
*/
|
||||||
public void setIndexingDefinitions(List<String> definitions)
|
public abstract void setIndexingDefinitions(List<String> definitions);
|
||||||
{
|
|
||||||
indexingDefinitions.clear();
|
|
||||||
for (String def : definitions)
|
|
||||||
{
|
|
||||||
IndexingDefinition id = new IndexingDefinition(def);
|
|
||||||
indexingDefinitions.add(id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the default index mode = used when there are no matches
|
* Set the default index mode = used when there are no matches
|
||||||
*
|
*
|
||||||
* @param defaultMode
|
* @param defaultMode
|
||||||
*/
|
*/
|
||||||
public void setDefaultMode(IndexMode defaultMode)
|
public abstract void setDefaultMode(IndexMode defaultMode);
|
||||||
{
|
|
||||||
this.defaultMode = defaultMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is snapshot triggered indexing enabled
|
* Is snapshot triggered indexing enabled
|
||||||
*
|
*
|
||||||
* @return true if indexing is enabled for AVM
|
* @return true if indexing is enabled for AVM
|
||||||
*/
|
*/
|
||||||
public boolean isIndexingEnabled()
|
public abstract boolean isIndexingEnabled();
|
||||||
{
|
|
||||||
return enableIndexing;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param store
|
* @param store
|
||||||
* @param before
|
* @param before
|
||||||
* @param after
|
* @param after
|
||||||
*/
|
*/
|
||||||
public void indexSnapshot(String store, int before, int after)
|
public abstract void indexSnapshot(String store, int before, int after);
|
||||||
{
|
|
||||||
indexSnapshotImpl(store, before, after);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param store
|
* @param store
|
||||||
* @param after
|
* @param after
|
||||||
*/
|
*/
|
||||||
public void indexSnapshot(String store, int after)
|
public abstract void indexSnapshot(String store, int after);
|
||||||
{
|
|
||||||
indexSnapshotImpl(store, -1, after);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void indexSnapshotImpl(String store, int before, int after)
|
|
||||||
{
|
|
||||||
if (getIndexMode(store) != IndexMode.UNINDEXED)
|
|
||||||
{
|
|
||||||
AVMLuceneIndexer avmIndexer = getIndexer(store);
|
|
||||||
if (avmIndexer != null)
|
|
||||||
{
|
|
||||||
int last = getLastIndexedSnapshot(avmIndexer, store);
|
|
||||||
|
|
||||||
if ((last == -1) && (! hasIndexBeenCreated(store)))
|
|
||||||
{
|
|
||||||
createIndex(store);
|
|
||||||
// ALF-7845
|
|
||||||
last = getLastIndexedSnapshot(avmIndexer, store);
|
|
||||||
}
|
|
||||||
|
|
||||||
int from = before != -1 ? before : last;
|
|
||||||
|
|
||||||
if (from > after)
|
|
||||||
{
|
|
||||||
if (logger.isTraceEnabled())
|
|
||||||
{
|
|
||||||
logger.trace("skip indexSnapshotImpl " + store + " (" + (before == -1 ? "-1, " : "") + from +", " + after +")", new Exception("Stack Trace"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
{
|
|
||||||
logger.debug("indexSnapshotImpl " + store + " (" + (before == -1 ? "-1, " : "") + from +", " + after +")", new Exception("Stack Trace"));
|
|
||||||
}
|
|
||||||
avmIndexer.index(store, from, after, getIndexMode(store));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param store
|
* @param store
|
||||||
* @return - the last indexed snapshot
|
* @return - the last indexed snapshot
|
||||||
*/
|
*/
|
||||||
public int getLastIndexedSnapshot(String store)
|
public abstract int getLastIndexedSnapshot(String store);
|
||||||
{
|
|
||||||
|
|
||||||
AVMLuceneIndexer avmIndexer = getIndexer(store);
|
|
||||||
if (avmIndexer != null)
|
|
||||||
{
|
|
||||||
return getLastIndexedSnapshot(avmIndexer, store);
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int getLastIndexedSnapshot(AVMLuceneIndexer avmIndexer, String store)
|
|
||||||
{
|
|
||||||
return avmIndexer.getLastIndexedSnapshot(store);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is the snapshot applied to the index? Is there an entry for any node that was added OR have all the nodes in the
|
* Is the snapshot applied to the index? Is there an entry for any node that was added OR have all the nodes in the
|
||||||
@@ -324,15 +121,7 @@ public class AVMSnapShotTriggeredIndexingMethodInterceptor implements MethodInte
|
|||||||
* @param id
|
* @param id
|
||||||
* @return - true if applied, false if not
|
* @return - true if applied, false if not
|
||||||
*/
|
*/
|
||||||
public boolean isSnapshotIndexed(String store, int id)
|
public abstract boolean isSnapshotIndexed(String store, int id);
|
||||||
{
|
|
||||||
AVMLuceneIndexer avmIndexer = getIndexer(store);
|
|
||||||
if (avmIndexer != null)
|
|
||||||
{
|
|
||||||
return avmIndexer.isSnapshotIndexed(store, id);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the index is up to date according to its index defintion and that all asynchronous work is done.
|
* Check if the index is up to date according to its index defintion and that all asynchronous work is done.
|
||||||
@@ -340,27 +129,7 @@ public class AVMSnapShotTriggeredIndexingMethodInterceptor implements MethodInte
|
|||||||
* @param store
|
* @param store
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public boolean isIndexUpToDateAndSearchable(String store)
|
public abstract boolean isIndexUpToDateAndSearchable(String store);
|
||||||
{
|
|
||||||
|
|
||||||
switch (getIndexMode(store))
|
|
||||||
{
|
|
||||||
case UNINDEXED:
|
|
||||||
return false;
|
|
||||||
case SYNCHRONOUS:
|
|
||||||
case ASYNCHRONOUS:
|
|
||||||
int last = avmService.getLatestSnapshotID(store);
|
|
||||||
AVMLuceneIndexer avmIndexer = getIndexer(store);
|
|
||||||
if (avmIndexer != null)
|
|
||||||
{
|
|
||||||
avmIndexer.flushPending();
|
|
||||||
return avmIndexer.isSnapshotSearchable(store, last);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the index is up to date according to its index defintion i it does not check that all asynchronous work
|
* Check if the index is up to date according to its index defintion i it does not check that all asynchronous work
|
||||||
@@ -369,26 +138,7 @@ public class AVMSnapShotTriggeredIndexingMethodInterceptor implements MethodInte
|
|||||||
* @param store
|
* @param store
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public boolean isIndexUpToDate(String store)
|
public abstract boolean isIndexUpToDate(String store);
|
||||||
{
|
|
||||||
switch (getIndexMode(store))
|
|
||||||
{
|
|
||||||
case UNINDEXED:
|
|
||||||
return true;
|
|
||||||
case SYNCHRONOUS:
|
|
||||||
case ASYNCHRONOUS:
|
|
||||||
int last = avmService.getLatestSnapshotID(store);
|
|
||||||
AVMLuceneIndexer avmIndexer = getIndexer(store);
|
|
||||||
if (avmIndexer != null)
|
|
||||||
{
|
|
||||||
avmIndexer.flushPending();
|
|
||||||
return avmIndexer.isSnapshotIndexed(store, last);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given an avm store name determine if it is indexed and if so how.
|
* Given an avm store name determine if it is indexed and if so how.
|
||||||
@@ -396,174 +146,14 @@ public class AVMSnapShotTriggeredIndexingMethodInterceptor implements MethodInte
|
|||||||
* @param store
|
* @param store
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public synchronized IndexMode getIndexMode(String store)
|
public abstract IndexMode getIndexMode(String store);
|
||||||
{
|
|
||||||
IndexMode mode = modeCache.get(store);
|
|
||||||
if (mode == null)
|
|
||||||
{
|
|
||||||
for (IndexingDefinition def : indexingDefinitions)
|
|
||||||
{
|
|
||||||
if (def.definitionType == DefinitionType.NAME)
|
|
||||||
{
|
|
||||||
if (def.pattern.matcher(store).matches())
|
|
||||||
{
|
|
||||||
mode = def.indexMode;
|
|
||||||
modeCache.put(store, mode);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
AVMStoreDescriptor avmStoreDescriptor = avmService.getStore(store);
|
|
||||||
Map<QName, PropertyValue> storeProperties = null;
|
|
||||||
if (avmStoreDescriptor != null)
|
|
||||||
{
|
|
||||||
storeProperties = avmService.getStoreProperties(store);
|
|
||||||
}
|
|
||||||
String storeType = StoreType.getStoreType(store, avmStoreDescriptor, storeProperties).toString();
|
|
||||||
if (def.pattern.matcher(storeType).matches())
|
|
||||||
{
|
|
||||||
mode = def.indexMode;
|
|
||||||
modeCache.put(store, mode);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
public abstract boolean hasIndexBeenCreated(String store);
|
||||||
}
|
|
||||||
}
|
|
||||||
// No definition
|
|
||||||
if (mode == null)
|
|
||||||
{
|
|
||||||
mode = defaultMode;
|
|
||||||
modeCache.put(store, mode);
|
|
||||||
}
|
|
||||||
return mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
private class IndexingDefinition
|
public abstract void createIndex(String store);
|
||||||
{
|
|
||||||
IndexMode indexMode;
|
|
||||||
|
|
||||||
DefinitionType definitionType;
|
public abstract AVMLuceneIndexer getIndexer(String store);
|
||||||
|
|
||||||
Pattern pattern;
|
public abstract void deleteIndex(String store);
|
||||||
|
|
||||||
IndexingDefinition(String definition)
|
|
||||||
{
|
|
||||||
String[] split = definition.split(":", 3);
|
|
||||||
if (split.length != 3)
|
|
||||||
{
|
|
||||||
throw new AlfrescoRuntimeException("Invalid index defintion. Must be of of the form IndexMode:DefinitionType:regular expression");
|
|
||||||
}
|
|
||||||
indexMode = IndexMode.valueOf(split[0].toUpperCase());
|
|
||||||
definitionType = DefinitionType.valueOf(split[1].toUpperCase());
|
|
||||||
pattern = Pattern.compile(split[2]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private enum DefinitionType
|
|
||||||
{
|
|
||||||
NAME, TYPE;
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum StoreType
|
|
||||||
{
|
|
||||||
STAGING, STAGING_PREVIEW, AUTHOR, AUTHOR_PREVIEW, WORKFLOW, WORKFLOW_PREVIEW, AUTHOR_WORKFLOW, AUTHOR_WORKFLOW_PREVIEW, UNKNOWN;
|
|
||||||
|
|
||||||
public static StoreType getStoreType(String name, AVMStoreDescriptor storeDescriptor, Map<QName, PropertyValue> storeProperties)
|
|
||||||
{
|
|
||||||
// if (avmService.getStore(name) != null)
|
|
||||||
if (storeDescriptor != null)
|
|
||||||
{
|
|
||||||
// Map<QName, PropertyValue> storeProperties = avmService.getStoreProperties(name);
|
|
||||||
if (storeProperties.containsKey(PROP_SANDBOX_STAGING_MAIN))
|
|
||||||
{
|
|
||||||
return StoreType.STAGING;
|
|
||||||
}
|
|
||||||
else if (storeProperties.containsKey(PROP_SANDBOX_STAGING_PREVIEW))
|
|
||||||
{
|
|
||||||
return StoreType.STAGING_PREVIEW;
|
|
||||||
}
|
|
||||||
else if (storeProperties.containsKey(PROP_SANDBOX_AUTHOR_MAIN))
|
|
||||||
{
|
|
||||||
return StoreType.AUTHOR;
|
|
||||||
}
|
|
||||||
else if (storeProperties.containsKey(PROP_SANDBOX_AUTHOR_PREVIEW))
|
|
||||||
{
|
|
||||||
return StoreType.AUTHOR_PREVIEW;
|
|
||||||
}
|
|
||||||
else if (storeProperties.containsKey(PROP_SANDBOX_WORKFLOW_MAIN))
|
|
||||||
{
|
|
||||||
return StoreType.WORKFLOW;
|
|
||||||
}
|
|
||||||
else if (storeProperties.containsKey(PROP_SANDBOX_WORKFLOW_PREVIEW))
|
|
||||||
{
|
|
||||||
return StoreType.WORKFLOW_PREVIEW;
|
|
||||||
}
|
|
||||||
else if (storeProperties.containsKey(PROP_SANDBOX_AUTHOR_WORKFLOW_MAIN))
|
|
||||||
{
|
|
||||||
return StoreType.AUTHOR_WORKFLOW;
|
|
||||||
}
|
|
||||||
else if (storeProperties.containsKey(PROP_SANDBOX_AUTHOR_WORKFLOW_PREVIEW))
|
|
||||||
{
|
|
||||||
return StoreType.AUTHOR_WORKFLOW_PREVIEW;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return StoreType.UNKNOWN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return StoreType.UNKNOWN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasIndexBeenCreated(String store)
|
|
||||||
{
|
|
||||||
AVMLuceneIndexer avmIndexer = getIndexer(store);
|
|
||||||
if (avmIndexer != null)
|
|
||||||
{
|
|
||||||
avmIndexer.flushPending();
|
|
||||||
return avmIndexer.hasIndexBeenCreated(store);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void createIndex(String store)
|
|
||||||
{
|
|
||||||
AVMLuceneIndexer avmIndexer = getIndexer(store);
|
|
||||||
if (avmIndexer != null)
|
|
||||||
{
|
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
{
|
|
||||||
logger.debug("createIndex " + store, new Exception("Stack Trace"));
|
|
||||||
}
|
|
||||||
avmIndexer.createIndex(store, IndexMode.SYNCHRONOUS);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public AVMLuceneIndexer getIndexer(String store)
|
|
||||||
{
|
|
||||||
StoreRef storeRef = AVMNodeConverter.ToStoreRef(store);
|
|
||||||
Indexer indexer = indexerAndSearcher.getIndexer(storeRef);
|
|
||||||
if (indexer instanceof AVMLuceneIndexer)
|
|
||||||
{
|
|
||||||
AVMLuceneIndexer avmIndexer = (AVMLuceneIndexer) indexer;
|
|
||||||
return avmIndexer;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void deleteIndex(String store)
|
|
||||||
{
|
|
||||||
StoreRef storeRef = AVMNodeConverter.ToStoreRef(store);
|
|
||||||
Indexer indexer = indexerAndSearcher.getIndexer(storeRef);
|
|
||||||
if (indexer instanceof AVMLuceneIndexer)
|
|
||||||
{
|
|
||||||
AVMLuceneIndexer avmIndexer = (AVMLuceneIndexer) indexer;
|
|
||||||
avmIndexer.deleteIndex(storeRef);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
@@ -0,0 +1,554 @@
|
|||||||
|
/*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.search;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import org.alfresco.error.AlfrescoRuntimeException;
|
||||||
|
import org.alfresco.repo.avm.AVMNodeConverter;
|
||||||
|
import org.alfresco.repo.domain.PropertyValue;
|
||||||
|
import org.alfresco.repo.search.impl.lucene.AVMLuceneIndexer;
|
||||||
|
import org.alfresco.service.cmr.avm.AVMService;
|
||||||
|
import org.alfresco.service.cmr.avm.AVMStoreDescriptor;
|
||||||
|
import org.alfresco.service.cmr.repository.StoreRef;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
import org.aopalliance.intercept.MethodInvocation;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method interceptor for atomic indexing of AVM entries The properties can defined how stores are indexed based on type
|
||||||
|
* (as set by Alfresco the Web site management UI) or based on the name of the store. Creates and deletes are indexed
|
||||||
|
* synchronously. Updates may be asynchronous, synchronous or ignored by the index.
|
||||||
|
*
|
||||||
|
* @author andyh
|
||||||
|
*/
|
||||||
|
public class AVMSnapShotTriggeredIndexingMethodInterceptorImpl implements AVMSnapShotTriggeredIndexingMethodInterceptor
|
||||||
|
{
|
||||||
|
private static Log logger = LogFactory.getLog(AVMSnapShotTriggeredIndexingMethodInterceptorImpl.class);
|
||||||
|
|
||||||
|
// Copy of store properties used to tag avm stores (a store propertry)
|
||||||
|
|
||||||
|
private AVMService avmService;
|
||||||
|
|
||||||
|
private IndexerAndSearcher indexerAndSearcher;
|
||||||
|
|
||||||
|
private boolean enableIndexing = true;
|
||||||
|
|
||||||
|
private IndexMode defaultMode = IndexMode.ASYNCHRONOUS;
|
||||||
|
|
||||||
|
private Map<String, IndexMode> modeCache = new HashMap<String, IndexMode>();
|
||||||
|
|
||||||
|
private List<IndexingDefinition> indexingDefinitions = new ArrayList<IndexingDefinition>();
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.alfresco.repo.search.AVMSnapShotTriggeredIndexingMethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public Object invoke(MethodInvocation mi) throws Throwable
|
||||||
|
{
|
||||||
|
if (enableIndexing)
|
||||||
|
{
|
||||||
|
if (mi.getMethod().getName().equals("createSnapshot"))
|
||||||
|
{
|
||||||
|
// May cause any number of other stores to do snap shot under the covers via layering or do nothing
|
||||||
|
// So we have to watch what actually changes
|
||||||
|
|
||||||
|
Object returnValue = mi.proceed();
|
||||||
|
|
||||||
|
Map<String, Integer> snapShots = (Map<String, Integer>) returnValue;
|
||||||
|
|
||||||
|
// Index any stores that have moved on
|
||||||
|
for (String store : snapShots.keySet())
|
||||||
|
{
|
||||||
|
int after = snapShots.get(store).intValue();
|
||||||
|
indexSnapshot(store, after);
|
||||||
|
}
|
||||||
|
return returnValue;
|
||||||
|
}
|
||||||
|
else if (mi.getMethod().getName().equals("purgeStore"))
|
||||||
|
{
|
||||||
|
String store = (String) mi.getArguments()[0];
|
||||||
|
Object returnValue = mi.proceed();
|
||||||
|
|
||||||
|
if (getIndexMode(store) != IndexMode.UNINDEXED)
|
||||||
|
{
|
||||||
|
AVMLuceneIndexer avmIndexer = getIndexer(store);
|
||||||
|
if (avmIndexer != null)
|
||||||
|
{
|
||||||
|
if (logger.isDebugEnabled())
|
||||||
|
{
|
||||||
|
logger.debug("purgeStore " + store, new Exception("Stack Trace"));
|
||||||
|
}
|
||||||
|
avmIndexer.deleteIndex(store, IndexMode.SYNCHRONOUS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return returnValue;
|
||||||
|
}
|
||||||
|
else if (mi.getMethod().getName().equals("createStore"))
|
||||||
|
{
|
||||||
|
String store = (String) mi.getArguments()[0];
|
||||||
|
Object returnValue = mi.proceed();
|
||||||
|
if (getIndexMode(store) != IndexMode.UNINDEXED)
|
||||||
|
{
|
||||||
|
createIndex(store);
|
||||||
|
}
|
||||||
|
return returnValue;
|
||||||
|
}
|
||||||
|
else if (mi.getMethod().getName().equals("renameStore"))
|
||||||
|
{
|
||||||
|
String from = (String) mi.getArguments()[0];
|
||||||
|
String to = (String) mi.getArguments()[1];
|
||||||
|
Object returnValue = mi.proceed();
|
||||||
|
int after = avmService.getLatestSnapshotID(to);
|
||||||
|
|
||||||
|
if (getIndexMode(from) != IndexMode.UNINDEXED)
|
||||||
|
{
|
||||||
|
AVMLuceneIndexer avmIndexer = getIndexer(from);
|
||||||
|
if (avmIndexer != null)
|
||||||
|
{
|
||||||
|
if (logger.isDebugEnabled())
|
||||||
|
{
|
||||||
|
logger.debug("renameStore deleteIndex " + from, new Exception("Stack Trace"));
|
||||||
|
}
|
||||||
|
avmIndexer.deleteIndex(from, IndexMode.SYNCHRONOUS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getIndexMode(to) != IndexMode.UNINDEXED)
|
||||||
|
{
|
||||||
|
AVMLuceneIndexer avmIndexer = getIndexer(to);
|
||||||
|
if (avmIndexer != null)
|
||||||
|
{
|
||||||
|
if (logger.isDebugEnabled())
|
||||||
|
{
|
||||||
|
logger.debug("renameStore createIndex " + to + "(0, " + after + ")", new Exception("Stack Trace"));
|
||||||
|
}
|
||||||
|
avmIndexer.createIndex(to, IndexMode.SYNCHRONOUS);
|
||||||
|
avmIndexer.index(to, 0, after, getIndexMode(to));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return returnValue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return mi.proceed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return mi.proceed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.alfresco.repo.search.AVMSnapShotTriggeredIndexingMethodInterceptor#setAvmService(org.alfresco.service.cmr.avm.AVMService)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void setAvmService(AVMService avmService)
|
||||||
|
{
|
||||||
|
this.avmService = avmService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.alfresco.repo.search.AVMSnapShotTriggeredIndexingMethodInterceptor#setIndexerAndSearcher(org.alfresco.repo.search.IndexerAndSearcher)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void setIndexerAndSearcher(IndexerAndSearcher indexerAndSearcher)
|
||||||
|
{
|
||||||
|
this.indexerAndSearcher = indexerAndSearcher;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.alfresco.repo.search.AVMSnapShotTriggeredIndexingMethodInterceptor#setEnableIndexing(boolean)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void setEnableIndexing(boolean enableIndexing)
|
||||||
|
{
|
||||||
|
this.enableIndexing = enableIndexing;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.alfresco.repo.search.AVMSnapShotTriggeredIndexingMethodInterceptor#setIndexingDefinitions(java.util.List)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void setIndexingDefinitions(List<String> definitions)
|
||||||
|
{
|
||||||
|
indexingDefinitions.clear();
|
||||||
|
for (String def : definitions)
|
||||||
|
{
|
||||||
|
IndexingDefinition id = new IndexingDefinition(def);
|
||||||
|
indexingDefinitions.add(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.alfresco.repo.search.AVMSnapShotTriggeredIndexingMethodInterceptor#setDefaultMode(org.alfresco.repo.search.IndexMode)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void setDefaultMode(IndexMode defaultMode)
|
||||||
|
{
|
||||||
|
this.defaultMode = defaultMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.alfresco.repo.search.AVMSnapShotTriggeredIndexingMethodInterceptor#isIndexingEnabled()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean isIndexingEnabled()
|
||||||
|
{
|
||||||
|
return enableIndexing;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.alfresco.repo.search.AVMSnapShotTriggeredIndexingMethodInterceptor#indexSnapshot(java.lang.String, int, int)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void indexSnapshot(String store, int before, int after)
|
||||||
|
{
|
||||||
|
indexSnapshotImpl(store, before, after);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.alfresco.repo.search.AVMSnapShotTriggeredIndexingMethodInterceptor#indexSnapshot(java.lang.String, int)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void indexSnapshot(String store, int after)
|
||||||
|
{
|
||||||
|
indexSnapshotImpl(store, -1, after);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void indexSnapshotImpl(String store, int before, int after)
|
||||||
|
{
|
||||||
|
if (getIndexMode(store) != IndexMode.UNINDEXED)
|
||||||
|
{
|
||||||
|
AVMLuceneIndexer avmIndexer = getIndexer(store);
|
||||||
|
if (avmIndexer != null)
|
||||||
|
{
|
||||||
|
int last = getLastIndexedSnapshot(avmIndexer, store);
|
||||||
|
|
||||||
|
if ((last == -1) && (! hasIndexBeenCreated(store)))
|
||||||
|
{
|
||||||
|
createIndex(store);
|
||||||
|
// ALF-7845
|
||||||
|
last = getLastIndexedSnapshot(avmIndexer, store);
|
||||||
|
}
|
||||||
|
|
||||||
|
int from = before != -1 ? before : last;
|
||||||
|
|
||||||
|
if (from > after)
|
||||||
|
{
|
||||||
|
if (logger.isTraceEnabled())
|
||||||
|
{
|
||||||
|
logger.trace("skip indexSnapshotImpl " + store + " (" + (before == -1 ? "-1, " : "") + from +", " + after +")", new Exception("Stack Trace"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (logger.isDebugEnabled())
|
||||||
|
{
|
||||||
|
logger.debug("indexSnapshotImpl " + store + " (" + (before == -1 ? "-1, " : "") + from +", " + after +")", new Exception("Stack Trace"));
|
||||||
|
}
|
||||||
|
avmIndexer.index(store, from, after, getIndexMode(store));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.alfresco.repo.search.AVMSnapShotTriggeredIndexingMethodInterceptor#getLastIndexedSnapshot(java.lang.String)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int getLastIndexedSnapshot(String store)
|
||||||
|
{
|
||||||
|
|
||||||
|
AVMLuceneIndexer avmIndexer = getIndexer(store);
|
||||||
|
if (avmIndexer != null)
|
||||||
|
{
|
||||||
|
return getLastIndexedSnapshot(avmIndexer, store);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getLastIndexedSnapshot(AVMLuceneIndexer avmIndexer, String store)
|
||||||
|
{
|
||||||
|
return avmIndexer.getLastIndexedSnapshot(store);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.alfresco.repo.search.AVMSnapShotTriggeredIndexingMethodInterceptor#isSnapshotIndexed(java.lang.String, int)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean isSnapshotIndexed(String store, int id)
|
||||||
|
{
|
||||||
|
AVMLuceneIndexer avmIndexer = getIndexer(store);
|
||||||
|
if (avmIndexer != null)
|
||||||
|
{
|
||||||
|
return avmIndexer.isSnapshotIndexed(store, id);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.alfresco.repo.search.AVMSnapShotTriggeredIndexingMethodInterceptor#isIndexUpToDateAndSearchable(java.lang.String)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean isIndexUpToDateAndSearchable(String store)
|
||||||
|
{
|
||||||
|
|
||||||
|
switch (getIndexMode(store))
|
||||||
|
{
|
||||||
|
case UNINDEXED:
|
||||||
|
return false;
|
||||||
|
case SYNCHRONOUS:
|
||||||
|
case ASYNCHRONOUS:
|
||||||
|
int last = avmService.getLatestSnapshotID(store);
|
||||||
|
AVMLuceneIndexer avmIndexer = getIndexer(store);
|
||||||
|
if (avmIndexer != null)
|
||||||
|
{
|
||||||
|
avmIndexer.flushPending();
|
||||||
|
return avmIndexer.isSnapshotSearchable(store, last);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.alfresco.repo.search.AVMSnapShotTriggeredIndexingMethodInterceptor#isIndexUpToDate(java.lang.String)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean isIndexUpToDate(String store)
|
||||||
|
{
|
||||||
|
switch (getIndexMode(store))
|
||||||
|
{
|
||||||
|
case UNINDEXED:
|
||||||
|
return true;
|
||||||
|
case SYNCHRONOUS:
|
||||||
|
case ASYNCHRONOUS:
|
||||||
|
int last = avmService.getLatestSnapshotID(store);
|
||||||
|
AVMLuceneIndexer avmIndexer = getIndexer(store);
|
||||||
|
if (avmIndexer != null)
|
||||||
|
{
|
||||||
|
avmIndexer.flushPending();
|
||||||
|
return avmIndexer.isSnapshotIndexed(store, last);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.alfresco.repo.search.AVMSnapShotTriggeredIndexingMethodInterceptor#getIndexMode(java.lang.String)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public synchronized IndexMode getIndexMode(String store)
|
||||||
|
{
|
||||||
|
IndexMode mode = modeCache.get(store);
|
||||||
|
if (mode == null)
|
||||||
|
{
|
||||||
|
for (IndexingDefinition def : indexingDefinitions)
|
||||||
|
{
|
||||||
|
if (def.definitionType == DefinitionType.NAME)
|
||||||
|
{
|
||||||
|
if (def.pattern.matcher(store).matches())
|
||||||
|
{
|
||||||
|
mode = def.indexMode;
|
||||||
|
modeCache.put(store, mode);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AVMStoreDescriptor avmStoreDescriptor = avmService.getStore(store);
|
||||||
|
Map<QName, PropertyValue> storeProperties = null;
|
||||||
|
if (avmStoreDescriptor != null)
|
||||||
|
{
|
||||||
|
storeProperties = avmService.getStoreProperties(store);
|
||||||
|
}
|
||||||
|
String storeType = StoreType.getStoreType(store, avmStoreDescriptor, storeProperties).toString();
|
||||||
|
if (def.pattern.matcher(storeType).matches())
|
||||||
|
{
|
||||||
|
mode = def.indexMode;
|
||||||
|
modeCache.put(store, mode);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// No definition
|
||||||
|
if (mode == null)
|
||||||
|
{
|
||||||
|
mode = defaultMode;
|
||||||
|
modeCache.put(store, mode);
|
||||||
|
}
|
||||||
|
return mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class IndexingDefinition
|
||||||
|
{
|
||||||
|
IndexMode indexMode;
|
||||||
|
|
||||||
|
DefinitionType definitionType;
|
||||||
|
|
||||||
|
Pattern pattern;
|
||||||
|
|
||||||
|
IndexingDefinition(String definition)
|
||||||
|
{
|
||||||
|
String[] split = definition.split(":", 3);
|
||||||
|
if (split.length != 3)
|
||||||
|
{
|
||||||
|
throw new AlfrescoRuntimeException("Invalid index defintion. Must be of of the form IndexMode:DefinitionType:regular expression");
|
||||||
|
}
|
||||||
|
indexMode = IndexMode.valueOf(split[0].toUpperCase());
|
||||||
|
definitionType = DefinitionType.valueOf(split[1].toUpperCase());
|
||||||
|
pattern = Pattern.compile(split[2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum DefinitionType
|
||||||
|
{
|
||||||
|
NAME, TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum StoreType
|
||||||
|
{
|
||||||
|
STAGING, STAGING_PREVIEW, AUTHOR, AUTHOR_PREVIEW, WORKFLOW, WORKFLOW_PREVIEW, AUTHOR_WORKFLOW, AUTHOR_WORKFLOW_PREVIEW, UNKNOWN;
|
||||||
|
|
||||||
|
public static StoreType getStoreType(String name, AVMStoreDescriptor storeDescriptor, Map<QName, PropertyValue> storeProperties)
|
||||||
|
{
|
||||||
|
// if (avmService.getStore(name) != null)
|
||||||
|
if (storeDescriptor != null)
|
||||||
|
{
|
||||||
|
// Map<QName, PropertyValue> storeProperties = avmService.getStoreProperties(name);
|
||||||
|
if (storeProperties.containsKey(PROP_SANDBOX_STAGING_MAIN))
|
||||||
|
{
|
||||||
|
return StoreType.STAGING;
|
||||||
|
}
|
||||||
|
else if (storeProperties.containsKey(PROP_SANDBOX_STAGING_PREVIEW))
|
||||||
|
{
|
||||||
|
return StoreType.STAGING_PREVIEW;
|
||||||
|
}
|
||||||
|
else if (storeProperties.containsKey(PROP_SANDBOX_AUTHOR_MAIN))
|
||||||
|
{
|
||||||
|
return StoreType.AUTHOR;
|
||||||
|
}
|
||||||
|
else if (storeProperties.containsKey(PROP_SANDBOX_AUTHOR_PREVIEW))
|
||||||
|
{
|
||||||
|
return StoreType.AUTHOR_PREVIEW;
|
||||||
|
}
|
||||||
|
else if (storeProperties.containsKey(PROP_SANDBOX_WORKFLOW_MAIN))
|
||||||
|
{
|
||||||
|
return StoreType.WORKFLOW;
|
||||||
|
}
|
||||||
|
else if (storeProperties.containsKey(PROP_SANDBOX_WORKFLOW_PREVIEW))
|
||||||
|
{
|
||||||
|
return StoreType.WORKFLOW_PREVIEW;
|
||||||
|
}
|
||||||
|
else if (storeProperties.containsKey(PROP_SANDBOX_AUTHOR_WORKFLOW_MAIN))
|
||||||
|
{
|
||||||
|
return StoreType.AUTHOR_WORKFLOW;
|
||||||
|
}
|
||||||
|
else if (storeProperties.containsKey(PROP_SANDBOX_AUTHOR_WORKFLOW_PREVIEW))
|
||||||
|
{
|
||||||
|
return StoreType.AUTHOR_WORKFLOW_PREVIEW;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return StoreType.UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return StoreType.UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.alfresco.repo.search.AVMSnapShotTriggeredIndexingMethodInterceptor#hasIndexBeenCreated(java.lang.String)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean hasIndexBeenCreated(String store)
|
||||||
|
{
|
||||||
|
AVMLuceneIndexer avmIndexer = getIndexer(store);
|
||||||
|
if (avmIndexer != null)
|
||||||
|
{
|
||||||
|
avmIndexer.flushPending();
|
||||||
|
return avmIndexer.hasIndexBeenCreated(store);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.alfresco.repo.search.AVMSnapShotTriggeredIndexingMethodInterceptor#createIndex(java.lang.String)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void createIndex(String store)
|
||||||
|
{
|
||||||
|
AVMLuceneIndexer avmIndexer = getIndexer(store);
|
||||||
|
if (avmIndexer != null)
|
||||||
|
{
|
||||||
|
if (logger.isDebugEnabled())
|
||||||
|
{
|
||||||
|
logger.debug("createIndex " + store, new Exception("Stack Trace"));
|
||||||
|
}
|
||||||
|
avmIndexer.createIndex(store, IndexMode.SYNCHRONOUS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.alfresco.repo.search.AVMSnapShotTriggeredIndexingMethodInterceptor#getIndexer(java.lang.String)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public AVMLuceneIndexer getIndexer(String store)
|
||||||
|
{
|
||||||
|
StoreRef storeRef = AVMNodeConverter.ToStoreRef(store);
|
||||||
|
Indexer indexer = indexerAndSearcher.getIndexer(storeRef);
|
||||||
|
if (indexer instanceof AVMLuceneIndexer)
|
||||||
|
{
|
||||||
|
AVMLuceneIndexer avmIndexer = (AVMLuceneIndexer) indexer;
|
||||||
|
return avmIndexer;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.alfresco.repo.search.AVMSnapShotTriggeredIndexingMethodInterceptor#deleteIndex(java.lang.String)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void deleteIndex(String store)
|
||||||
|
{
|
||||||
|
StoreRef storeRef = AVMNodeConverter.ToStoreRef(store);
|
||||||
|
Indexer indexer = indexerAndSearcher.getIndexer(storeRef);
|
||||||
|
if (indexer instanceof AVMLuceneIndexer)
|
||||||
|
{
|
||||||
|
AVMLuceneIndexer avmIndexer = (AVMLuceneIndexer) indexer;
|
||||||
|
avmIndexer.deleteIndex(storeRef);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -37,6 +37,8 @@ import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
|
|||||||
import org.alfresco.service.cmr.search.ResultSet;
|
import org.alfresco.service.cmr.search.ResultSet;
|
||||||
import org.alfresco.service.cmr.search.SearchParameters;
|
import org.alfresco.service.cmr.search.SearchParameters;
|
||||||
import org.alfresco.service.cmr.search.SearchParameters.FieldFacet;
|
import org.alfresco.service.cmr.search.SearchParameters.FieldFacet;
|
||||||
|
import org.alfresco.service.cmr.search.SearchParameters.FieldFacetMethod;
|
||||||
|
import org.alfresco.service.cmr.search.SearchParameters.FieldFacetSort;
|
||||||
import org.alfresco.service.cmr.search.SearchParameters.SortDefinition;
|
import org.alfresco.service.cmr.search.SearchParameters.SortDefinition;
|
||||||
import org.alfresco.service.cmr.security.PermissionService;
|
import org.alfresco.service.cmr.security.PermissionService;
|
||||||
import org.apache.commons.codec.net.URLCodec;
|
import org.apache.commons.codec.net.URLCodec;
|
||||||
@@ -112,6 +114,10 @@ public class SolrQueryHTTPClient
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
// Simple demo
|
||||||
|
// FieldFacet ff = new FieldFacet("@"+ContentModel.PROP_NAME);
|
||||||
|
// ff.setLimit(2);
|
||||||
|
// searchParameters.addFieldFacet(ff);
|
||||||
|
|
||||||
URLCodec encoder = new URLCodec();
|
URLCodec encoder = new URLCodec();
|
||||||
StringBuilder url = new StringBuilder();
|
StringBuilder url = new StringBuilder();
|
||||||
@@ -208,7 +214,32 @@ public class SolrQueryHTTPClient
|
|||||||
for(FieldFacet facet : searchParameters.getFieldFacets())
|
for(FieldFacet facet : searchParameters.getFieldFacets())
|
||||||
{
|
{
|
||||||
url.append("&facet.field=").append(encoder.encode(facet.getField(), "UTF-8"));
|
url.append("&facet.field=").append(encoder.encode(facet.getField(), "UTF-8"));
|
||||||
url.append("&").append(encoder.encode("f."+facet.getField()+".limit", "UTF-8")).append("=").append(encoder.encode(""+facet.getLimit(), "UTF-8"));
|
if(facet.getEnumMethodCacheMinDF() != 0)
|
||||||
|
{
|
||||||
|
url.append("&").append(encoder.encode("f."+facet.getField()+".facet.enum.cache.minDf", "UTF-8")).append("=").append(encoder.encode(""+facet.getEnumMethodCacheMinDF(), "UTF-8"));
|
||||||
|
}
|
||||||
|
url.append("&").append(encoder.encode("f."+facet.getField()+".facet.limit", "UTF-8")).append("=").append(encoder.encode(""+facet.getLimit(), "UTF-8"));
|
||||||
|
if(facet.getMethod() != null)
|
||||||
|
{
|
||||||
|
url.append("&").append(encoder.encode("f."+facet.getField()+".facet.method", "UTF-8")).append("=").append(encoder.encode(facet.getMethod()==FieldFacetMethod.ENUM ? "enum" : "fc", "UTF-8"));
|
||||||
|
}
|
||||||
|
if(facet.getMinCount() != 0)
|
||||||
|
{
|
||||||
|
url.append("&").append(encoder.encode("f."+facet.getField()+".facet.mincount", "UTF-8")).append("=").append(encoder.encode(""+facet.getMinCount(), "UTF-8"));
|
||||||
|
}
|
||||||
|
if(facet.getOffset() != 0)
|
||||||
|
{
|
||||||
|
url.append("&").append(encoder.encode("f."+facet.getField()+".facet.offset", "UTF-8")).append("=").append(encoder.encode(""+facet.getOffset(), "UTF-8"));
|
||||||
|
}
|
||||||
|
if(facet.getPrefix() != null)
|
||||||
|
{
|
||||||
|
url.append("&").append(encoder.encode("f."+facet.getField()+".facet.prefix", "UTF-8")).append("=").append(encoder.encode(""+facet.getPrefix(), "UTF-8"));
|
||||||
|
}
|
||||||
|
if(facet.getSort() != null)
|
||||||
|
{
|
||||||
|
url.append("&").append(encoder.encode("f."+facet.getField()+".facet.sort", "UTF-8")).append("=").append(encoder.encode(facet.getSort() == FieldFacetSort.COUNT ? "count" : "index", "UTF-8"));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user