SEARCH-2454 Remove old lucene (#23)

This PR removes legacy Lucene code and dependency to the lucene 2.4.1 library.
The data type analysers were removed with an exception of the definitions in models (datadictionaryModel.xml and cmisModel.xml) to be backwards compatible with existing components (like older versions of Search Services) and to ensure the current old-style models can still work with repository and pass validation.
This commit is contained in:
Alex Mukha
2020-10-19 14:15:27 +01:00
committed by GitHub
parent 88cb7a0be2
commit 7ddb31d5e8
161 changed files with 2738 additions and 16852 deletions

View File

@@ -21,6 +21,7 @@ branches:
only:
- master
- /release\/.*/
- feature/search-2454-remove-old-lucene
env:
global:

View File

@@ -117,12 +117,6 @@ public class CustomModelDefinitionImpl implements CustomModelDefinition
return this.active;
}
@Override
public String getAnalyserResourceBundleName()
{
return m2ModelDefinition.getAnalyserResourceBundleName();
}
@Override
public String getAuthor()
{

View File

@@ -280,11 +280,6 @@ public interface DictionaryDAO extends ModelQuery
// MT-specific
boolean isModelInherited(QName name);
/**
* @return String
*/
String getDefaultAnalyserResourceBundleName();
/**
* @return ClassLoader
*/

View File

@@ -101,18 +101,6 @@ public class DictionaryDAOImpl implements DictionaryDAO, NamespaceDAO,
this.dictionaryRegistryCache = dictionaryRegistryCache;
}
@Override
public String getDefaultAnalyserResourceBundleName()
{
return defaultAnalyserResourceBundleName;
}
public void setDefaultAnalyserResourceBundleName(
String defaultAnalyserResourceBundleName)
{
this.defaultAnalyserResourceBundleName = defaultAnalyserResourceBundleName;
}
/**
* Construct
*

View File

@@ -234,15 +234,6 @@ import org.alfresco.service.namespace.QName;
return Collections.unmodifiableMap(childassociations);
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.dictionary.ClassDefinition#getAnalyserResourceBundleName()
*/
@Override
public String getAnalyserResourceBundleName()
{
return type.getAnalyserResourceBundleName();
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.dictionary.ClassDefinition#getParentClassDefinition()
*/

View File

@@ -48,7 +48,7 @@ public abstract class M2Class
private Boolean archive = null;
private Boolean includedInSuperTypeQuery = null;
private String analyserResourceBundleName = null;
private List<M2Property> properties = new ArrayList<M2Property>();
private List<M2PropertyOverride> propertyOverrides = new ArrayList<M2PropertyOverride>();
private List<M2ClassAssociation> associations = new ArrayList<M2ClassAssociation>();
@@ -270,19 +270,6 @@ public abstract class M2Class
{
return Collections.unmodifiableList(mandatoryAspects);
}
/**
* @return String
*/
public String getAnalyserResourceBundleName()
{
return analyserResourceBundleName;
}
public void setAnalyserResourceBundleName(String analyserResourceBundleName)
{
this.analyserResourceBundleName = analyserResourceBundleName;
}
public void setConfigProperties(Properties configProperties)
{

View File

@@ -206,8 +206,6 @@ import org.alfresco.util.EqualsHelper;
defaultAspectNames.add(name);
}
}
this.analyserResourceBundleName = m2Class.getAnalyserResourceBundleName();
}
@Override
@@ -761,15 +759,6 @@ import org.alfresco.util.EqualsHelper;
return modelDiffs;
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.dictionary.ClassDefinition#getAnalyserResourceBundleName()
*/
@Override
public String getAnalyserResourceBundleName()
{
return analyserResourceBundleName;
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.dictionary.ClassDefinition#getParentClassDefinition()
*/

View File

@@ -40,86 +40,50 @@ public class M2DataType
private String defaultAnalyserClassName = null;
private String javaClassName = null;
private String analyserResourceBundleName = null;
/*package*/ M2DataType()
{
super();
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getTitle()
{
return title;
}
public void setTitle(String title)
{
this.title = title;
}
public String getDescription()
{
return description;
}
public void setDescription(String description)
{
this.description = description;
}
public String getDefaultAnalyserClassName()
{
return defaultAnalyserClassName;
}
public void setDefaultAnalyserClassName(String defaultAnalyserClassName)
{
this.defaultAnalyserClassName = defaultAnalyserClassName;;
}
public String getJavaClassName()
{
return javaClassName;
}
public void setJavaClassName(String javaClassName)
{
this.javaClassName = javaClassName;;
}
/**
* @return String
*/
public String getAnalyserResourceBundleName()
{
return analyserResourceBundleName;
}
public void setAnalyserResourceBundleName(String analyserResourceBundleName)
{
this.analyserResourceBundleName = analyserResourceBundleName;
}
}

View File

@@ -67,7 +67,6 @@ import org.alfresco.service.namespace.QName;
throw new DictionaryException(ERR_NOT_DEFINED_NAMESPACE, name.toPrefixString(), name.getNamespaceURI(), model.getName().toPrefixString());
}
this.dataType = propertyType;
this.analyserResourceBundleName = dataType.getAnalyserResourceBundleName();
}
@@ -146,108 +145,9 @@ import org.alfresco.service.namespace.QName;
return value;
}
@Override
public String getDefaultAnalyserClassName()
{
return dataType.getDefaultAnalyserClassName();
}
@Override
public String getJavaClassName()
{
return dataType.getJavaClassName();
}
@Override
public String getAnalyserResourceBundleName()
{
return analyserResourceBundleName;
}
@Override
public String resolveAnalyserClassName()
{
return resolveAnalyserClassName(I18NUtil.getLocale());
}
/**
* @param locale Locale
* @return String
*/
@Override
public String resolveAnalyserClassName(Locale locale)
{
ClassLoader resourceBundleClassLoader = getModel().getDictionaryDAO().getResourceClassLoader();
if(resourceBundleClassLoader == null)
{
resourceBundleClassLoader = this.getClass().getClassLoader();
}
StringBuilder keyBuilder = new StringBuilder(64);
keyBuilder.append(getModel().getName().toPrefixString());
keyBuilder.append(".datatype");
keyBuilder.append(".").append(getName().toPrefixString());
keyBuilder.append(".analyzer");
String key = StringUtils.replace(keyBuilder.toString(), ":", "_");
String analyserClassName = null;
String defaultAnalyserResourceBundleName = this.getModel().getDictionaryDAO().getDefaultAnalyserResourceBundleName();
if(defaultAnalyserResourceBundleName != null)
{
ResourceBundle bundle = ResourceBundle.getBundle(defaultAnalyserResourceBundleName, locale, resourceBundleClassLoader);
if(bundle.containsKey(key))
{
analyserClassName = bundle.getString(key);
}
}
String analyserResourceBundleName;
if(analyserClassName == null)
{
analyserResourceBundleName = dataType.getAnalyserResourceBundleName();
if(analyserResourceBundleName != null)
{
ResourceBundle bundle = ResourceBundle.getBundle(analyserResourceBundleName, locale, resourceBundleClassLoader);
if(bundle.containsKey(key))
{
analyserClassName = bundle.getString(key);
}
}
}
if(analyserClassName == null)
{
analyserResourceBundleName = getModel().getAnalyserResourceBundleName();
if(analyserResourceBundleName != null)
{
ResourceBundle bundle = ResourceBundle.getBundle(analyserResourceBundleName, locale, resourceBundleClassLoader);
if(bundle.containsKey(key))
{
analyserClassName = bundle.getString(key);
}
}
}
if(analyserClassName == null)
{
// MLTEXT should fall back to TEXT for analysis
if(name.equals(DataTypeDefinition.MLTEXT))
{
analyserClassName = model.getDictionaryDAO().getDataType(DataTypeDefinition.TEXT).resolveAnalyserClassName(locale);
if(analyserClassName == null)
{
analyserClassName = dataType.getDefaultAnalyserClassName();
}
}
else
{
analyserClassName = dataType.getDefaultAnalyserClassName();
}
}
return analyserClassName;
}
}

View File

@@ -469,21 +469,6 @@ public class M2Model
return new ArrayList();
}
/**
* @return String
*/
public String getAnalyserResourceBundleName()
{
return analyserResourceBundleName;
}
public void setAnalyserResourceBundleName(String analyserResourceBundleName)
{
this.analyserResourceBundleName = analyserResourceBundleName;
}
public void setConfigProperties(Properties configProperties)
{
if (types != null)

View File

@@ -55,7 +55,6 @@ public class M2ModelDefinition implements ModelDefinition
{
this.name = QName.createQName(model.getName(), resolver);
this.model = model;
this.analyserResourceBundleName = model.getAnalyserResourceBundleName();
this.dictionaryDAO = dictionaryDAO;
}
@@ -175,17 +174,6 @@ public class M2ModelDefinition implements ModelDefinition
return model.getChecksum(bindingType);
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.dictionary.ModelDefinition#getAnalyserResourceBundleName()
*/
@Override
public String getAnalyserResourceBundleName()
{
return analyserResourceBundleName;
}
@Override
public DictionaryDAO getDictionaryDAO()
{

View File

@@ -312,20 +312,6 @@ public class M2Property
}
}
}
/**
* @return String
*/
public String getAnalyserResourceBundleName()
{
return analyserResourceBundleName;
}
public void setAnalyserResourceBundleName(String analyserResourceBundleName)
{
this.analyserResourceBundleName = analyserResourceBundleName;
}
public void setConfigProperties(Properties configProperties)
{

View File

@@ -78,7 +78,6 @@ import org.springframework.util.StringUtils;
// Resolve Names
this.name = QName.createQName(m2Property.getName(), prefixResolver);
this.propertyTypeName = QName.createQName(m2Property.getType(), prefixResolver);
this.analyserResourceBundleName = m2Property.getAnalyserResourceBundleName();
}
@@ -689,119 +688,4 @@ import org.springframework.util.StringUtils;
return modelDiffs;
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.dictionary.PropertyDefinition#getAnalyserResourceBundleName()
*/
@Override
public String getAnalyserResourceBundleName()
{
return analyserResourceBundleName;
}
@Override
public String resolveAnalyserClassName()
{
return resolveAnalyserClassName(I18NUtil.getLocale());
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.dictionary.PropertyDefinition#getAnalyserClassName(java.lang.String, java.util.Locale)
*/
@Override
public String resolveAnalyserClassName(Locale locale
)
{
ClassLoader resourceBundleClassLoader = getModel().getDictionaryDAO().getResourceClassLoader();
if(resourceBundleClassLoader == null)
{
resourceBundleClassLoader = this.getClass().getClassLoader();
}
StringBuilder keyBuilder = new StringBuilder(64);
keyBuilder.append(getDataType().getModel().getName().toPrefixString());
keyBuilder.append(".datatype");
keyBuilder.append(".").append(getDataType().getName().toPrefixString());
keyBuilder.append(".analyzer");
String key = StringUtils.replace(keyBuilder.toString(), ":", "_");
String analyserClassName = null;
String analyserResourceBundleName = getAnalyserResourceBundleName();
if(analyserResourceBundleName != null)
{
ResourceBundle bundle = ResourceBundle.getBundle(analyserResourceBundleName, locale, resourceBundleClassLoader);
if(bundle.containsKey(key))
{
analyserClassName = bundle.getString(key);
}
}
// walk containing class and its hierarchy
ClassDefinition classDefinition = null;
ClassDefinition parentClassDefinition = null;
while(analyserClassName == null)
{
if(classDefinition == null)
{
classDefinition = getContainerClass();
}
else
{
if(parentClassDefinition == null)
{
break;
}
else
{
classDefinition = parentClassDefinition;
}
}
parentClassDefinition = classDefinition.getParentClassDefinition();
analyserResourceBundleName = classDefinition.getAnalyserResourceBundleName();
if(analyserResourceBundleName != null)
{
ResourceBundle bundle = ResourceBundle.getBundle(analyserResourceBundleName, locale, resourceBundleClassLoader);
if(bundle.containsKey(key))
{
analyserClassName = bundle.getString(key);
}
}
if(analyserClassName == null)
{
if((parentClassDefinition == null) || !classDefinition.getModel().getName().equals(parentClassDefinition.getModel().getName()))
{
analyserResourceBundleName = classDefinition.getModel().getAnalyserResourceBundleName();
if(analyserResourceBundleName != null)
{
ResourceBundle bundle = ResourceBundle.getBundle(analyserResourceBundleName, locale, resourceBundleClassLoader);
if(bundle.containsKey(key))
{
analyserClassName = bundle.getString(key);
}
}
}
}
}
String defaultAnalyserResourceBundleName = this.getContainerClass().getModel().getDictionaryDAO().getDefaultAnalyserResourceBundleName();
if(analyserClassName == null)
{
if(defaultAnalyserResourceBundleName != null)
{
ResourceBundle bundle = ResourceBundle.getBundle(defaultAnalyserResourceBundleName, locale, resourceBundleClassLoader);
if(bundle.containsKey(key))
{
analyserClassName = bundle.getString(key);
}
}
}
if(analyserClassName == null)
{
analyserClassName = getDataType().resolveAnalyserClassName(locale);
}
return analyserClassName;
}
}

View File

@@ -12,7 +12,7 @@
<value name="published" field="published" usage="optional"/>
<value name="version" field="version" usage="optional"/>
<value name="analyserResourceBundleName" field="analyserResourceBundleName" usage="optional"/>
<structure name="imports" usage="optional">
<collection field="imports" factory="org.alfresco.repo.dictionary.M2Model.createList">
<structure name="import" type="org.alfresco.repo.dictionary.M2Namespace" usage="optional">
@@ -37,7 +37,7 @@
<value style="attribute" name="name" field="name"/>
<value name="title" field="title" usage="optional"/>
<value name="description" field="description" usage="optional"/>
<value name="default-analyser-class" field="defaultAnalyserClassName"/>
<value name="default-analyser-class" field="defaultAnalyserClassName" usage="optional"/>
<value name="analyserResourceBundleName" field="analyserResourceBundleName" usage="optional"/>
<value name="java-class" field="javaClassName"/>
</structure>
@@ -179,4 +179,4 @@
<value name="propagateTimestamps" field="propagateTimestamps" usage="optional"/>
</mapping>
</binding>
</binding>

View File

@@ -149,12 +149,6 @@ public interface ClassDefinition
*/
public List<AspectDefinition> getDefaultAspects(boolean inherited);
/**
* Get the name of the property bundle that defines analyser mappings for this class (keyed by the type of the property)
* @return the resource or null if not set.
*/
public String getAnalyserResourceBundleName();
/**
* Get the parent class definition
*

View File

@@ -98,33 +98,8 @@ public interface DataTypeDefinition
*/
public String getDescription(MessageLookup messageLookup);
/**
* Get the name of the property bundle that defines analyser mappings for this data type (keyed by the type of the property)
* @return the resource or null if not set.
*/
public String getAnalyserResourceBundleName();
/**
* @return the equivalent java class name (or null, if not mapped)
*/
public String getJavaClassName();
/**
* Get the default analyser class - used when no resource bundles can be found and no repository default is set.
* @return String
*/
public String getDefaultAnalyserClassName();
/**
* @param locale
* @return String
*/
public String resolveAnalyserClassName(Locale locale);
/**
*
* @return String
*/
public String resolveAnalyserClassName();
}

View File

@@ -105,12 +105,6 @@ public interface ModelDefinition
public long getChecksum(XMLBindingType bindingType);
/**
* Get the name of the property bundle that defines analyser mappings for this model (keyed by the type of the property)
* @return the resource or null if not set.
*/
public String getAnalyserResourceBundleName();
/**
* @return DictionaryDAO
*/

View File

@@ -161,22 +161,4 @@ public interface PropertyDefinition extends ClassAttributeDefinition
* @return Returns a list of property constraint definitions
*/
public List<ConstraintDefinition> getConstraints();
/**
* Get the name of the property bundle that defines analyser mappings for this class.
* @return the resource or null if not set.
*/
public String getAnalyserResourceBundleName();
/**
* @param locale Locale
* @return String
*/
public String resolveAnalyserClassName(Locale locale);
/**
*
* @return String
*/
public String resolveAnalyserClassName();
}

View File

@@ -41,9 +41,6 @@
<property name="dictionaryRegistryCache">
<ref bean="compiledModelsCache"/>
</property>
<property name="defaultAnalyserResourceBundleName">
<value>${lucene.defaultAnalyserResourceBundleName}</value>
</property>
</bean>
<bean id="threadFactory" class="org.alfresco.util.TraceableThreadFactory">

View File

@@ -16,16 +16,19 @@
<data-types>
<data-type name="cmis:id">
<!-- Analysers are EOLed, left here for backwards compatibility -->
<default-analyser-class>org.alfresco.repo.search.impl.lucene.analysis.AlfrescoStandardAnalyser</default-analyser-class>
<java-class>java.lang.String</java-class>
</data-type>
<data-type name="cmis:uri">
<!-- Analysers are EOLed, left here for backwards compatibility -->
<default-analyser-class>org.alfresco.repo.search.impl.lucene.analysis.AlfrescoStandardAnalyser</default-analyser-class>
<java-class>java.lang.String</java-class>
</data-type>
<data-type name="cmis:html">
<!-- Analysers are EOLed, left here for backwards compatibility -->
<default-analyser-class>org.alfresco.repo.search.impl.lucene.analysis.AlfrescoStandardAnalyser</default-analyser-class>
<java-class>java.lang.String</java-class>
</data-type>
@@ -436,4 +439,4 @@
</types>
</model>
</model>

View File

@@ -1,18 +0,0 @@
# Data Type Index Analyzers
d_dictionary.datatype.d_any.analyzer=org.alfresco.repo.search.impl.lucene.analysis.AlfrescoStandardAnalyser
d_dictionary.datatype.d_text.analyzer=org.alfresco.repo.search.impl.lucene.analysis.AlfrescoStandardAnalyser
d_dictionary.datatype.d_content.analyzer=org.alfresco.repo.search.impl.lucene.analysis.AlfrescoStandardAnalyser
d_dictionary.datatype.d_int.analyzer=org.alfresco.repo.search.impl.lucene.analysis.IntegerAnalyser
d_dictionary.datatype.d_long.analyzer=org.alfresco.repo.search.impl.lucene.analysis.LongAnalyser
d_dictionary.datatype.d_float.analyzer=org.alfresco.repo.search.impl.lucene.analysis.FloatAnalyser
d_dictionary.datatype.d_double.analyzer=org.alfresco.repo.search.impl.lucene.analysis.DoubleAnalyser
d_dictionary.datatype.d_date.analyzer=org.alfresco.repo.search.impl.lucene.analysis.DateAnalyser
d_dictionary.datatype.d_datetime.analyzer=org.alfresco.repo.search.impl.lucene.analysis.DateAnalyser
d_dictionary.datatype.d_boolean.analyzer=org.alfresco.repo.search.impl.lucene.analysis.AlfrescoStandardAnalyser
d_dictionary.datatype.d_qname.analyzer=org.alfresco.repo.search.impl.lucene.analysis.AlfrescoStandardAnalyser
d_dictionary.datatype.d_guid.analyzer=org.alfresco.repo.search.impl.lucene.analysis.AlfrescoStandardAnalyser
d_dictionary.datatype.d_category.analyzer=org.alfresco.repo.search.impl.lucene.analysis.AlfrescoStandardAnalyser
d_dictionary.datatype.d_noderef.analyzer=org.alfresco.repo.search.impl.lucene.analysis.AlfrescoStandardAnalyser
d_dictionary.datatype.d_path.analyzer=org.alfresco.repo.search.impl.lucene.analysis.AlfrescoStandardAnalyser
d_dictionary.datatype.d_locale.analyzer=org.alfresco.repo.search.impl.lucene.analysis.LowerCaseVerbatimAnalyser

View File

@@ -1,4 +0,0 @@
# Data Type Index Analyzers
d_dictionary.datatype.d_text.analyzer=org.apache.lucene.analysis.cz.CzechAnalyzer
d_dictionary.datatype.d_content.analyzer=org.apache.lucene.analysis.cz.CzechAnalyzer

View File

@@ -1,4 +0,0 @@
# Data Type Index Analyzers
d_dictionary.datatype.d_text.analyzer=org.alfresco.repo.search.impl.lucene.analysis.DanishSnowballAnalyser
d_dictionary.datatype.d_content.analyzer=org.alfresco.repo.search.impl.lucene.analysis.DanishSnowballAnalyser

View File

@@ -1,4 +0,0 @@
# Data Type Index Analyzers
d_dictionary.datatype.d_text.analyzer=org.apache.lucene.analysis.de.GermanAnalyzer
d_dictionary.datatype.d_content.analyzer=org.apache.lucene.analysis.de.GermanAnalyzer

View File

@@ -1,4 +0,0 @@
# Data Type Index Analyzers
d_dictionary.datatype.d_text.analyzer=org.apache.lucene.analysis.el.GreekAnalyzer
d_dictionary.datatype.d_content.analyzer=org.apache.lucene.analysis.el.GreekAnalyzer

View File

@@ -1,4 +0,0 @@
# Data Type Index Analyzers
d_dictionary.datatype.d_text.analyzer=org.alfresco.repo.search.impl.lucene.analysis.AlfrescoStandardAnalyser
d_dictionary.datatype.d_content.analyzer=org.alfresco.repo.search.impl.lucene.analysis.AlfrescoStandardAnalyser

View File

@@ -1,4 +0,0 @@
# Data Type Index Analyzers
d_dictionary.datatype.d_text.analyzer=org.alfresco.repo.search.impl.lucene.analysis.SpanishSnowballAnalyser
d_dictionary.datatype.d_content.analyzer=org.alfresco.repo.search.impl.lucene.analysis.SpanishSnowballAnalyser

View File

@@ -1,4 +0,0 @@
# Data Type Index Analyzers
d_dictionary.datatype.d_text.analyzer=org.alfresco.repo.search.impl.lucene.analysis.FinnishSnowballAnalyser
d_dictionary.datatype.d_content.analyzer=org.alfresco.repo.search.impl.lucene.analysis.FinnishSnowballAnalyser

View File

@@ -1,4 +0,0 @@
# Data Type Index Analyzers
d_dictionary.datatype.d_text.analyzer=org.apache.lucene.analysis.fr.FrenchAnalyzer
d_dictionary.datatype.d_content.analyzer=org.apache.lucene.analysis.fr.FrenchAnalyzer

View File

@@ -1,4 +0,0 @@
# Data Type Index Analyzers
d_dictionary.datatype.d_text.analyzer=org.alfresco.repo.search.impl.lucene.analysis.ItalianSnowballAnalyser
d_dictionary.datatype.d_content.analyzer=org.alfresco.repo.search.impl.lucene.analysis.ItalianSnowballAnalyser

View File

@@ -1,4 +0,0 @@
# Data Type Index Analyzers
d_dictionary.datatype.d_text.analyzer=org.apache.lucene.analysis.cjk.CJKAnalyzer
d_dictionary.datatype.d_content.analyzer=org.apache.lucene.analysis.cjk.CJKAnalyzer

View File

@@ -1,4 +0,0 @@
# Data Type Index Analyzers
d_dictionary.datatype.d_text.analyzer=org.apache.lucene.analysis.cjk.CJKAnalyzer
d_dictionary.datatype.d_content.analyzer=org.apache.lucene.analysis.cjk.CJKAnalyzer

View File

@@ -1,4 +0,0 @@
# Data Type Index Analyzers
d_dictionary.datatype.d_text.analyzer=org.apache.lucene.analysis.nl.DutchAnalyzer
d_dictionary.datatype.d_content.analyzer=org.apache.lucene.analysis.nl.DutchAnalyzer

View File

@@ -1,4 +0,0 @@
# Data Type Index Analyzers
d_dictionary.datatype.d_text.analyzer=org.alfresco.repo.search.impl.lucene.analysis.NorwegianSnowballAnalyser
d_dictionary.datatype.d_content.analyzer=org.alfresco.repo.search.impl.lucene.analysis.NorwegianSnowballAnalyser

View File

@@ -1,4 +0,0 @@
# Data Type Index Analyzers
d_dictionary.datatype.d_text.analyzer=org.alfresco.repo.search.impl.lucene.analysis.PortugueseSnowballAnalyser
d_dictionary.datatype.d_content.analyzer=org.alfresco.repo.search.impl.lucene.analysis.PortugueseSnowballAnalyser

View File

@@ -1,4 +0,0 @@
# Data Type Index Analyzers
d_dictionary.datatype.d_text.analyzer=org.apache.lucene.analysis.br.BrazilianAnalyzer
d_dictionary.datatype.d_content.analyzer=org.apache.lucene.analysis.br.BrazilianAnalyzer

View File

@@ -1,4 +0,0 @@
# Data Type Index Analyzers
d_dictionary.datatype.d_text.analyzer=org.apache.lucene.analysis.ru.RussianAnalyzer
d_dictionary.datatype.d_content.analyzer=org.apache.lucene.analysis.ru.RussianAnalyzer

View File

@@ -1,4 +0,0 @@
# Data Type Index Analyzers
d_dictionary.datatype.d_text.analyzer=org.alfresco.repo.search.impl.lucene.analysis.SwedishSnowballAnalyser
d_dictionary.datatype.d_content.analyzer=org.alfresco.repo.search.impl.lucene.analysis.SwedishSnowballAnalyser

View File

@@ -1,4 +0,0 @@
# Data Type Index Analyzers
d_dictionary.datatype.d_text.analyzer=org.apache.lucene.analysis.th.ThaiAnalyzer
d_dictionary.datatype.d_content.analyzer=org.apache.lucene.analysis.th.ThaiAnalyzer

View File

@@ -1,4 +0,0 @@
# Data Type Index Analyzers
d_dictionary.datatype.d_text.analyzer=org.apache.lucene.analysis.cn.ChineseAnalyzer
d_dictionary.datatype.d_content.analyzer=org.apache.lucene.analysis.cn.ChineseAnalyzer

View File

@@ -4,8 +4,9 @@
<author>Alfresco</author>
<published>2005-09-29</published>
<version>1.0</version>
<!-- Analysers are EOLed, left here for backwards compatibility -->
<analyserResourceBundleName>alfresco/model/dataTypeAnalyzers</analyserResourceBundleName>
<namespaces>
<!-- Default Namespace -->
<namespace uri="" prefix=""/>
@@ -20,11 +21,13 @@
<data-types>
<data-type name="d:any">
<!-- Analysers are EOLed, left here for backwards compatibility -->
<default-analyser-class>org.alfresco.repo.search.impl.lucene.analysis.AlfrescoStandardAnalyser</default-analyser-class>
<java-class>java.lang.Object</java-class>
</data-type>
<data-type name="d:encrypted">
<!-- Analysers are EOLed, left here for backwards compatibility -->
<default-analyser-class>org.alfresco.repo.search.impl.lucene.analysis.EmptyAnalyser</default-analyser-class>
<java-class>javax.crypto.SealedObject</java-class>
</data-type>
@@ -35,91 +38,109 @@
</data-type>
<data-type name="d:mltext">
<!-- Analysers are EOLed, left here for backwards compatibility -->
<default-analyser-class>org.alfresco.repo.search.impl.lucene.analysis.AlfrescoStandardAnalyser</default-analyser-class>
<java-class>org.alfresco.service.cmr.repository.MLText</java-class>
</data-type>
<data-type name="d:content">
<!-- Analysers are EOLed, left here for backwards compatibility -->
<default-analyser-class>org.alfresco.repo.search.impl.lucene.analysis.AlfrescoStandardAnalyser</default-analyser-class>
<java-class>org.alfresco.service.cmr.repository.ContentData</java-class>
</data-type>
<data-type name="d:int">
<!-- Analysers are EOLed, left here for backwards compatibility -->
<default-analyser-class>org.alfresco.repo.search.impl.lucene.analysis.IntegerAnalyser</default-analyser-class>
<java-class>java.lang.Integer</java-class>
</data-type>
<data-type name="d:long">
<!-- Analysers are EOLed, left here for backwards compatibility -->
<default-analyser-class>org.alfresco.repo.search.impl.lucene.analysis.LongAnalyser</default-analyser-class>
<java-class>java.lang.Long</java-class>
</data-type>
<data-type name="d:float">
<!-- Analysers are EOLed, left here for backwards compatibility -->
<default-analyser-class>org.alfresco.repo.search.impl.lucene.analysis.FloatAnalyser</default-analyser-class>
<java-class>java.lang.Float</java-class>
</data-type>
<data-type name="d:double">
<!-- Analysers are EOLed, left here for backwards compatibility -->
<default-analyser-class>org.alfresco.repo.search.impl.lucene.analysis.DoubleAnalyser</default-analyser-class>
<java-class>java.lang.Double</java-class>
</data-type>
<data-type name="d:date">
<!-- Analysers are EOLed, left here for backwards compatibility -->
<default-analyser-class>org.alfresco.repo.search.impl.lucene.analysis.DateAnalyser</default-analyser-class>
<java-class>java.util.Date</java-class>
</data-type>
<data-type name="d:datetime">
<!-- Analysers are EOLed, left here for backwards compatibility -->
<default-analyser-class>org.alfresco.repo.search.impl.lucene.analysis.DateTimeAnalyser</default-analyser-class>
<java-class>java.util.Date</java-class>
</data-type>
<data-type name="d:boolean">
<!-- Analysers are EOLed, left here for backwards compatibility -->
<default-analyser-class>org.alfresco.repo.search.impl.lucene.analysis.AlfrescoStandardAnalyser</default-analyser-class>
<java-class>java.lang.Boolean</java-class>
</data-type>
<data-type name="d:qname">
<!-- Analysers are EOLed, left here for backwards compatibility -->
<default-analyser-class>org.alfresco.repo.search.impl.lucene.analysis.AlfrescoStandardAnalyser</default-analyser-class>
<java-class>org.alfresco.service.namespace.QName</java-class>
</data-type>
<data-type name="d:noderef">
<!-- Analysers are EOLed, left here for backwards compatibility -->
<default-analyser-class>org.alfresco.repo.search.impl.lucene.analysis.AlfrescoStandardAnalyser</default-analyser-class>
<java-class>org.alfresco.service.cmr.repository.NodeRef</java-class>
</data-type>
<data-type name="d:childassocref">
<!-- Analysers are EOLed, left here for backwards compatibility -->
<default-analyser-class>org.alfresco.repo.search.impl.lucene.analysis.AlfrescoStandardAnalyser</default-analyser-class>
<java-class>org.alfresco.service.cmr.repository.ChildAssociationRef</java-class>
</data-type>
<data-type name="d:assocref">
<!-- Analysers are EOLed, left here for backwards compatibility -->
<default-analyser-class>org.alfresco.repo.search.impl.lucene.analysis.AlfrescoStandardAnalyser</default-analyser-class>
<java-class>org.alfresco.service.cmr.repository.AssociationRef</java-class>
</data-type>
<data-type name="d:path">
<!-- Analysers are EOLed, left here for backwards compatibility -->
<default-analyser-class>org.alfresco.repo.search.impl.lucene.analysis.AlfrescoStandardAnalyser</default-analyser-class>
<java-class>org.alfresco.service.cmr.repository.Path</java-class>
</data-type>
<data-type name="d:category">
<!-- Analysers are EOLed, left here for backwards compatibility -->
<default-analyser-class>org.alfresco.repo.search.impl.lucene.analysis.AlfrescoStandardAnalyser</default-analyser-class>
<java-class>org.alfresco.service.cmr.repository.NodeRef</java-class>
</data-type>
<data-type name="d:locale">
<!-- Analysers are EOLed, left here for backwards compatibility -->
<default-analyser-class>org.alfresco.repo.search.impl.lucene.analysis.VerbatimAnalyser</default-analyser-class>
<java-class>java.util.Locale</java-class>
</data-type>
<data-type name="d:version">
<!-- Analysers are EOLed, left here for backwards compatibility -->
<default-analyser-class>org.alfresco.repo.search.impl.lucene.analysis.VerbatimAnalyser</default-analyser-class>
<java-class>org.alfresco.util.VersionNumber</java-class>
</data-type>
<data-type name="d:period">
<data-type name="d:period">
<!-- Analysers are EOLed, left here for backwards compatibility -->
<default-analyser-class>org.alfresco.repo.search.impl.lucene.analysis.VerbatimAnalyser</default-analyser-class>
<java-class>org.alfresco.service.cmr.repository.Period</java-class>
</data-type>
@@ -128,5 +149,5 @@
<!-- TODO: Define dictionary meta model -->
</model>

View File

@@ -4,21 +4,21 @@
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
*
* 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/>.
* #L%
@@ -36,7 +36,6 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
@@ -69,7 +68,7 @@ import org.junit.Test;
import org.springframework.extensions.surf.util.I18NUtil;
/**
*
*
* @author sglover
*
*/
@@ -80,6 +79,7 @@ public class DictionaryDAOTest
private static final String TEST_URL = "http://www.alfresco.org/test/dictionarydaotest/1.0";
private static final String TEST2_URL = "http://www.alfresco.org/test/dictionarydaotest2/1.0";
private static final String TEST_MODEL = "org/alfresco/repo/dictionary/dictionarydaotest_model.xml";
private static final String TEST_MODEL_NEW_FORMAT = "org/alfresco/repo/dictionary/dictionarydaotest_model_new_format.xml";
private static final String TEST_NS_CLASH_MODEL = "org/alfresco/repo/dictionary/nstest_model.xml";
private static final String TEST_BUNDLE = "org/alfresco/repo/dictionary/dictionarydaotest_model";
private static final String TEST_COMMON_NS_PARENT_MODEL = "org/alfresco/repo/dictionary/commonpropertynsparent_model.xml";
@@ -90,7 +90,7 @@ public class DictionaryDAOTest
@Before
public void setUp() throws Exception
{
{
// register resource bundles for messages
I18NUtil.registerResourceBundle(TEST_RESOURCE_MESSAGES);
@@ -119,7 +119,7 @@ public class DictionaryDAOTest
component.setMessageLookup(new StaticMessageLookup());
service = component;
}
private void initDictionaryCaches(DictionaryDAOImpl dictionaryDAO, TenantService tenantService)
{
CompiledModelsCache compiledModelsCache = new CompiledModelsCache();
@@ -140,17 +140,17 @@ public class DictionaryDAOTest
@Test
public void testBootstrap()
{
TenantService tenantService = new SingleTServiceImpl();
TenantService tenantService = new SingleTServiceImpl();
DictionaryDAOImpl dictionaryDAO = new DictionaryDAOImpl();
dictionaryDAO.setTenantService(tenantService);
initDictionaryCaches(dictionaryDAO, tenantService);
DictionaryBootstrap bootstrap = new DictionaryBootstrap();
List<String> bootstrapModels = new ArrayList<String>();
bootstrapModels.add("alfresco/model/dictionaryModel.xml");
bootstrap.setModels(bootstrapModels);
bootstrap.setDictionaryDAO(dictionaryDAO);
bootstrap.setTenantService(tenantService);
@@ -168,10 +168,10 @@ public class DictionaryDAOTest
DictionaryDAOImpl dictionaryDAO = new DictionaryDAOImpl();
dictionaryDAO.setTenantService(tenantService);
initDictionaryCaches(dictionaryDAO, tenantService);
DictionaryBootstrap bootstrap = new DictionaryBootstrap();
List<String> bootstrapModels = new ArrayList<String>();
bootstrapModels.add("alfresco/model/dictionaryModel.xml");
bootstrapModels.add(TEST_MODEL);
bootstrapModels.add(TEST_NS_CLASH_MODEL);
@@ -191,6 +191,37 @@ public class DictionaryDAOTest
// Good!
}
}
@Test
public void testNamespaceClashResultsInSensibleErrorWithNewFormat()
{
TenantService tenantService = new SingleTServiceImpl();
DictionaryDAOImpl dictionaryDAO = new DictionaryDAOImpl();
dictionaryDAO.setTenantService(tenantService);
initDictionaryCaches(dictionaryDAO, tenantService);
DictionaryBootstrap bootstrap = new DictionaryBootstrap();
List<String> bootstrapModels = new ArrayList<String>();
bootstrapModels.add("alfresco/model/dictionaryModel_new_format.xml");
bootstrapModels.add(TEST_MODEL_NEW_FORMAT);
bootstrapModels.add(TEST_NS_CLASH_MODEL);
bootstrap.setModels(bootstrapModels);
bootstrap.setDictionaryDAO(dictionaryDAO);
bootstrap.setTenantService(tenantService);
try
{
bootstrap.bootstrap();
fail("Expected "+NamespaceException.class.getName()+" to be thrown, but it was not.");
}
catch (NamespaceException e)
{
System.out.println(e.getMessage());
// Good!
}
}
@Test
public void testUseImportedNamespaces()
@@ -200,14 +231,36 @@ public class DictionaryDAOTest
DictionaryDAOImpl dictionaryDAO = new DictionaryDAOImpl();
dictionaryDAO.setTenantService(tenantService);
initDictionaryCaches(dictionaryDAO, tenantService);
DictionaryBootstrap bootstrap = new DictionaryBootstrap();
List<String> bootstrapModels = new ArrayList<String>();
bootstrapModels.add("alfresco/model/dictionaryModel.xml");
bootstrapModels.add(TEST_COMMON_NS_PARENT_MODEL);
bootstrapModels.add(TEST_COMMON_NS_CHILD_MODEL);
bootstrap.setModels(bootstrapModels);
bootstrap.setDictionaryDAO(dictionaryDAO);
bootstrap.setTenantService(tenantService);
bootstrap.bootstrap();
}
@Test
public void testUseImportedNamespacesWithNewFormat()
{
TenantService tenantService = new SingleTServiceImpl();
DictionaryDAOImpl dictionaryDAO = new DictionaryDAOImpl();
dictionaryDAO.setTenantService(tenantService);
initDictionaryCaches(dictionaryDAO, tenantService);
DictionaryBootstrap bootstrap = new DictionaryBootstrap();
List<String> bootstrapModels = new ArrayList<String>();
bootstrapModels.add("alfresco/model/dictionaryModel_new_format.xml");
bootstrapModels.add(TEST_COMMON_NS_PARENT_MODEL);
bootstrapModels.add(TEST_COMMON_NS_CHILD_MODEL);
bootstrap.setModels(bootstrapModels);
bootstrap.setDictionaryDAO(dictionaryDAO);
bootstrap.setTenantService(tenantService);
@@ -220,32 +273,31 @@ public class DictionaryDAOTest
QName model = QName.createQName(TEST_URL, "dictionarydaotest");
ModelDefinition modelDef = service.getModel(model);
assertEquals("Model Description", modelDef.getDescription(service));
QName type = QName.createQName(TEST_URL, "base");
TypeDefinition typeDef = service.getType(type);
assertEquals("Base Title", typeDef.getTitle(service));
assertEquals("Base Description", typeDef.getDescription(service));
QName prop = QName.createQName(TEST_URL, "prop1");
PropertyDefinition propDef = service.getProperty(prop);
assertEquals("Prop1 Title", propDef.getTitle(service));
assertEquals("Prop1 Description", propDef.getDescription(service));
QName assoc = QName.createQName(TEST_URL, "assoc1");
AssociationDefinition assocDef = service.getAssociation(assoc);
assertEquals("Assoc1 Title", assocDef.getTitle(service));
assertEquals("Assoc1 Description", assocDef.getDescription(service));
QName datatype = QName.createQName(TEST_URL, "datatype");
DataTypeDefinition datatypeDef = service.getDataType(datatype);
assertEquals("alfresco/model/dataTypeAnalyzers", datatypeDef.getAnalyserResourceBundleName());
QName constraint = QName.createQName(TEST_URL, "list1");
ConstraintDefinition constraintDef = service.getConstraint(constraint);
assertEquals("List1 title", constraintDef.getTitle(service));
assertEquals("List1 description", constraintDef.getDescription(service));
// Localisation of List Of Values Constraint.
// 1. LoV defined at the top of the model.
ListOfValuesConstraint lovConstraint = (ListOfValuesConstraint)constraintDef.getConstraint();
@@ -254,7 +306,7 @@ public class DictionaryDAOTest
assertEquals("Wrong localised lov value.", "VALUE WITH SPACES display", lovConstraint.getDisplayLabel("VALUE WITH SPACES", service)); // Keys with spaces.
assertEquals("Wrong localised lov value.", "VALUE WITH TRAILING SPACE display", lovConstraint.getDisplayLabel("VALUE WITH TRAILING SPACE ", service)); // Keys with trailing space.
assertNull(lovConstraint.getDisplayLabel("nosuchLOV", service));
// 2. A named LoV defined within a specific property "non-Ref".
QName constrainedPropName = QName.createQName(TEST_URL, "constrainedProp");
PropertyDefinition constrainedPropDef = service.getProperty(constrainedPropName);
@@ -267,23 +319,23 @@ public class DictionaryDAOTest
assertEquals("Wrong localised lov value.", "GAMMA, DELTA display", lovConstraint.getDisplayLabel("GAMMA, DELTA", service)); // Keys with commas
assertEquals("Wrong localised lov value.", "OMEGA", lovConstraint.getDisplayLabel("OMEGA", service));
assertNull(lovConstraint.getDisplayLabel("nosuchLOV", service));
// Localisation of unnamed LoV defined within a specific property are not supported.
}
@Test
public void testConstraints()
{
{
QName model = QName.createQName(TEST_URL, "dictionarydaotest");
Collection<ConstraintDefinition> modelConstraints = service.getConstraints(model);
assertEquals(23, modelConstraints.size()); // 10 + 7 + 6
QName conRegExp1QName = QName.createQName(TEST_URL, "regex1");
boolean found1 = false;
QName conStrLen1QName = QName.createQName(TEST_URL, "stringLength1");
boolean found2 = false;
for (ConstraintDefinition constraintDef : modelConstraints)
{
if (constraintDef.getName().equals(conRegExp1QName))
@@ -292,7 +344,7 @@ public class DictionaryDAOTest
assertEquals("Regex1 description", constraintDef.getDescription(service));
found1 = true;
}
if (constraintDef.getName().equals(conStrLen1QName))
{
assertNull(constraintDef.getTitle(service));
@@ -302,12 +354,12 @@ public class DictionaryDAOTest
}
assertTrue(found1);
assertTrue(found2);
// get the constraints for a property without constraints
QName propNoConstraintsQName = QName.createQName(TEST_URL, "fileprop");
PropertyDefinition propNoConstraintsDef = service.getProperty(propNoConstraintsQName);
assertNotNull("Property without constraints returned null list", propNoConstraintsDef.getConstraints());
// get the constraints defined for the property
QName prop1QName = QName.createQName(TEST_URL, "prop1");
PropertyDefinition propDef = service.getProperty(prop1QName);
@@ -317,21 +369,21 @@ public class DictionaryDAOTest
assertTrue("Constraint instance incorrect", constraints.get(0).getConstraint() instanceof RegexConstraint);
assertTrue("Constraint instance incorrect", constraints.get(1).getConstraint() instanceof StringLengthConstraint);
assertTrue("Constraint instance incorrect", constraints.get(2).getConstraint() instanceof RegisteredConstraint);
// check the individual constraints
ConstraintDefinition constraintDef = constraints.get(0);
assertTrue("Constraint anonymous name incorrect", constraintDef.getName().getLocalName().equals("dictionarydaotest_base_prop1_anon_0"));
// inherit title / description for reference constraint
assertTrue("Constraint title incorrect", constraintDef.getTitle(service).equals("Regex1 title"));
assertTrue("Constraint description incorrect", constraintDef.getDescription(service).equals("Regex1 description"));
constraintDef = constraints.get(1);
assertTrue("Constraint anonymous name incorrect", constraintDef.getName().getLocalName().equals("dictionarydaotest_base_prop1_anon_1"));
assertTrue("Constraint title incorrect", constraintDef.getTitle(service).equals("Prop1 Strlen1 title"));
assertTrue("Constraint description incorrect", constraintDef.getDescription(service).equals("Prop1 Strlen1 description"));
// check that the constraint implementation is valid (it used a reference)
Constraint constraint = constraintDef.getConstraint();
assertNotNull("Reference constraint has no implementation", constraint);
@@ -406,7 +458,7 @@ public class DictionaryDAOTest
allowedValues = constraint.getAllowedValues();
assertEquals("Expected 1 allowed values", 1, allowedValues.size());
assertEquals("HIJ", allowedValues.get(0));
// check the inherited property on second derived aspect
propDef = service.getProperty(aspectTwoQName, propQName);
assertNotNull(propDef);
@@ -425,7 +477,7 @@ public class DictionaryDAOTest
allowedValues = constraint.getAllowedValues();
assertEquals("Wrong number of allowed values", 1, allowedValues.size());
assertEquals("HIJ", allowedValues.get(0));
// check the cross-namespace inheritance
propDef = service.getProperty(aspectThreeQName, propQName);
assertNotNull(propDef);
@@ -466,7 +518,7 @@ public class DictionaryDAOTest
QName testEnforcedQName = QName.createQName(TEST_URL, "enforced");
ClassDefinition testEnforcedClassDef = service.getClass(testEnforcedQName);
Map<QName, PropertyDefinition> testEnforcedPropertyDefs = testEnforcedClassDef.getProperties();
PropertyDefinition propertyDef = null;
QName testMandatoryEnforcedQName = QName.createQName(TEST_URL, "mandatory-enforced");
@@ -508,12 +560,12 @@ public class DictionaryDAOTest
// Test invalid args
boolean testI1 = service.isSubClass(invalid, referenceable);
assertFalse(testI1);
boolean testI2 = service.isSubClass(referenceable, invalid);
assertFalse(testI2);
boolean testI3 = service.isSubClass(invalid, invalid);
assertFalse(testI3);
@@ -529,7 +581,7 @@ public class DictionaryDAOTest
boolean test5 = service.isSubClass(base, folder); // reversed test
assertFalse(test5);
}
@Test
public void testPropertyOverride()
{
@@ -538,7 +590,7 @@ public class DictionaryDAOTest
PropertyDefinition prop1 = props1.get(QName.createQName(TEST_URL, "propoverride"));
String def1 = prop1.getDefaultValue();
assertEquals("one", def1);
TypeDefinition type2 = service.getType(QName.createQName(TEST_URL, "overridetype2"));
Map<QName, PropertyDefinition> props2 = type2.getProperties();
PropertyDefinition prop2 = props2.get(QName.createQName(TEST_URL, "propoverride"));
@@ -569,541 +621,6 @@ public class DictionaryDAOTest
childAssocDef = (ChildAssociationDefinition) assocDef;
assertTrue("Expected 'true' for timestamp propagation", childAssocDef.getPropagateTimestamps());
}
@Test
public void testDataTypeAnlyserResolution()
{
// Stuff to configure/
TenantService tenantService = new SingleTServiceImpl();
DictionaryDAOImpl dictionaryDAO = new DictionaryDAOImpl();
dictionaryDAO.setTenantService(tenantService);
initDictionaryCaches(dictionaryDAO, tenantService);
ModelDefinition modelDefinition;
DataTypeDefinition dataTypeDefinition;
//
dictionaryDAO.putModel(createModel(dictionaryDAO, false, false, false));
QName modeQName = QName.createQName("test:analyzerModel", dictionaryDAO);
QName dataTypeQName = QName.createQName("test:analyzerDataType", dictionaryDAO);
modelDefinition = dictionaryDAO.getModel(modeQName);
assertEquals(modelDefinition.getAnalyserResourceBundleName(), null);
dataTypeDefinition = dictionaryDAO.getDataType(dataTypeQName);
assertEquals(dataTypeDefinition.getAnalyserResourceBundleName(), null);
assertEquals(dataTypeDefinition.getDefaultAnalyserClassName(), null);
assertNull(dataTypeDefinition.resolveAnalyserClassName());
dictionaryDAO.setDefaultAnalyserResourceBundleName("defaultBundle");
try
{
dataTypeDefinition.resolveAnalyserClassName();
fail();
}
catch(MissingResourceException mre)
{
assertTrue(mre.getMessage().contains("defaultBundle"));
}
dictionaryDAO.setDefaultAnalyserResourceBundleName(null);
dictionaryDAO.removeModel(modeQName);
//
dictionaryDAO.putModel(createModel(dictionaryDAO, false, false, true));
modelDefinition = dictionaryDAO.getModel(modeQName);
assertEquals(modelDefinition.getAnalyserResourceBundleName(), null);
dataTypeDefinition = dictionaryDAO.getDataType(dataTypeQName);
assertEquals(dataTypeDefinition.getAnalyserResourceBundleName(), null);
assertEquals(dataTypeDefinition.getDefaultAnalyserClassName(), "java.lang.String");
assertEquals(dataTypeDefinition.resolveAnalyserClassName(), "java.lang.String");
dictionaryDAO.setDefaultAnalyserResourceBundleName("defaultBundle");
try
{
dataTypeDefinition.resolveAnalyserClassName();
fail();
}
catch(MissingResourceException mre)
{
assertTrue(mre.getMessage().contains("defaultBundle"));
}
dictionaryDAO.setDefaultAnalyserResourceBundleName(null);
dictionaryDAO.removeModel(modeQName);
//
dictionaryDAO.putModel(createModel(dictionaryDAO, false, true, false));
modelDefinition = dictionaryDAO.getModel(modeQName);
assertEquals(modelDefinition.getAnalyserResourceBundleName(), null);
dataTypeDefinition = dictionaryDAO.getDataType(dataTypeQName);
assertEquals(dataTypeDefinition.getAnalyserResourceBundleName(), "dataTypeResourceBundle");
assertEquals(dataTypeDefinition.getDefaultAnalyserClassName(), null);
try
{
dataTypeDefinition.resolveAnalyserClassName();
fail();
}
catch(MissingResourceException mre)
{
assertTrue(mre.getMessage().contains("dataTypeResourceBundle"));
}
dictionaryDAO.setDefaultAnalyserResourceBundleName("defaultBundle");
try
{
dataTypeDefinition.resolveAnalyserClassName();
fail();
}
catch(MissingResourceException mre)
{
assertTrue(mre.getMessage().contains("defaultBundle"));
}
dictionaryDAO.setDefaultAnalyserResourceBundleName(null);
dictionaryDAO.removeModel(modeQName);
//
dictionaryDAO.putModel(createModel(dictionaryDAO, false, true, true));
modelDefinition = dictionaryDAO.getModel(modeQName);
assertEquals(modelDefinition.getAnalyserResourceBundleName(), null);
dataTypeDefinition = dictionaryDAO.getDataType(dataTypeQName);
assertEquals(dataTypeDefinition.getAnalyserResourceBundleName(), "dataTypeResourceBundle");
assertEquals(dataTypeDefinition.getDefaultAnalyserClassName(), "java.lang.String");
try
{
dataTypeDefinition.resolveAnalyserClassName();
fail();
}
catch(MissingResourceException mre)
{
assertTrue(mre.getMessage().contains("dataTypeResourceBundle"));
}
dictionaryDAO.setDefaultAnalyserResourceBundleName("defaultBundle");
try
{
dataTypeDefinition.resolveAnalyserClassName();
fail();
}
catch(MissingResourceException mre)
{
assertTrue(mre.getMessage().contains("defaultBundle"));
}
dictionaryDAO.setDefaultAnalyserResourceBundleName(null);
dictionaryDAO.removeModel(modeQName);
dictionaryDAO.putModel(createModel(dictionaryDAO, true, false, false));
modelDefinition = dictionaryDAO.getModel(modeQName);
assertEquals(modelDefinition.getAnalyserResourceBundleName(), "dataTypeModelResourceBundle");
dataTypeDefinition = dictionaryDAO.getDataType(dataTypeQName);
assertEquals(dataTypeDefinition.getAnalyserResourceBundleName(), null);
assertEquals(dataTypeDefinition.getDefaultAnalyserClassName(), null);
try
{
dataTypeDefinition.resolveAnalyserClassName();
fail();
}
catch(MissingResourceException mre)
{
assertTrue(mre.getMessage().contains("dataTypeModelResourceBundle"));
}
dictionaryDAO.setDefaultAnalyserResourceBundleName("defaultBundle");
try
{
dataTypeDefinition.resolveAnalyserClassName();
fail();
}
catch(MissingResourceException mre)
{
assertTrue(mre.getMessage().contains("defaultBundle"));
}
dictionaryDAO.setDefaultAnalyserResourceBundleName(null);
dictionaryDAO.removeModel(modeQName);
//
dictionaryDAO.putModel(createModel(dictionaryDAO, true, false, true));
modelDefinition = dictionaryDAO.getModel(modeQName);
assertEquals(modelDefinition.getAnalyserResourceBundleName(), "dataTypeModelResourceBundle");
dataTypeDefinition = dictionaryDAO.getDataType(dataTypeQName);
assertEquals(dataTypeDefinition.getAnalyserResourceBundleName(), null);
assertEquals(dataTypeDefinition.getDefaultAnalyserClassName(), "java.lang.String");
try
{
dataTypeDefinition.resolveAnalyserClassName();
fail();
}
catch(MissingResourceException mre)
{
assertTrue(mre.getMessage().contains("dataTypeModelResourceBundle"));
}
dictionaryDAO.setDefaultAnalyserResourceBundleName("defaultBundle");
try
{
dataTypeDefinition.resolveAnalyserClassName();
fail();
}
catch(MissingResourceException mre)
{
assertTrue(mre.getMessage().contains("defaultBundle"));
}
dictionaryDAO.setDefaultAnalyserResourceBundleName(null);
dictionaryDAO.removeModel(modeQName);
//
dictionaryDAO.putModel(createModel(dictionaryDAO, true, true, false));
modelDefinition = dictionaryDAO.getModel(modeQName);
assertEquals(modelDefinition.getAnalyserResourceBundleName(), "dataTypeModelResourceBundle");
dataTypeDefinition = dictionaryDAO.getDataType(dataTypeQName);
assertEquals(dataTypeDefinition.getAnalyserResourceBundleName(), "dataTypeResourceBundle");
assertEquals(dataTypeDefinition.getDefaultAnalyserClassName(), null);
try
{
dataTypeDefinition.resolveAnalyserClassName();
fail();
}
catch(MissingResourceException mre)
{
assertTrue(mre.getMessage().contains("dataTypeResourceBundle"));
}
dictionaryDAO.setDefaultAnalyserResourceBundleName("defaultBundle");
try
{
dataTypeDefinition.resolveAnalyserClassName();
fail();
}
catch(MissingResourceException mre)
{
assertTrue(mre.getMessage().contains("defaultBundle"));
}
dictionaryDAO.setDefaultAnalyserResourceBundleName(null);
dictionaryDAO.removeModel(modeQName);
//
dictionaryDAO.putModel(createModel(dictionaryDAO, true, true, true));
modelDefinition = dictionaryDAO.getModel(modeQName);
assertEquals(modelDefinition.getAnalyserResourceBundleName(), "dataTypeModelResourceBundle");
dataTypeDefinition = dictionaryDAO.getDataType(dataTypeQName);
assertEquals(dataTypeDefinition.getAnalyserResourceBundleName(), "dataTypeResourceBundle");
assertEquals(dataTypeDefinition.getDefaultAnalyserClassName(), "java.lang.String");
try
{
dataTypeDefinition.resolveAnalyserClassName();
fail();
}
catch(MissingResourceException mre)
{
assertTrue(mre.getMessage().contains("dataTypeResourceBundle"));
}
dictionaryDAO.setDefaultAnalyserResourceBundleName("defaultBundle");
try
{
dataTypeDefinition.resolveAnalyserClassName();
fail();
}
catch(MissingResourceException mre)
{
assertTrue(mre.getMessage().contains("defaultBundle"));
}
dictionaryDAO.setDefaultAnalyserResourceBundleName(null);
dictionaryDAO.removeModel(modeQName);
}
private M2Model createModel(DictionaryDAO dictionaryDAO, boolean withModelBundle, boolean withDataTypeBundle, boolean withTypeAnalyserClss)
{
String testNamespace = "http://www.alfresco.org/test/analyserResolution";
M2Model model = M2Model.createModel("test:analyzerModel");
model.createNamespace(testNamespace, "test");
if(withModelBundle)
{
model.setAnalyserResourceBundleName("dataTypeModelResourceBundle");
}
M2DataType dataTypeWithAnalyserBundleName = model.createPropertyType("test:analyzerDataType");
dataTypeWithAnalyserBundleName.setJavaClassName("java.lang.String");
if(withTypeAnalyserClss)
{
dataTypeWithAnalyserBundleName.setDefaultAnalyserClassName("java.lang.String");
}
if(withDataTypeBundle)
{
dataTypeWithAnalyserBundleName.setAnalyserResourceBundleName("dataTypeResourceBundle");
}
return model;
}
@Test
public void testTypeAnalyserResolution()
{
// Stuff to configure/
TenantService tenantService = new SingleTServiceImpl();
DictionaryDAOImpl dictionaryDAO = new DictionaryDAOImpl();
dictionaryDAO.setTenantService(tenantService);
initDictionaryCaches(dictionaryDAO, tenantService);
// build data model - typical settings
dictionaryDAO.putModel(createModel(dictionaryDAO, true, false, true));
// check simple stack - all defined keep removing the end
ModelDefinition modelDefinition;
ClassDefinition superDefinition;
ClassDefinition classDefinition;
PropertyDefinition propertyDefinition;
dictionaryDAO.putModel(createTypeModel(dictionaryDAO, true, true, true, true));
QName modelQName = QName.createQName("test2:analyzerClassModel", dictionaryDAO);
QName superQName = QName.createQName("test2:analyzerSuperType", dictionaryDAO);
QName typeQName = QName.createQName("test2:analyzerType", dictionaryDAO);
QName propertyQName = QName.createQName("test2:analyzerProperty", dictionaryDAO);
modelDefinition = dictionaryDAO.getModel(modelQName);
assertEquals(modelDefinition.getAnalyserResourceBundleName(), "typeModelResourceBundle");
superDefinition = dictionaryDAO.getType(superQName);
assertEquals(superDefinition.getAnalyserResourceBundleName(), "superTypeResourceBundle");
classDefinition = dictionaryDAO.getType(typeQName);
assertEquals(classDefinition.getAnalyserResourceBundleName(), "typeResourceBundle");
propertyDefinition = dictionaryDAO.getProperty(propertyQName);
assertEquals(propertyDefinition.getAnalyserResourceBundleName(), "propertyResourceBundle");
try
{
propertyDefinition.resolveAnalyserClassName();
fail();
}
catch(MissingResourceException mre)
{
assertTrue(mre.getMessage().contains("propertyResourceBundle"));
}
dictionaryDAO.setDefaultAnalyserResourceBundleName("defaultBundle");
try
{
propertyDefinition.resolveAnalyserClassName();
fail();
}
catch(MissingResourceException mre)
{
assertTrue(mre.getMessage().contains("propertyResourceBundle"));
}
dictionaryDAO.setDefaultAnalyserResourceBundleName(null);
dictionaryDAO.removeModel(modelQName);
//
dictionaryDAO.putModel(createTypeModel(dictionaryDAO, true, true, true, false));
modelDefinition = dictionaryDAO.getModel(modelQName);
assertEquals(modelDefinition.getAnalyserResourceBundleName(), "typeModelResourceBundle");
superDefinition = dictionaryDAO.getType(superQName);
assertEquals(superDefinition.getAnalyserResourceBundleName(), "superTypeResourceBundle");
classDefinition = dictionaryDAO.getType(typeQName);
assertEquals(classDefinition.getAnalyserResourceBundleName(), "typeResourceBundle");
propertyDefinition = dictionaryDAO.getProperty(propertyQName);
assertEquals(propertyDefinition.getAnalyserResourceBundleName(), null);
try
{
propertyDefinition.resolveAnalyserClassName();
fail();
}
catch(MissingResourceException mre)
{
assertTrue(mre.getMessage().contains("typeResourceBundle"));
}
dictionaryDAO.setDefaultAnalyserResourceBundleName("defaultBundle");
try
{
propertyDefinition.resolveAnalyserClassName();
fail();
}
catch(MissingResourceException mre)
{
assertTrue(mre.getMessage().contains("typeResourceBundle"));
}
dictionaryDAO.setDefaultAnalyserResourceBundleName(null);
dictionaryDAO.removeModel(modelQName);
//
dictionaryDAO.putModel(createTypeModel(dictionaryDAO, true, true, false, false));
modelDefinition = dictionaryDAO.getModel(modelQName);
assertEquals(modelDefinition.getAnalyserResourceBundleName(), "typeModelResourceBundle");
superDefinition = dictionaryDAO.getType(superQName);
assertEquals(superDefinition.getAnalyserResourceBundleName(), "superTypeResourceBundle");
classDefinition = dictionaryDAO.getType(typeQName);
assertEquals(classDefinition.getAnalyserResourceBundleName(), null);
propertyDefinition = dictionaryDAO.getProperty(propertyQName);
assertEquals(propertyDefinition.getAnalyserResourceBundleName(), null);
try
{
propertyDefinition.resolveAnalyserClassName();
fail();
}
catch(MissingResourceException mre)
{
assertTrue(mre.getMessage().contains("superTypeResourceBundle"));
}
dictionaryDAO.setDefaultAnalyserResourceBundleName("defaultBundle");
try
{
propertyDefinition.resolveAnalyserClassName();
fail();
}
catch(MissingResourceException mre)
{
assertTrue(mre.getMessage().contains("superTypeResourceBundle"));
}
dictionaryDAO.setDefaultAnalyserResourceBundleName(null);
dictionaryDAO.removeModel(modelQName);
//
dictionaryDAO.putModel(createTypeModel(dictionaryDAO, true, false, false, false));
modelDefinition = dictionaryDAO.getModel(modelQName);
assertEquals(modelDefinition.getAnalyserResourceBundleName(), "typeModelResourceBundle");
superDefinition = dictionaryDAO.getType(superQName);
assertEquals(superDefinition.getAnalyserResourceBundleName(), null);
classDefinition = dictionaryDAO.getType(typeQName);
assertEquals(classDefinition.getAnalyserResourceBundleName(), null);
propertyDefinition = dictionaryDAO.getProperty(propertyQName);
assertEquals(propertyDefinition.getAnalyserResourceBundleName(), null);
try
{
propertyDefinition.resolveAnalyserClassName();
fail();
}
catch(MissingResourceException mre)
{
assertTrue(mre.getMessage().contains("typeModelResourceBundle"));
}
dictionaryDAO.setDefaultAnalyserResourceBundleName("defaultBundle");
try
{
propertyDefinition.resolveAnalyserClassName();
fail();
}
catch(MissingResourceException mre)
{
assertTrue(mre.getMessage().contains("typeModelResourceBundle"));
}
dictionaryDAO.setDefaultAnalyserResourceBundleName(null);
dictionaryDAO.removeModel(modelQName);
//
dictionaryDAO.putModel(createTypeModel(dictionaryDAO, false, false, false, false));
modelDefinition = dictionaryDAO.getModel(modelQName);
assertEquals(modelDefinition.getAnalyserResourceBundleName(), null);
superDefinition = dictionaryDAO.getType(superQName);
assertEquals(superDefinition.getAnalyserResourceBundleName(), null);
classDefinition = dictionaryDAO.getType(typeQName);
assertEquals(classDefinition.getAnalyserResourceBundleName(), null);
propertyDefinition = dictionaryDAO.getProperty(propertyQName);
assertEquals(propertyDefinition.getAnalyserResourceBundleName(), null);
try
{
propertyDefinition.resolveAnalyserClassName();
fail();
}
catch(MissingResourceException mre)
{
assertTrue(mre.getMessage().contains("dataTypeModelResourceBundle"));
}
dictionaryDAO.setDefaultAnalyserResourceBundleName("defaultBundle");
try
{
propertyDefinition.resolveAnalyserClassName();
fail();
}
catch(MissingResourceException mre)
{
assertTrue(mre.getMessage().contains("defaultBundle"));
}
dictionaryDAO.setDefaultAnalyserResourceBundleName(null);
dictionaryDAO.removeModel(modelQName);
}
/**
* @param dictionaryDAO DictionaryDAOImpl
* @param withModelBundle boolean
* @param withInheritedTypeBundle boolean
* @param withTypeBundle boolean
* @param withPropertyBundle boolean
* @return M2Model
*/
private M2Model createTypeModel(DictionaryDAOImpl dictionaryDAO, boolean withModelBundle, boolean withInheritedTypeBundle, boolean withTypeBundle, boolean withPropertyBundle)
{
String testNamespace = "http://www.alfresco.org/test/analyserResolutionType";
M2Model model = M2Model.createModel("test2:analyzerClassModel");
model.createNamespace(testNamespace, "test2");
model.createImport("http://www.alfresco.org/test/analyserResolution", "test");
if(withModelBundle)
{
model.setAnalyserResourceBundleName("typeModelResourceBundle");
}
M2Type superTypeWithAnalyserBundleName = model.createType("test2:analyzerSuperType");
if(withInheritedTypeBundle)
{
superTypeWithAnalyserBundleName.setAnalyserResourceBundleName("superTypeResourceBundle");
}
M2Type typeWithAnalyserBundleName = model.createType("test2:analyzerType");
typeWithAnalyserBundleName.setParentName("test2:analyzerSuperType");
if(withTypeBundle)
{
typeWithAnalyserBundleName.setAnalyserResourceBundleName("typeResourceBundle");
}
M2Property propertyWithAnalyserBundelName = typeWithAnalyserBundleName.createProperty("test2:analyzerProperty");
propertyWithAnalyserBundelName.setType("test:analyzerDataType");
if(withPropertyBundle)
{
propertyWithAnalyserBundelName.setAnalyserResourceBundleName("propertyResourceBundle");
}
return model;
}
//testing a model containing circular dependency cannot be imported with bootstrap
@Test
@@ -1147,7 +664,6 @@ public class DictionaryDAOTest
String testNamespace = "http://www.alfresco.org/model/dictionary/1.0/my";
M2Model model = M2Model.createModel("my:circularModel");
model.createNamespace(testNamespace, "my");
model.setAnalyserResourceBundleName("typeModelResourceBundle");
M2Type typeA = model.createType("my:circularA");
typeA.setParentName("my:circularC");
M2Type typeB = model.createType("my:circularB");

View File

@@ -0,0 +1,436 @@
<model name="cmis:cmismodel" xmlns="http://www.alfresco.org/model/dictionary/1.0">
<description>CMIS Model Definitions</description>
<version>1.0</version>
<imports>
<import uri="http://www.alfresco.org/model/dictionary/1.0" prefix="d" />
</imports>
<namespaces>
<namespace uri="http://www.alfresco.org/model/cmis/1.0/cs01" prefix="cmis" />
<namespace uri="http://www.alfresco.org/model/cmis/1.0/cs01ext" prefix="cmisext" />
<namespace uri="http://www.alfresco.org/model/cmis/1.0/alfcmis" prefix="alfcmis" />
</namespaces>
<data-types>
<data-type name="cmis:id">
<java-class>java.lang.String</java-class>
</data-type>
<data-type name="cmis:uri">
<java-class>java.lang.String</java-class>
</data-type>
<data-type name="cmis:html">
<java-class>java.lang.String</java-class>
</data-type>
</data-types>
<constraints>
<constraint name="cmis:allowedValuesForContentStreamAllowed" type="LIST">
<parameter name="allowedValues">
<list>
<value>notallowed</value>
<value>allowed</value>
<value>required</value>
</list>
</parameter>
</constraint>
</constraints>
<types>
<type name="cmisext:object">
<properties>
<property name="cmis:objectId">
<title>Object Id</title>
<description>The unique object id (a node ref)</description>
<type>cmis:id</type>
<protected>true</protected>
<mandatory>false</mandatory>
<multiple>false</multiple>
<index enabled="true">
<tokenised>false</tokenised>
</index>
</property>
<property name="cmis:objectTypeId">
<title>Object Type Id</title>
<description>Id of the objects type</description>
<type>cmis:id</type>
<protected>true</protected>
<mandatory>true</mandatory>
<multiple>false</multiple>
<index enabled="true">
<tokenised>false</tokenised>
</index>
</property>
<property name="cmis:baseTypeId">
<title>Base Type Id</title>
<description>Id of the base object type for the object</description>
<type>cmis:id</type>
<protected>true</protected>
<mandatory>false</mandatory>
<multiple>false</multiple>
<index enabled="true">
<tokenised>true</tokenised>
</index>
</property>
<property name="cmis:name">
<title>Name</title>
<description>Name</description>
<type>d:text</type>
<protected>false</protected>
<mandatory>true</mandatory>
<multiple>false</multiple>
<index enabled="true">
<tokenised>both</tokenised>
</index>
</property>
<property name="cmis:createdBy">
<title>Created by</title>
<description>The authority who created this object</description>
<type>d:text</type>
<protected>true</protected>
<mandatory>false</mandatory>
<multiple>false</multiple>
<index enabled="true">
<tokenised>false</tokenised>
</index>
</property>
<property name="cmis:creationDate">
<title>Creation Date</title>
<description>The object creation date</description>
<type>d:datetime</type>
<protected>true</protected>
<mandatory>false</mandatory>
<multiple>false</multiple>
<index enabled="true">
<tokenised>false</tokenised>
</index>
</property>
<property name="cmis:lastModifiedBy">
<title>Last Modified By</title>
<description>The authority who last modified this object</description>
<type>d:text</type>
<protected>true</protected>
<mandatory>false</mandatory>
<multiple>false</multiple>
<index enabled="true">
<tokenised>false</tokenised>
</index>
</property>
<property name="cmis:lastModificationDate">
<title>Last Modified Date</title>
<description>The date this object was last modified</description>
<type>d:datetime</type>
<protected>true</protected>
<mandatory>false</mandatory>
<multiple>false</multiple>
<index enabled="true">
<tokenised>false</tokenised>
</index>
</property>
<property name="cmis:changeToken">
<title>Change token</title>
<description>Change Token</description>
<type>d:text</type>
<protected>true</protected>
<mandatory>false</mandatory>
<multiple>false</multiple>
<index enabled="false" />
</property>
<property name="alfcmis:nodeRef">
<title>Alfresco Node Ref</title>
<description>Alfresco Node Ref</description>
<type>cmis:id</type>
<protected>true</protected>
<mandatory>false</mandatory>
<multiple>false</multiple>
<index enabled="false" />
</property>
<!-- V1.1 -->
<property name="cmis:description">
<title>Description</title>
<description>Description</description>
<type>d:text</type>
<protected>false</protected>
<mandatory>false</mandatory>
<multiple>false</multiple>
<index enabled="true">
<tokenised>true</tokenised>
</index>
</property>
<property name="cmis:secondaryObjectTypeIds">
<title>Secondary Object Type Ids</title>
<description>Ids of the secondary object types for the object</description>
<type>cmis:id</type>
<protected>false</protected>
<mandatory>false</mandatory>
<multiple>true</multiple>
<index enabled="true">
<tokenised>true</tokenised>
</index>
</property>
</properties>
</type>
<type name="cmis:document">
<title>Document</title>
<description>Document Type</description>
<parent>cmisext:object</parent>
<properties>
<property name="cmis:isImmutable">
<title>Is Immutable</title>
<description>Is the document immutable?</description>
<type>d:boolean</type>
<protected>true</protected>
<mandatory>false</mandatory>
<multiple>false</multiple>
<index enabled="false" />
</property>
<property name="cmis:isLatestVersion">
<title>Is Latest Version</title>
<description>Is this the latest version of the document?</description>
<type>d:boolean</type>
<protected>true</protected>
<mandatory>false</mandatory>
<multiple>false</multiple>
<index enabled="false" />
</property>
<property name="cmis:isMajorVersion">
<title>Is Major Version</title>
<description>Is this a major version of the document?</description>
<type>d:boolean</type>
<protected>true</protected>
<mandatory>false</mandatory>
<multiple>false</multiple>
<index enabled="false" />
</property>
<property name="cmis:isLatestMajorVersion">
<title>Is Latest Major Version</title>
<description>Is this the latest major version of the document?</description>
<type>d:boolean</type>
<protected>true</protected>
<mandatory>false</mandatory>
<multiple>false</multiple>
<index enabled="false" />
</property>
<property name="cmis:versionLabel">
<title>Version Label</title>
<description>The version label</description>
<type>d:text</type>
<protected>true</protected>
<mandatory>false</mandatory>
<multiple>false</multiple>
<index enabled="false"/>
</property>
<property name="cmis:versionSeriesId">
<title>Version series id</title>
<description>The version series id</description>
<type>cmis:id</type>
<protected>true</protected>
<mandatory>false</mandatory>
<multiple>false</multiple>
<index enabled="false"/>
</property>
<property name="cmis:isVersionSeriesCheckedOut">
<title>Is Version Series Checked Out</title>
<description>Is the version series checked out?</description>
<type>d:boolean</type>
<protected>true</protected>
<mandatory>false</mandatory>
<multiple>false</multiple>
<index enabled="false" />
</property>
<property name="cmis:versionSeriesCheckedOutBy">
<title>Version Series Checked Out By</title>
<description>The authority who checked out this document version series</description>
<type>d:text</type>
<protected>true</protected>
<mandatory>false</mandatory>
<multiple>false</multiple>
<index enabled="false" />
</property>
<property name="cmis:versionSeriesCheckedOutId">
<title>Version Series Checked Out Id</title>
<description>The checked out version series id</description>
<type>cmis:id</type>
<protected>true</protected>
<mandatory>false</mandatory>
<multiple>false</multiple>
<index enabled="false" />
</property>
<property name="cmis:checkinComment">
<title>Checkin Comment</title>
<description>The checkin comment</description>
<type>d:text</type>
<protected>true</protected>
<mandatory>false</mandatory>
<multiple>false</multiple>
<index enabled="false" />
</property>
<property name="cmis:contentStreamLength">
<title>Content Stream Length</title>
<description>The length of the content stream</description>
<type>d:long</type>
<protected>true</protected>
<mandatory>false</mandatory>
<multiple>false</multiple>
<index enabled="true">
<tokenised>false</tokenised>
</index>
</property>
<property name="cmis:contentStreamMimeType">
<title>Content Stream MIME Type</title>
<description>The content stream MIME type</description>
<type>d:text</type>
<protected>true</protected>
<mandatory>false</mandatory>
<multiple>false</multiple>
<index enabled="true">
<tokenised>false</tokenised>
</index>
</property>
<property name="cmis:contentStreamFileName">
<title>Content Stream Filename</title>
<description>The content stream filename</description>
<type>d:text</type>
<protected>true</protected>
<mandatory>false</mandatory>
<multiple>false</multiple>
<index enabled="true">
<tokenised>true</tokenised>
</index>
</property>
<property name="cmis:contentStreamId">
<title>Content Stream Id</title>
<description>Id of the stream</description>
<type>cmis:id</type>
<protected>true</protected>
<mandatory>false</mandatory>
<multiple>false</multiple>
<index enabled="false" />
</property>
<!-- V1.1 -->
<property name="cmis:isPrivateWorkingCopy">
<title>Is private working copy</title>
<description>Indicates if this instance is a private working copy</description>
<type>d:boolean</type>
<protected>true</protected>
<mandatory>false</mandatory>
<multiple>false</multiple>
<index enabled="false" />
</property>
</properties>
</type>
<type name="cmis:folder">
<title>Folder</title>
<description>Folder Type</description>
<parent>cmisext:object</parent>
<properties>
<property name="cmis:parentId">
<title>Parent Id</title>
<description>The parent id of the folder</description>
<type>cmis:id</type>
<protected>true</protected>
<mandatory>false</mandatory>
<multiple>false</multiple>
<index enabled="true">
<tokenised>false</tokenised>
</index>
</property>
<property name="cmis:path">
<title>Path</title>
<description>The fully qualified path to this folder/description</description>
<type>d:text</type>
<protected>true</protected>
<mandatory>false</mandatory>
<multiple>false</multiple>
<index enabled="false"/>
</property>
<property name="cmis:allowedChildObjectTypeIds">
<title>Allowed Child Object Types Ids</title>
<description>The allowed child object type ids</description>
<type>cmis:id</type>
<protected>true</protected>
<mandatory>false</mandatory>
<multiple>true</multiple>
<index enabled="false" />
</property>
</properties>
</type>
<type name="cmis:relationship">
<title>Relationship</title>
<description>Relationship Type</description>
<parent>cmisext:object</parent>
<properties>
<property name="cmis:sourceId">
<title>Source Id</title>
<description>The source id for the relationship</description>
<type>cmis:id</type>
<protected>true</protected>
<mandatory enforced="true">true</mandatory>
<multiple>false</multiple>
<index enabled="false" />
</property>
<property name="cmis:targetId">
<title>Target Id</title>
<description>The target id for the relationship</description>
<type>cmis:id</type>
<protected>true</protected>
<mandatory enforced="true">true</mandatory>
<multiple>false</multiple>
<index enabled="false" />
</property>
</properties>
</type>
<type name="cmis:policy">
<title>Policy</title>
<description>Policy Type</description>
<parent>cmisext:object</parent>
<properties>
<property name="cmis:policyText">
<title>Policy Text</title>
<description>The policy text</description>
<type>d:text</type>
<protected>true</protected>
<mandatory enforced="true">true</mandatory>
<multiple>false</multiple>
<index enabled="false" />
</property>
</properties>
</type>
<type name="cmis:secondary">
<title>Secondary Type</title>
<description>Secondary Type</description>
<parent>cmisext:object</parent>
<properties>
</properties>
</type>
<type name="cmis:item">
<title>Item Type</title>
<description>CMIS Item</description>
<parent>cmisext:object</parent>
<properties>
</properties>
</type>
<type name="cmisext:aspects">
<title>Aspects</title>
<description>Aspects Type</description>
<parent>cmis:policy</parent>
</type>
</types>
</model>

View File

@@ -0,0 +1,111 @@
<model name="d:dictionary" xmlns="http://www.alfresco.org/model/dictionary/1.0">
<description>Alfresco Dictionary Model</description>
<author>Alfresco</author>
<published>2005-09-29</published>
<version>1.0</version>
<analyserResourceBundleName>alfresco/model/dataTypeAnalyzers</analyserResourceBundleName>
<namespaces>
<!-- Default Namespace -->
<namespace uri="" prefix=""/>
<!-- Default Alfresco Namespace -->
<namespace uri="http://www.alfresco.org" prefix="alf"/>
<!-- Dictionary Namespace -->
<namespace uri="http://www.alfresco.org/model/dictionary/1.0" prefix="d"/>
<!-- View Namespace -->
<namespace uri="http://www.alfresco.org/view/repository/1.0" prefix="view"/>
</namespaces>
<data-types>
<data-type name="d:any">
<java-class>java.lang.Object</java-class>
</data-type>
<data-type name="d:encrypted">
<java-class>javax.crypto.SealedObject</java-class>
</data-type>
<data-type name="d:text">
<java-class>java.lang.String</java-class>
</data-type>
<data-type name="d:mltext">
<java-class>org.alfresco.service.cmr.repository.MLText</java-class>
</data-type>
<data-type name="d:content">
<java-class>org.alfresco.service.cmr.repository.ContentData</java-class>
</data-type>
<data-type name="d:int">
<java-class>java.lang.Integer</java-class>
</data-type>
<data-type name="d:long">
<java-class>java.lang.Long</java-class>
</data-type>
<data-type name="d:float">
<java-class>java.lang.Float</java-class>
</data-type>
<data-type name="d:double">
<java-class>java.lang.Double</java-class>
</data-type>
<data-type name="d:date">
<java-class>java.util.Date</java-class>
</data-type>
<data-type name="d:datetime">
<java-class>java.util.Date</java-class>
</data-type>
<data-type name="d:boolean">
<java-class>java.lang.Boolean</java-class>
</data-type>
<data-type name="d:qname">
<java-class>org.alfresco.service.namespace.QName</java-class>
</data-type>
<data-type name="d:noderef">
<java-class>org.alfresco.service.cmr.repository.NodeRef</java-class>
</data-type>
<data-type name="d:childassocref">
<java-class>org.alfresco.service.cmr.repository.ChildAssociationRef</java-class>
</data-type>
<data-type name="d:assocref">
<java-class>org.alfresco.service.cmr.repository.AssociationRef</java-class>
</data-type>
<data-type name="d:path">
<java-class>org.alfresco.service.cmr.repository.Path</java-class>
</data-type>
<data-type name="d:category">
<java-class>org.alfresco.service.cmr.repository.NodeRef</java-class>
</data-type>
<data-type name="d:locale">
<java-class>java.util.Locale</java-class>
</data-type>
<data-type name="d:version">
<java-class>org.alfresco.util.VersionNumber</java-class>
</data-type>
<data-type name="d:period">
<java-class>org.alfresco.service.cmr.repository.Period</java-class>
</data-type>
</data-types>
<!-- TODO: Define dictionary meta model -->
</model>

View File

@@ -9,8 +9,6 @@ test_dictionarydaotest.property.test_prop1.description=Prop1 Description
test_dictionarydaotest.association.test_assoc1.title=Assoc1 Title
test_dictionarydaotest.association.test_assoc1.description=Assoc1 Description
test_dictionarydaotest.datatype.test_datatype.analyzer=Datatype Analyser
listconstraint.test_list1.ABC=ABC display
listconstraint.test_list1.DEF=DEF display
listconstraint.test_list1.VALUE\ WITH\ SPACES=VALUE WITH SPACES display

View File

@@ -4,11 +4,11 @@
<author>Alfresco</author>
<published>2005-05-30</published>
<version>1.0</version>
<imports>
<import uri="http://www.alfresco.org/model/dictionary/1.0" prefix="d"/>
</imports>
<namespaces>
<namespace uri="http://www.alfresco.org/test/dictionarydaotest/1.0" prefix="test"/>
<namespace uri="http://www.alfresco.org/test/dictionarydaotest2/1.0" prefix="test2"/>
@@ -18,12 +18,12 @@
<data-type name="test:datatype">
<default-analyser-class>org.alfresco.repo.search.impl.lucene.analysis.AlfrescoStandardAnalyser</default-analyser-class>
<analyserResourceBundleName>alfresco/model/dataTypeAnalyzers</analyserResourceBundleName>
<analyserResourceBundleName>alfresco/model/dataTypeAnalyzers</analyserResourceBundleName>
<java-class>java.lang.Object</java-class>
</data-type>
</data-types>
<constraints>
<constraint name="test:registered1" type="REGISTERED">
<parameter name="registeredName"><value>cm:reg1</value></parameter>
@@ -57,40 +57,40 @@
<title>List1 title</title>
<description>List1 description</description>
<parameter name="allowedValues">
<list>
<value>ABC</value>
<value>DEF</value>
<value>VALUE WITH SPACES</value>
<value>VALUE WITH TRAILING SPACE </value>
</list>
<list>
<value>ABC</value>
<value>DEF</value>
<value>VALUE WITH SPACES</value>
<value>VALUE WITH TRAILING SPACE </value>
</list>
</parameter>
<parameter name="caseSensitive"><value>true</value></parameter>
</constraint>
<constraint name="test:list2" type="LIST">
<parameter name="allowedValues">
<list>
<value>HIJ</value>
</list>
<list>
<value>HIJ</value>
</list>
</parameter>
<parameter name="caseSensitive"><value>true</value></parameter>
</constraint>
<constraint name="test2:list3" type="LIST">
<parameter name="allowedValues">
<list>
<value>XYZ</value>
</list>
<list>
<value>XYZ</value>
</list>
</parameter>
<parameter name="caseSensitive"><value>true</value></parameter>
</constraint>
</constraints>
<types>
<type name="test:base">
<title>Base</title>
<description>The Base Type</description>
<parent></parent>
<properties>
<property name="test:prop1">
<type>d:text</type>
@@ -99,14 +99,14 @@
<constraints>
<constraint ref="test:regex1"/>
<constraint ref="test:stringLength1">
<title>Prop1 Strlen1 title</title>
<description>Prop1 Strlen1 description</description>
<title>Prop1 Strlen1 title</title>
<description>Prop1 Strlen1 description</description>
</constraint>
<constraint ref="test:registered1"/>
</constraints>
</property>
</properties>
<associations>
<association name="test:assoc1">
<source>
@@ -158,16 +158,16 @@
<propagateTimestamps>true</propagateTimestamps>
</child-association>
</associations>
<mandatory-aspects>
<aspect>test:referenceable</aspect>
</mandatory-aspects>
</type>
<type name="test:file">
<parent>test:base</parent>
<archive>true</archive>
<properties>
<property name="test:fileprop">
<type>d:text</type>
@@ -202,12 +202,12 @@
<type name="test:file-derived">
<parent>test:file</parent>
</type>
<type name="test:file-derived-no-archive">
<parent>test:file</parent>
<archive>false</archive>
</type>
<type name="test:folder">
<parent>test:base</parent>
<properties>
@@ -218,7 +218,7 @@
</property>
</properties>
</type>
<type name="test:enforced">
<parent>test:base</parent>
<properties>
@@ -236,39 +236,39 @@
</property>
</properties>
</type>
<type name="test:overridetype1">
<properties>
<properties>
<property name="test:propoverride">
<type>d:text</type>
<default>one</default>
<type>d:text</type>
<default>one</default>
</property>
</properties>
</properties>
</type>
<type name="test:overridetype2">
<parent>test:overridetype1</parent>
<overrides>
<parent>test:overridetype1</parent>
<overrides>
<property name="test:propoverride">
<default>two</default>
<default>two</default>
</property>
</overrides>
</overrides>
</type>
<type name="test:overridetype3">
<parent>test:overridetype2</parent>
<overrides>
<parent>test:overridetype2</parent>
<overrides>
<property name="test:propoverride">
<default>three</default>
<default>three</default>
</property>
</overrides>
</overrides>
</type>
<type name="test:typeWithNamedPropConstraint">
<title>Type with named property-defined constraint.</title>
<description>A type with a named constraint defined within one of its properties.</description>
<parent></parent>
<properties>
<property name="test:constrainedProp">
<type>d:text</type>
@@ -278,28 +278,28 @@
<constraint name="test:inlineConstraint" type="LIST">
<title>Inline constraint</title>
<description>An inline constraint</description>
<parameter name="allowedValues">
<list>
<value>ALPHA</value>
<value>BETA</value>
<value>GAMMA, DELTA</value>
<value>OMEGA</value>
</list>
</parameter>
<parameter name="caseSensitive"><value>true</value></parameter>
<parameter name="allowedValues">
<list>
<value>ALPHA</value>
<value>BETA</value>
<value>GAMMA, DELTA</value>
<value>OMEGA</value>
</list>
</parameter>
<parameter name="caseSensitive"><value>true</value></parameter>
</constraint>
</constraints>
</property>
</properties>
</type>
</types>
<aspects>
<aspect name="test:referenceable">
<title>Referenceable</title>
<description>The referenceable aspect</description>
<parent></parent>
<properties>
<property name="test:id">
<type>d:int</type>
@@ -362,5 +362,5 @@
</overrides>
</aspect>
</aspects>
</model>

View File

@@ -9,8 +9,6 @@ test_dictionarydaotest.property.test_prop1.description=Prop1 Description
test_dictionarydaotest.association.test_assoc1.title=Assoc1 Title
test_dictionarydaotest.association.test_assoc1.description=Assoc1 Description
test_dictionarydaotest.datatype.test_datatype.analyzer=Datatype Analyser
listconstraint.test_list1.ABC=ABC display
listconstraint.test_list1.DEF=DEF display
listconstraint.test_list1.VALUE\ WITH\ SPACES=VALUE WITH SPACES display

View File

@@ -0,0 +1,364 @@
<model name="test:dictionarydaotest" xmlns="http://www.alfresco.org/model/dictionary/1.0">
<description>Alfresco Content Model</description>
<author>Alfresco</author>
<published>2005-05-30</published>
<version>1.0</version>
<imports>
<import uri="http://www.alfresco.org/model/dictionary/1.0" prefix="d"/>
</imports>
<namespaces>
<namespace uri="http://www.alfresco.org/test/dictionarydaotest/1.0" prefix="test"/>
<namespace uri="http://www.alfresco.org/test/dictionarydaotest2/1.0" prefix="test2"/>
</namespaces>
<data-types>
<data-type name="test:datatype">
<java-class>java.lang.Object</java-class>
</data-type>
</data-types>
<constraints>
<constraint name="test:registered1" type="REGISTERED">
<parameter name="registeredName"><value>cm:reg1</value></parameter>
</constraint>
<constraint name="test:registered2" type="REGISTERED">
<parameter name="registeredName"><value>cm:reg2</value></parameter>
</constraint>
<constraint name="test:regex1" type="REGEX">
<title>Regex1 title</title>
<description>Regex1 description</description>
<parameter name="expression"><value>[A-Z]*</value></parameter>
<parameter name="requiresMatch"><value>false</value></parameter>
</constraint>
<constraint name="test:regex2" type="REGEX">
<parameter name="expression"><value>[a-z]*</value></parameter>
<parameter name="requiresMatch"><value>false</value></parameter>
</constraint>
<constraint name="test:stringLength1" type="LENGTH">
<parameter name="minLength"><value>0</value></parameter>
<parameter name="maxLength"><value>256</value></parameter>
</constraint>
<constraint name="test:stringLength2" type="LENGTH">
<parameter name="minLength"><value>0</value></parameter>
<parameter name="maxLength"><value>128</value></parameter>
</constraint>
<constraint name="test:minMax1" type="MINMAX">
<parameter name="minValue"><value>0</value></parameter>
<parameter name="maxValue"><value>256</value></parameter>
</constraint>
<constraint name="test:list1" type="LIST">
<title>List1 title</title>
<description>List1 description</description>
<parameter name="allowedValues">
<list>
<value>ABC</value>
<value>DEF</value>
<value>VALUE WITH SPACES</value>
<value>VALUE WITH TRAILING SPACE </value>
</list>
</parameter>
<parameter name="caseSensitive"><value>true</value></parameter>
</constraint>
<constraint name="test:list2" type="LIST">
<parameter name="allowedValues">
<list>
<value>HIJ</value>
</list>
</parameter>
<parameter name="caseSensitive"><value>true</value></parameter>
</constraint>
<constraint name="test2:list3" type="LIST">
<parameter name="allowedValues">
<list>
<value>XYZ</value>
</list>
</parameter>
<parameter name="caseSensitive"><value>true</value></parameter>
</constraint>
</constraints>
<types>
<type name="test:base">
<title>Base</title>
<description>The Base Type</description>
<parent></parent>
<properties>
<property name="test:prop1">
<type>d:text</type>
<protected>true</protected>
<default></default>
<constraints>
<constraint ref="test:regex1"/>
<constraint ref="test:stringLength1">
<title>Prop1 Strlen1 title</title>
<description>Prop1 Strlen1 description</description>
</constraint>
<constraint ref="test:registered1"/>
</constraints>
</property>
</properties>
<associations>
<association name="test:assoc1">
<source>
<mandatory>true</mandatory>
<many>false</many>
</source>
<target>
<class>test:base</class>
<mandatory>false</mandatory>
<many>true</many>
</target>
</association>
<association name="test:assoc2">
<source>
<mandatory>true</mandatory>
<many>true</many>
</source>
<target>
<class>test:referenceable</class>
<mandatory>false</mandatory>
<many>false</many>
</target>
</association>
<child-association name="test:childassoc1">
<source>
<mandatory>true</mandatory>
<many>true</many>
</source>
<target>
<class>test:referenceable</class>
<mandatory>false</mandatory>
<many>false</many>
</target>
<child-name>fred</child-name>
<duplicate>true</duplicate>
</child-association>
<child-association name="test:childassocPropagate">
<source>
<mandatory>true</mandatory>
<many>true</many>
</source>
<target>
<class>test:referenceable</class>
<mandatory>false</mandatory>
<many>false</many>
</target>
<child-name>fred</child-name>
<duplicate>true</duplicate>
<propagateTimestamps>true</propagateTimestamps>
</child-association>
</associations>
<mandatory-aspects>
<aspect>test:referenceable</aspect>
</mandatory-aspects>
</type>
<type name="test:file">
<parent>test:base</parent>
<archive>true</archive>
<properties>
<property name="test:fileprop">
<type>d:text</type>
<protected>true</protected>
<default></default>
</property>
</properties>
<associations>
<child-association name="test:childassoc2">
<target>
<class>test:referenceable</class>
</target>
<child-name>fred</child-name>
<duplicate>true</duplicate>
</child-association>
</associations>
<overrides>
<property name="test:prop1">
<default>an overriden default value</default>
<constraints>
<constraint ref="test:stringLength2"/>
<constraint ref="test:regex2"/>
<constraint ref="test:registered2"/>
</constraints>
</property>
</overrides>
</type>
<type name="test:file-derived">
<parent>test:file</parent>
</type>
<type name="test:file-derived-no-archive">
<parent>test:file</parent>
<archive>false</archive>
</type>
<type name="test:folder">
<parent>test:base</parent>
<properties>
<property name="test:folderprop">
<type>d:text</type>
<protected>true</protected>
<default></default>
</property>
</properties>
</type>
<type name="test:enforced">
<parent>test:base</parent>
<properties>
<property name="test:mandatory-enforced">
<type>d:text</type>
<mandatory enforced="true">true</mandatory>
</property>
<property name="test:mandatory-not-enforced">
<type>d:text</type>
<mandatory enforced="false">true</mandatory>
</property>
<property name="test:mandatory-default-enforced">
<type>d:text</type>
<mandatory>true</mandatory>
</property>
</properties>
</type>
<type name="test:overridetype1">
<properties>
<property name="test:propoverride">
<type>d:text</type>
<default>one</default>
</property>
</properties>
</type>
<type name="test:overridetype2">
<parent>test:overridetype1</parent>
<overrides>
<property name="test:propoverride">
<default>two</default>
</property>
</overrides>
</type>
<type name="test:overridetype3">
<parent>test:overridetype2</parent>
<overrides>
<property name="test:propoverride">
<default>three</default>
</property>
</overrides>
</type>
<type name="test:typeWithNamedPropConstraint">
<title>Type with named property-defined constraint.</title>
<description>A type with a named constraint defined within one of its properties.</description>
<parent></parent>
<properties>
<property name="test:constrainedProp">
<type>d:text</type>
<protected>true</protected>
<default></default>
<constraints>
<constraint name="test:inlineConstraint" type="LIST">
<title>Inline constraint</title>
<description>An inline constraint</description>
<parameter name="allowedValues">
<list>
<value>ALPHA</value>
<value>BETA</value>
<value>GAMMA, DELTA</value>
<value>OMEGA</value>
</list>
</parameter>
<parameter name="caseSensitive"><value>true</value></parameter>
</constraint>
</constraints>
</property>
</properties>
</type>
</types>
<aspects>
<aspect name="test:referenceable">
<title>Referenceable</title>
<description>The referenceable aspect</description>
<parent></parent>
<properties>
<property name="test:id">
<type>d:int</type>
<protected>true</protected>
<mandatory>true</mandatory>
<index enabled="true">
<atomic>true</atomic>
<stored>false</stored>
</index>
<constraints>
<constraint ref="test:minMax1"/>
</constraints>
</property>
</properties>
</aspect>
<aspect name="test:aspect-base">
<title>Aspect Base</title>
<parent></parent>
<properties>
<property name="test:aspect-base-p1">
<type>d:text</type>
<constraints>
<constraint ref="test:list1"/>
</constraints>
</property>
</properties>
</aspect>
<aspect name="test:aspect-one">
<title>Aspect One</title>
<parent>test:aspect-base</parent>
<overrides>
<property name="test:aspect-base-p1">
<constraints>
<constraint ref="test:list2"/>
</constraints>
</property>
</overrides>
</aspect>
<aspect name="test:aspect-two">
<title>Aspect Two</title>
<parent>test:aspect-base</parent>
<overrides>
<property name="test:aspect-base-p1">
<constraints>
<constraint ref="test:list1"/>
<constraint ref="test:list2"/>
</constraints>
</property>
</overrides>
</aspect>
<aspect name="test2:aspect-three">
<title>Aspect derived from other namespace</title>
<parent>test:aspect-base</parent>
<overrides>
<property name="test:aspect-base-p1">
<constraints>
<constraint ref="test2:list3"/>
</constraints>
</property>
</overrides>
</aspect>
</aspects>
</model>

View File

@@ -52,7 +52,6 @@
<dependency.activiti-engine.version>5.23.0</dependency.activiti-engine.version>
<dependency.activiti.version>5.23.0</dependency.activiti.version>
<dependency.transform.model.version>1.0.2.11</dependency.transform.model.version>
<dependency.alfresco-legacy-lucene.version>6.2</dependency.alfresco-legacy-lucene.version>
<dependency.alfresco-greenmail.version>6.2</dependency.alfresco-greenmail.version>
<dependency.acs-event-model.version>0.0.8</dependency.acs-event-model.version>

View File

@@ -28,7 +28,7 @@ import java.io.IOException;
import java.util.Locale;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.search.impl.lucene.LuceneQueryParserException;
import org.alfresco.repo.search.QueryParserException;
import org.alfresco.repo.search.impl.solr.SolrSQLJSONResultSet;
import org.alfresco.repo.security.permissions.impl.acegi.FilteringResultSet;
import org.alfresco.rest.api.search.impl.ResultMapper;
@@ -100,7 +100,7 @@ public class SearchSQLApiWebscript extends AbstractWebScript implements Recogniz
}
catch (Exception exception)
{
if (exception instanceof LuceneQueryParserException)
if (exception instanceof QueryParserException)
{
renderException(exception,res,assistant);
}

View File

@@ -44,7 +44,7 @@ import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import org.alfresco.repo.search.impl.lucene.SolrJSONResultSet;
import org.alfresco.repo.search.impl.solr.SolrJSONResultSet;
import org.alfresco.repo.search.impl.solr.facet.facetsresponse.GenericBucket;
import org.alfresco.repo.search.impl.solr.facet.facetsresponse.GenericFacetResponse;
import org.alfresco.repo.search.impl.solr.facet.facetsresponse.GenericFacetResponse.FACET_TYPE;

View File

@@ -349,20 +349,5 @@ public class AdminWebScriptTest extends BaseWebScriptTest
{
return null;
}
public String getAnalyserResourceBundleName()
{
return null;
}
public String resolveAnalyserClassName(Locale locale)
{
return null;
}
public String resolveAnalyserClassName()
{
return null;
}
}
}

View File

@@ -51,7 +51,7 @@ import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.alfresco.repo.search.EmptyResultSet;
import org.alfresco.repo.search.impl.lucene.SolrJSONResultSet;
import org.alfresco.repo.search.impl.solr.SolrJSONResultSet;
import org.alfresco.repo.search.impl.solr.facet.facetsresponse.GenericBucket;
import org.alfresco.repo.search.impl.solr.facet.facetsresponse.GenericFacetResponse;
import org.alfresco.repo.search.impl.solr.facet.facetsresponse.GenericFacetResponse.FACET_TYPE;

View File

@@ -11,11 +11,6 @@
</parent>
<dependencies>
<dependency>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-legacy-lucene</artifactId>
<version>${dependency.alfresco-legacy-lucene.version}</version>
</dependency>
<dependency>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-jlan-embed</artifactId>
@@ -944,13 +939,6 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-legacy-lucene</artifactId>
<version>${dependency.alfresco-legacy-lucene.version}</version>
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>

View File

@@ -1,245 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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/>.
* #L%
*/
package org.alfresco.opencmis.search;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.alfresco.opencmis.dictionary.CMISDictionaryService;
import org.alfresco.opencmis.search.CMISQueryOptions.CMISQueryMode;
import org.alfresco.repo.search.impl.lucene.PagingLuceneResultSet;
import org.alfresco.repo.search.impl.querymodel.Query;
import org.alfresco.repo.search.impl.querymodel.QueryEngine;
import org.alfresco.repo.search.impl.querymodel.QueryEngineResults;
import org.alfresco.repo.search.impl.querymodel.QueryModelException;
import org.alfresco.repo.security.permissions.impl.acegi.FilteringResultSet;
import org.alfresco.service.cmr.dictionary.DictionaryService;
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.LimitBy;
import org.alfresco.service.cmr.search.QueryConsistency;
import org.alfresco.service.cmr.search.ResultSet;
import org.alfresco.util.Pair;
import org.apache.chemistry.opencmis.commons.enums.BaseTypeId;
import org.apache.chemistry.opencmis.commons.enums.CapabilityJoin;
import org.apache.chemistry.opencmis.commons.enums.CapabilityQuery;
/**
* @author andyh
*/
public class CMISQueryServiceImpl implements CMISQueryService
{
private CMISDictionaryService cmisDictionaryService;
private QueryEngine luceneQueryEngine;
private QueryEngine dbQueryEngine;
private NodeService nodeService;
private DictionaryService alfrescoDictionaryService;
public void setOpenCMISDictionaryService(CMISDictionaryService cmisDictionaryService)
{
this.cmisDictionaryService = cmisDictionaryService;
}
/**
* @param queryEngine
* the luceneQueryEngine to set
*/
public void setLuceneQueryEngine(QueryEngine queryEngine)
{
this.luceneQueryEngine = queryEngine;
}
/**
* @param queryEngine
* the dbQueryEngine to set
*/
public void setDbQueryEngine(QueryEngine queryEngine)
{
this.dbQueryEngine = queryEngine;
}
/**
* @param nodeService
* the nodeService to set
*/
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
/**
* @param alfrescoDictionaryService
* the Alfresco Dictionary Service to set
*/
public void setAlfrescoDictionaryService(DictionaryService alfrescoDictionaryService)
{
this.alfrescoDictionaryService = alfrescoDictionaryService;
}
public CMISResultSet query(CMISQueryOptions options)
{
Pair<Query, QueryEngineResults> resultPair = executeQuerySwitchingImpl(options);
Query query = resultPair.getFirst();
QueryEngineResults results = resultPair.getSecond();
Map<String, ResultSet> wrapped = new HashMap<String, ResultSet>();
Map<Set<String>, ResultSet> map = results.getResults();
for (Set<String> group : map.keySet())
{
ResultSet current = map.get(group);
for (String selector : group)
{
wrapped.put(selector, filterNotExistingNodes(current));
}
}
LimitBy limitBy = null;
if ((null != results.getResults()) && !results.getResults().isEmpty()
&& (null != results.getResults().values()) && !results.getResults().values().isEmpty())
{
limitBy = results.getResults().values().iterator().next().getResultSetMetaData().getLimitedBy();
}
CMISResultSet cmis = new CMISResultSet(wrapped, options, limitBy, nodeService, query, cmisDictionaryService,
alfrescoDictionaryService);
return cmis;
}
private Pair<Query, QueryEngineResults> executeQuerySwitchingImpl(CMISQueryOptions options)
{
switch (options.getQueryConsistency())
{
case TRANSACTIONAL_IF_POSSIBLE :
{
try
{
return executeQueryUsingEngine(dbQueryEngine, options);
}
catch(QueryModelException qme)
{
return executeQueryUsingEngine(luceneQueryEngine, options);
}
}
case TRANSACTIONAL :
{
return executeQueryUsingEngine(dbQueryEngine, options);
}
case EVENTUAL :
case DEFAULT :
default :
{
return executeQueryUsingEngine(luceneQueryEngine, options);
}
}
}
private Pair<Query, QueryEngineResults> executeQueryUsingEngine(QueryEngine queryEngine, CMISQueryOptions options)
{
CapabilityJoin joinSupport = getJoinSupport();
if (options.getQueryMode() == CMISQueryOptions.CMISQueryMode.CMS_WITH_ALFRESCO_EXTENSIONS)
{
joinSupport = CapabilityJoin.INNERANDOUTER;
}
// TODO: Refactor to avoid duplication of valid scopes here and in
// CMISQueryParser
BaseTypeId[] validScopes = (options.getQueryMode() == CMISQueryMode.CMS_STRICT) ? CmisFunctionEvaluationContext.STRICT_SCOPES
: CmisFunctionEvaluationContext.ALFRESCO_SCOPES;
CmisFunctionEvaluationContext functionContext = new CmisFunctionEvaluationContext();
functionContext.setCmisDictionaryService(cmisDictionaryService);
functionContext.setNodeService(nodeService);
functionContext.setValidScopes(validScopes);
CMISQueryParser parser = new CMISQueryParser(options, cmisDictionaryService, joinSupport);
QueryConsistency queryConsistency = options.getQueryConsistency();
if (queryConsistency == QueryConsistency.DEFAULT)
{
options.setQueryConsistency(QueryConsistency.EVENTUAL);
}
Query query = parser.parse(queryEngine.getQueryModelFactory(), functionContext);
QueryEngineResults queryEngineResults = queryEngine.executeQuery(query, options, functionContext);
return new Pair<Query, QueryEngineResults>(query, queryEngineResults);
}
/* MNT-8804 filter ResultSet for nodes with corrupted indexes */
private ResultSet filterNotExistingNodes(ResultSet resultSet)
{
if (resultSet instanceof PagingLuceneResultSet)
{
ResultSet wrapped = ((PagingLuceneResultSet)resultSet).getWrapped();
if (wrapped instanceof FilteringResultSet)
{
FilteringResultSet filteringResultSet = (FilteringResultSet)wrapped;
for (int i = 0; i < filteringResultSet.length(); i++)
{
NodeRef nodeRef = filteringResultSet.getNodeRef(i);
/* filter node if it does not exist */
if (!nodeService.exists(nodeRef))
{
filteringResultSet.setIncluded(i, false);
}
}
}
}
return resultSet;
}
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;
}
}

View File

@@ -46,7 +46,7 @@ import org.alfresco.repo.blog.cannedqueries.DraftsAndPublishedBlogPostsCannedQue
import org.alfresco.repo.blog.cannedqueries.GetBlogPostsCannedQuery;
import org.alfresco.repo.blog.cannedqueries.GetBlogPostsCannedQueryFactory;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.search.impl.lucene.LuceneUtils;
import org.alfresco.repo.search.LuceneUtils;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.permissions.AccessDeniedException;
import org.alfresco.repo.site.SiteServiceImpl;

View File

@@ -1,28 +1,28 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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/>.
* #L%
*/
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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/>.
* #L%
*/
package org.alfresco.repo.links;
import java.io.Serializable;
@@ -42,7 +42,7 @@ import org.alfresco.repo.domain.node.NodeDAO;
import org.alfresco.repo.node.getchildren.GetChildrenAuditableCannedQuery;
import org.alfresco.repo.node.getchildren.GetChildrenAuditableCannedQueryFactory;
import org.alfresco.repo.query.NodeBackedEntity;
import org.alfresco.repo.search.impl.lucene.LuceneUtils;
import org.alfresco.repo.search.LuceneUtils;
import org.alfresco.repo.site.SiteServiceImpl;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.links.LinkInfo;

View File

@@ -1,50 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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/>.
* #L%
*/
package org.alfresco.repo.search;
/**
* How to carry out the index request ...
*
* @author andyh
*
*/
public enum IndexMode
{
/**
* Synchronously
*/
SYNCHRONOUS,
/**
* Asynchronously
*/
ASYNCHRONOUS,
/**
* Unindexed
*/
UNINDEXED;
}

View File

@@ -1,33 +1,32 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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/>.
* #L%
*/
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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/>.
* #L%
*/
package org.alfresco.repo.search;
import java.util.Collection;
import org.alfresco.repo.search.impl.lucene.LuceneIndexException;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;

View File

@@ -0,0 +1,128 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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/>.
* #L%
*/
package org.alfresco.repo.search;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
/**
* Lucene utils
*
* @author Andy
*
*/
public class LuceneUtils
{
/**
* This is the date string format as required by Lucene e.g. "1970\\-01\\-01T00:00:00"
* @since 4.0
*/
private static final SimpleDateFormat LUCENE_DATETIME_FORMAT = new SimpleDateFormat("yyyy\\-MM\\-dd'T'HH:mm:ss");
/**
* Returns a date string in the format required by Lucene.
*
* @since 4.0
*/
public static String getLuceneDateString(Date date)
{
return LUCENE_DATETIME_FORMAT.format(date);
}
/**
* This method creates a Lucene query fragment which constrains the specified dateProperty to a range
* given by the fromDate and toDate parameters.
*
* @param fromDate the start of the date range (defaults to 1970-01-01 00:00:00 if null).
* @param toDate the end of the date range (defaults to 3000-12-31 00:00:00 if null).
* @param dateProperty the Alfresco property value to check against the range (must be a valid Date or DateTime property).
*
* @return the Lucene query fragment.
*
* @throws NullPointerException if dateProperty is null or if the dateProperty is not recognised by the system.
* @throws IllegalArgumentException if dateProperty refers to a property that is not of type {@link DataTypeDefinition#DATE} or {@link DataTypeDefinition#DATETIME}.
*/
public static String createDateRangeQuery(Date fromDate, Date toDate, QName dateProperty,
DictionaryService dictionaryService, NamespaceService namespaceService)
{
// Some sanity checking of the date property.
if (dateProperty == null)
{
throw new NullPointerException("dateProperty cannot be null");
}
PropertyDefinition propDef = dictionaryService.getProperty(dateProperty);
if (propDef == null)
{
throw new NullPointerException("dateProperty '" + dateProperty + "' not recognised.");
}
else
{
final QName propDefType = propDef.getDataType().getName();
if ( !DataTypeDefinition.DATE.equals(propDefType) &&
!DataTypeDefinition.DATETIME.equals(propDefType))
{
throw new IllegalArgumentException("Illegal property type '" + dateProperty + "' [" + propDefType + "]");
}
}
QName propertyName = propDef.getName();
final String shortFormQName = propertyName.toPrefixString(namespaceService);
final String prefix = shortFormQName.substring(0, shortFormQName.indexOf(QName.NAMESPACE_PREFIX));
final String localName = propertyName.getLocalName();
// I can see potential issues with using 1970 and 3000 as default dates, but this is what the previous
// JavaScript controllers/libs did and I'll reproduce it here.
final String ZERO_DATE = "1970\\-01\\-01T00:00:00";
final String FUTURE_DATE = "3000\\-12\\-31T00:00:00";
StringBuilder luceneQuery = new StringBuilder();
luceneQuery.append(" +@").append(prefix).append("\\:").append(localName).append(":[");
if (fromDate != null)
{
luceneQuery.append(LuceneUtils.getLuceneDateString(fromDate));
}
else
{
luceneQuery.append(ZERO_DATE);
}
luceneQuery.append(" TO ");
if (toDate != null)
{
luceneQuery.append(LuceneUtils.getLuceneDateString(toDate));
}
else
{
luceneQuery.append(FUTURE_DATE);
}
luceneQuery.append("] ");
return luceneQuery.toString();
}
}

View File

@@ -0,0 +1,82 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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/>.
* #L%
*/
package org.alfresco.repo.search;
import org.alfresco.error.AlfrescoRuntimeException;
/**
* @author Andy
*
*/
public class QueryParserException extends AlfrescoRuntimeException
{
/**
*
*/
private static final long serialVersionUID = 4886993838297301968L;
/**
* @param msgId
*/
public QueryParserException(String msgId)
{
super(msgId);
// TODO Auto-generated constructor stub
}
/**
* @param msgId
* @param msgParams
*/
public QueryParserException(String msgId, Object[] msgParams)
{
super(msgId, msgParams);
// TODO Auto-generated constructor stub
}
/**
* @param msgId
* @param cause
*/
public QueryParserException(String msgId, Throwable cause)
{
super(msgId, cause);
// TODO Auto-generated constructor stub
}
/**
* @param msgId
* @param msgParams
* @param cause
*/
public QueryParserException(String msgId, Object[] msgParams, Throwable cause)
{
super(msgId, msgParams, cause);
// TODO Auto-generated constructor stub
}
}

View File

@@ -1,35 +1,36 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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/>.
* #L%
*/
package org.alfresco.repo.search.impl.lucene;
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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/>.
* #L%
*/
package org.alfresco.repo.search.impl;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.alfresco.repo.search.impl.lucene.AbstractLuceneQueryLanguage;
import org.alfresco.repo.search.impl.parsers.AlfrescoFunctionEvaluationContext;
import org.alfresco.repo.search.impl.parsers.FTSParser;
import org.alfresco.repo.search.impl.parsers.FTSQueryParser;
@@ -51,7 +52,7 @@ import org.alfresco.service.cmr.search.ResultSet;
import org.alfresco.service.cmr.search.SearchParameters;
import org.alfresco.service.cmr.search.SearchParameters.SortDefinition;
import org.alfresco.service.cmr.search.SearchParameters.SortDefinition.SortType;
import org.alfresco.service.namespace.NamespacePrefixResolver;
import org.alfresco.service.namespace.NamespacePrefixResolver;
import org.alfresco.service.namespace.NamespaceService;
/**
@@ -60,27 +61,27 @@ import org.alfresco.service.namespace.NamespaceService;
*/
public abstract class AbstractAlfrescoFtsQueryLanguage extends AbstractLuceneQueryLanguage
{
NamespaceService namespaceService;
DictionaryService dictionaryService;
NamespaceService namespaceService;
DictionaryService dictionaryService;
QueryEngine queryEngine;
/**
* @param namespaceService the namespaceService to set
*/
public void setNamespaceService(NamespaceService namespaceService)
{
this.namespaceService = namespaceService;
}
/**
* @param dictionaryService the dictionaryService to set
*/
public void setDictionaryService(DictionaryService dictionaryService)
{
this.dictionaryService = dictionaryService;
}
/**
* @param namespaceService the namespaceService to set
*/
public void setNamespaceService(NamespaceService namespaceService)
{
this.namespaceService = namespaceService;
}
/**
* @param dictionaryService the dictionaryService to set
*/
public void setDictionaryService(DictionaryService dictionaryService)
{
this.dictionaryService = dictionaryService;
}
/**
* @param queryEngine QueryEngine
*/
@@ -103,7 +104,7 @@ public abstract class AbstractAlfrescoFtsQueryLanguage extends AbstractLuceneQue
{
String ftsExpression = searchParameters.getQuery();
QueryModelFactory factory = queryEngine.getQueryModelFactory();
AlfrescoFunctionEvaluationContext context = new AlfrescoFunctionEvaluationContext(
AlfrescoFunctionEvaluationContext context = new AlfrescoFunctionEvaluationContext(
namespaceService, dictionaryService,
searchParameters.getNamespace());

View File

@@ -1,29 +1,29 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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/>.
* #L%
*/
package org.alfresco.repo.search.impl.lucene;
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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/>.
* #L%
*/
package org.alfresco.repo.search.impl;
import java.util.Collection;
import java.util.Collections;
@@ -32,7 +32,6 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.alfresco.error.AlfrescoRuntimeException;
@@ -43,10 +42,7 @@ import org.alfresco.query.PagingResults;
import org.alfresco.repo.search.IndexerAndSearcher;
import org.alfresco.repo.search.IndexerException;
import org.alfresco.repo.tenant.TenantService;
import org.alfresco.service.cmr.dictionary.AspectDefinition;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
import org.alfresco.service.cmr.repository.NodeRef;
@@ -69,7 +65,7 @@ import org.alfresco.util.Pair;
*
* @author andyh
*/
public class LuceneCategoryServiceImpl implements CategoryService
public abstract class AbstractCategoryServiceImpl implements CategoryService
{
protected NodeService nodeService;
@@ -81,14 +77,14 @@ public class LuceneCategoryServiceImpl implements CategoryService
protected DictionaryService dictionaryService;
protected IndexerAndSearcher indexerAndSearcher;
protected IndexerAndSearcher indexerAndSearcher;
protected int queryFetchSize = 5000;
/**
*
*/
public LuceneCategoryServiceImpl()
public AbstractCategoryServiceImpl()
{
super();
}
@@ -153,12 +149,12 @@ public class LuceneCategoryServiceImpl implements CategoryService
public void setIndexerAndSearcher(IndexerAndSearcher indexerAndSearcher)
{
this.indexerAndSearcher = indexerAndSearcher;
}
}
public void setQueryFetchSize(int queryFetchSize) {
this.queryFetchSize = queryFetchSize;
}
public void setQueryFetchSize(int queryFetchSize) {
this.queryFetchSize = queryFetchSize;
}
public Collection<ChildAssociationRef> getChildren(NodeRef categoryRef, Mode mode, Depth depth)
{
return getChildren(categoryRef, mode, depth, false, null, queryFetchSize);
@@ -541,70 +537,5 @@ public class LuceneCategoryServiceImpl implements CategoryService
throw new UnsupportedOperationException();
}
public List<Pair<NodeRef, Integer>> getTopCategories(StoreRef storeRef, QName aspectName, int count)
{
if (indexerAndSearcher instanceof LuceneIndexerAndSearcher)
{
AspectDefinition definition = dictionaryService.getAspect(aspectName);
if(definition == null)
{
throw new IllegalStateException("Unknown aspect");
}
QName catProperty = null;
Map<QName, PropertyDefinition> properties = definition.getProperties();
for(QName pName : properties.keySet())
{
if(pName.getNamespaceURI().equals(aspectName.getNamespaceURI()))
{
if(pName.getLocalName().equalsIgnoreCase(aspectName.getLocalName()))
{
PropertyDefinition def = properties.get(pName);
if(def.getDataType().getName().equals(DataTypeDefinition.CATEGORY))
{
catProperty = pName;
}
}
}
}
if(catProperty == null)
{
throw new IllegalStateException("Aspect does not have category property mirroring the aspect name");
}
LuceneIndexerAndSearcher lias = (LuceneIndexerAndSearcher) indexerAndSearcher;
String field = "@" + catProperty;
SearchService searchService = lias.getSearcher(storeRef, false);
if (searchService instanceof LuceneSearcher)
{
LuceneSearcher luceneSearcher = (LuceneSearcher)searchService;
List<Pair<String, Integer>> topTerms = luceneSearcher.getTopTerms(field, count);
List<Pair<NodeRef, Integer>> answer = new LinkedList<Pair<NodeRef, Integer>>();
for (Pair<String, Integer> term : topTerms)
{
Pair<NodeRef, Integer> toAdd;
NodeRef nodeRef = new NodeRef(term.getFirst());
if (nodeService.exists(nodeRef))
{
toAdd = new Pair<NodeRef, Integer>(nodeRef, term.getSecond());
}
else
{
toAdd = new Pair<NodeRef, Integer>(null, term.getSecond());
}
answer.add(toAdd);
}
return answer;
}
else
{
throw new UnsupportedOperationException("getPolularCategories is only supported for lucene indexes");
}
}
else
{
throw new UnsupportedOperationException("getPolularCategories is only supported for lucene indexes");
}
}
public abstract List<Pair<NodeRef, Integer>> getTopCategories(StoreRef storeRef, QName aspectName, int count);
}

View File

@@ -1,29 +1,29 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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/>.
* #L%
*/
package org.alfresco.repo.search.impl.lucene;
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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/>.
* #L%
*/
package org.alfresco.repo.search.impl;
import java.util.HashMap;
import java.util.Map;
@@ -32,6 +32,7 @@ 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.repo.search.impl.lucene.LuceneQueryLanguageSPI;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.search.SearchService;

View File

@@ -23,7 +23,7 @@
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.search.impl.lucene;
package org.alfresco.repo.search.impl;
import java.util.Collections;
import java.util.HashMap;
@@ -71,7 +71,7 @@ public abstract class AbstractJSONAPIResult implements JSONAPIResult
}
/* (non-Javadoc)
* @see org.alfresco.repo.search.impl.lucene.JSONAPIResult#getCores()
* @see org.alfresco.repo.search.impl.JSONAPIResult#getCores()
*/
@Override
public List<String> getCores()
@@ -80,7 +80,7 @@ public abstract class AbstractJSONAPIResult implements JSONAPIResult
}
/* (non-Javadoc)
* @see org.alfresco.repo.search.impl.lucene.JSONAPIResult#getCoresInfo()
* @see org.alfresco.repo.search.impl.JSONAPIResult#getCoresInfo()
*/
@Override
public Map<String, Map<String, Object>> getCoresInfo()

View File

@@ -1,32 +1,32 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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/>.
* #L%
*/
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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/>.
* #L%
*/
package org.alfresco.repo.search.impl;
import org.alfresco.repo.search.impl.lucene.SolrSuggesterResult;
import org.alfresco.repo.search.impl.solr.SolrSuggesterResult;
import org.alfresco.service.cmr.search.SuggesterParameters;
import org.alfresco.service.cmr.search.SuggesterResult;
import org.alfresco.service.cmr.search.SuggesterService;

View File

@@ -23,26 +23,26 @@
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.search.impl.lucene;
package org.alfresco.repo.search.impl;
import java.util.List;
import java.util.Map;
/**
* JSON returned from SOLR API
*
* @author aborroy
* @since 6.2
*/
public interface JSONAPIResult
/**
* JSON returned from SOLR API
*
* @author aborroy
* @since 6.2
*/
public interface JSONAPIResult
{
/**
* Time to perform the requested action or command in SOLR
* @return Number of milliseconds
*/
public Long getQueryTime();
/**
* HTTP Response code
* But for 200, that is being returned as 0

View File

@@ -23,11 +23,19 @@
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.search.impl.lucene;
package org.alfresco.repo.search.impl;
import java.util.Arrays;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.search.impl.solr.SolrActionAclReportResult;
import org.alfresco.repo.search.impl.solr.SolrActionAclTxReportResult;
import org.alfresco.repo.search.impl.solr.SolrActionCheckResult;
import org.alfresco.repo.search.impl.solr.SolrActionFixResult;
import org.alfresco.repo.search.impl.solr.SolrActionNodeReportResult;
import org.alfresco.repo.search.impl.solr.SolrActionReportResult;
import org.alfresco.repo.search.impl.solr.SolrActionStatusResult;
import org.alfresco.repo.search.impl.solr.SolrActionTxReportResult;
import org.json.JSONException;
import org.json.JSONObject;

View File

@@ -23,16 +23,16 @@
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.search.impl.lucene;
/**
* Json returned from Solr
*
* @author Gethin James
* @since 5.0
*/
public interface JSONResult
{
public Long getQueryTime();
public long getNumberFound();
}
package org.alfresco.repo.search.impl;
/**
* Json returned from Solr
*
* @author Gethin James
* @since 5.0
*/
public interface JSONResult
{
public Long getQueryTime();
public long getNumberFound();
}

View File

@@ -23,26 +23,26 @@
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.search.impl.lucene;
import org.alfresco.error.AlfrescoRuntimeException;
public class QueryParameterisationException extends AlfrescoRuntimeException
{
/**
*
*/
private static final long serialVersionUID = 1L;
public QueryParameterisationException(String msg)
{
super(msg);
}
public QueryParameterisationException(String msg, Throwable cause)
{
super(msg, cause);
}
}
package org.alfresco.repo.search.impl;
import org.alfresco.error.AlfrescoRuntimeException;
public class QueryParameterisationException extends AlfrescoRuntimeException
{
/**
*
*/
private static final long serialVersionUID = 1L;
public QueryParameterisationException(String msg)
{
super(msg);
}
public QueryParameterisationException(String msg, Throwable cause)
{
super(msg, cause);
}
}

View File

@@ -1,355 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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/>.
* #L%
*/
package org.alfresco.repo.search.impl.lucene;
import java.io.File;
import java.io.IOException;
import java.util.Set;
import org.alfresco.repo.search.IndexerException;
import org.alfresco.repo.search.impl.lucene.analysis.AlfrescoStandardAnalyser;
import org.alfresco.repo.search.impl.lucene.index.IndexInfo;
import org.alfresco.repo.search.impl.lucene.index.TransactionStatus;
import org.alfresco.repo.search.impl.lucene.index.IndexInfo.LockWork;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.repository.StoreRef;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.search.IndexSearcher;
/**
* Common support for abstracting the lucene indexer from its configuration and management requirements.
*
* <p>
* This class defines where the indexes are stored. This should be via a configurable Bean property in Spring.
*
* <p>
* The default file structure is
* <ol>
* <li><b>"base"/"protocol"/"name"/</b> for the main index
* <li><b>"base"/"protocol"/"name"/deltas/"id"</b> for transactional updates
* <li><b>"base"/"protocol"/"name"/undo/"id"</b> undo information
* </ol>
*
* <p>
* The IndexWriter and IndexReader for a given index are toggled (one should be used for delete and the other for write). These are reused/closed/initialised as required.
*
* <p>
* The index deltas are buffered to memory and persisted in the file system as required.
*
* @author Andy Hind
*
*/
public abstract class AbstractLuceneBase
{
private static Log s_logger = LogFactory.getLog(AbstractLuceneBase.class);
private IndexInfo indexInfo;
/**
* The identifier for the store
*/
protected StoreRef store;
/**
* The identifier for the delta
*/
protected String deltaId;
private LuceneConfig config;
private TransactionStatus status = TransactionStatus.UNKNOWN;
// "lucene-indexes";
/**
* Initialise the configuration elements of the lucene store indexers and searchers.
*
* @param store StoreRef
* @param deltaId String
* @throws LuceneIndexException
*/
protected void initialise(StoreRef store, String deltaId)
throws LuceneIndexException
{
this.store = store;
this.deltaId = deltaId;
String basePath = getBasePath();
File baseDir = new File(basePath);
indexInfo = IndexInfo.getIndexInfo(baseDir, config);
try
{
if (this.deltaId != null)
{
if (! getStatus().equals(TransactionStatus.ACTIVE))
{
setStatus(TransactionStatus.ACTIVE);
}
else
{
if (s_logger.isDebugEnabled())
{
s_logger.debug("Delta already set as active " + deltaId);
}
}
}
}
catch (IOException e)
{
throw new IndexerException("Failed to set delta as active");
}
}
/**
* Utility method to find the path to the base index
*
* @return - the base path
*/
private String getBasePath()
{
if (config.getIndexRootLocation() == null)
{
throw new IndexerException("No configuration for index location");
}
String basePath = config.getIndexRootLocation()
+ File.separator + store.getProtocol() + File.separator + store.getIdentifier() + File.separator;
return basePath;
}
/**
* Get a searcher for the main index TODO: Split out support for the main index. We really only need this if we want to search over the changing index before it is committed
*
* @return - the searcher
* @throws LuceneIndexException
*/
protected IndexSearcher getSearcher() throws LuceneIndexException
{
try
{
return new ClosingIndexSearcher(indexInfo.getMainIndexReferenceCountingReadOnlyIndexReader());
}
catch (IOException e)
{
s_logger.error("Error", e);
throw new LuceneIndexException("Failed to open IndexSarcher for " + getBasePath(), e);
}
}
protected ClosingIndexSearcher getSearcher(LuceneIndexer luceneIndexer) throws LuceneIndexException
{
// If we know the delta id we should do better
try
{
if (luceneIndexer == null)
{
return new ClosingIndexSearcher(indexInfo.getMainIndexReferenceCountingReadOnlyIndexReader());
}
else
{
// TODO: Create appropriate reader that lies about deletions
// from the first
//
luceneIndexer.flushPending();
return new ClosingIndexSearcher(indexInfo.getMainIndexReferenceCountingReadOnlyIndexReader(deltaId,
luceneIndexer.getDeletions(), luceneIndexer.getContainerDeletions(), luceneIndexer
.getDeleteOnlyNodes()));
}
}
catch (IOException e)
{
s_logger.error("Error", e);
throw new LuceneIndexException("Failed to open IndexSarcher for " + getBasePath(), e);
}
}
/**
* Get a reader for the on file portion of the delta
*
* @return - the index reader
* @throws IOException
* @throws IOException
*/
protected IndexReader getDeltaReader() throws LuceneIndexException, IOException
{
return indexInfo.getDeltaIndexReader(deltaId);
}
/**
* Close the on file reader for the delta if it is open
*
* @throws IOException
*
* @throws IOException
*/
protected void closeDeltaReader() throws LuceneIndexException, IOException
{
indexInfo.closeDeltaIndexReader(deltaId);
}
/**
* Get the on file writer for the delta
*
* @return - the writer for the delta
* @throws IOException
* @throws IOException
*/
protected IndexWriter getDeltaWriter() throws LuceneIndexException, IOException
{
return indexInfo.getDeltaIndexWriter(deltaId, new LuceneAnalyser(dictionaryService, config.getDefaultMLIndexAnalysisMode()));
}
/**
* Close the on disk delta writer
*
* @throws IOException
*
* @throws IOException
*/
protected void closeDeltaWriter() throws LuceneIndexException, IOException
{
indexInfo.closeDeltaIndexWriter(deltaId);
}
/**
* Save the in memory delta to the disk, make sure there is nothing held in memory
*
* @throws IOException
*
* @throws IOException
*/
protected void saveDelta() throws LuceneIndexException, IOException
{
// Only one should exist so we do not need error trapping to execute the
// other
closeDeltaReader();
closeDeltaWriter();
}
protected void setInfo(long docs, Set<String> deletions, Set<String> containerDeletions, boolean deleteNodesOnly) throws IOException
{
indexInfo.setPreparedState(deltaId, deletions, containerDeletions, docs, deleteNodesOnly);
}
protected void setStatus(TransactionStatus status) throws IOException
{
indexInfo.setStatus(deltaId, status, null, null);
this.status = status;
}
protected TransactionStatus getStatus()
{
return status;
}
private DictionaryService dictionaryService;
protected IndexReader getReader() throws LuceneIndexException, IOException
{
return indexInfo.getMainIndexReferenceCountingReadOnlyIndexReader();
}
/**
* Set the dictionary service
* @param dictionaryService DictionaryService
*/
public void setDictionaryService(DictionaryService dictionaryService)
{
this.dictionaryService = dictionaryService;
}
/**
* Get the dictionary service.
*
* @return - the service
*/
public DictionaryService getDictionaryService()
{
return dictionaryService;
}
/**
* Set the lucene configuration options
*
* @param config LuceneConfig
*/
public void setLuceneConfig(LuceneConfig config)
{
this.config = config;
}
/**
* Get the lucene configuration options.
*
* @return - the config options object.
*/
public LuceneConfig getLuceneConfig()
{
return config;
}
/**
* Get the ID for the delat we are working with.
*
* @return - the id
*/
public String getDeltaId()
{
return deltaId;
}
/**
* Execute actions against a read only index (all write ops will block)
*
* @return - the result returned by the action.
*/
public <R> R doReadOnly(LockWork<R> lockWork)
{
return indexInfo.doReadOnly(lockWork);
}
public void deleteIndex()
{
indexInfo.delete(deltaId);
}
}

View File

@@ -1,814 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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/>.
* #L%
*/
package org.alfresco.repo.search.impl.lucene;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.ListIterator;
import java.util.Set;
import javax.transaction.Status;
import javax.transaction.xa.XAResource;
import org.alfresco.repo.node.NodeBulkLoader;
import org.alfresco.repo.search.Indexer;
import org.alfresco.repo.search.IndexerException;
import org.alfresco.repo.search.impl.lucene.index.TransactionStatus;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
import org.alfresco.service.transaction.TransactionService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.index.TermDocs;
import org.springframework.dao.ConcurrencyFailureException;
/**
* Common support for indexing across implementations
*
* @author andyh
* @param <T> -
* the type used to generate the key in the index file
*/
public abstract class AbstractLuceneIndexerImpl<T> extends AbstractLuceneBase implements Indexer
{
/**
* Enum for indexing actions against a node
*/
protected enum Action
{
/**
* An index
*/
INDEX,
/**
* A reindex
*/
REINDEX,
/**
* A delete
*/
DELETE,
/**
* A cascaded reindex (ensures directory structre is ok)
*/
CASCADEREINDEX
}
protected enum IndexUpdateStatus
{
/**
* Inde is unchanged
*/
UNMODIFIED,
/**
* Index is being changein in TX
*/
SYNCRONOUS,
/**
* Index is eiong changed by a background upate
*/
ASYNCHRONOUS;
}
protected enum FTSStatus {New, Dirty, Clean};
protected long docs;
// An indexer with read through activated can only see already-committed documents in the database. Useful when
// reindexing lots of old documents and not wanting to pollute the caches with stale versions of nodes.
private boolean isReadThrough;
protected TransactionService transactionService;
protected NodeBulkLoader bulkLoader;
public void setReadThrough(boolean isReadThrough)
{
this.isReadThrough = isReadThrough;
}
public void setTransactionService(TransactionService transactionService)
{
this.transactionService = transactionService;
}
/**
* @param bulkLoader object to provide node loading options
*/
public void setBulkLoader(NodeBulkLoader bulkLoader)
{
this.bulkLoader = bulkLoader;
}
protected static class Command<S>
{
S ref;
Action action;
Command(S ref, Action action)
{
this.ref = ref;
this.action = action;
}
public String toString()
{
StringBuffer buffer = new StringBuffer();
if (action == Action.INDEX)
{
buffer.append("Index ");
}
else if (action == Action.DELETE)
{
buffer.append("Delete ");
}
else if (action == Action.REINDEX)
{
buffer.append("Reindex ");
}
else
{
buffer.append("Unknown ... ");
}
buffer.append(ref);
return buffer.toString();
}
}
/**
* No transform available
*/
public static final String NOT_INDEXED_NO_TRANSFORMATION = "nint";
/**
* Tranfrom failed
*/
public static final String NOT_INDEXED_TRANSFORMATION_FAILED = "nitf";
/**
* No content
*/
public static final String NOT_INDEXED_CONTENT_MISSING = "nicm";
/**
* No type conversion
*/
public static final String NOT_INDEXED_NO_TYPE_CONVERSION = "nintc";
/**
* Logger
*/
private static Log s_logger = LogFactory.getLog(AbstractLuceneIndexerImpl.class);
protected static Set<String> deletePrimary(Collection<String> nodeRefs, IndexReader reader, boolean delete)
throws LuceneIndexException
{
Set<String> refs = new LinkedHashSet<String>();
for (String nodeRef : nodeRefs)
{
try
{
TermDocs td = reader.termDocs(new Term("PRIMARYPARENT", nodeRef));
while (td.next())
{
int doc = td.doc();
Document document = reader.document(doc);
String[] ids = document.getValues("ID");
refs.add(ids[ids.length - 1]);
if (delete)
{
reader.deleteDocument(doc);
}
}
td.close();
}
catch (IOException e)
{
throw new LuceneIndexException("Failed to delete node by primary parent for " + nodeRef, e);
}
}
return refs;
}
protected static Set<String> deleteReference(Collection<String> nodeRefs, IndexReader reader, boolean delete)
throws LuceneIndexException
{
Set<String> refs = new LinkedHashSet<String>();
for (String nodeRef : nodeRefs)
{
try
{
TermDocs td = reader.termDocs(new Term("PARENT", nodeRef));
while (td.next())
{
int doc = td.doc();
Document document = reader.document(doc);
String[] ids = document.getValues("ID");
refs.add(ids[ids.length - 1]);
if (delete)
{
reader.deleteDocument(doc);
}
}
td.close();
}
catch (IOException e)
{
throw new LuceneIndexException("Failed to delete node by parent for " + nodeRef, e);
}
}
return refs;
}
protected static Set<String> deleteContainerAndBelow(String nodeRef, IndexReader reader, boolean delete,
boolean cascade) throws LuceneIndexException
{
Set<String> refs = new LinkedHashSet<String>();
try
{
if (delete)
{
reader.deleteDocuments(new Term("ID", nodeRef));
}
refs.add(nodeRef);
if (cascade)
{
TermDocs td = reader.termDocs(new Term("ANCESTOR", nodeRef));
while (td.next())
{
int doc = td.doc();
Document document = reader.document(doc);
String[] ids = document.getValues("ID");
refs.add(ids[ids.length - 1]);
if (delete)
{
reader.deleteDocument(doc);
}
}
td.close();
}
}
catch (IOException e)
{
throw new LuceneIndexException("Failed to delete container and below for " + nodeRef, e);
}
return refs;
}
protected boolean locateContainer(String nodeRef, IndexReader reader)
{
boolean found = false;
try
{
TermDocs td = reader.termDocs(new Term("ID", nodeRef));
while (td.next())
{
int doc = td.doc();
Document document = reader.document(doc);
if (document.getField("ISCONTAINER") != null)
{
found = true;
break;
}
}
td.close();
}
catch (IOException e)
{
throw new LuceneIndexException("Failed to delete container and below for " + nodeRef, e);
}
return found;
}
/** the maximum transformation time to allow atomically, defaulting to 20ms */
protected long maxAtomicTransformationTime = 20;
/**
* A list of all deletions we have made - at merge these deletions need to be made against the main index. TODO:
* Consider if this information needs to be persisted for recovery
*/
protected Set<String> deletions = new LinkedHashSet<String>();
/**
* A list of cascading container deletions we have made - at merge these deletions need to be made against the main index.
*/
protected Set<String> containerDeletions = new LinkedHashSet<String>();
/**
* List of pending indexing commands.
*/
protected List<Command<T>> commandList = new ArrayList<Command<T>>(10000);
/**
* Flag to indicte if we are doing an in transactional delta or a batch update to the index. If true, we are just
* fixing up non atomically indexed things from one or more other updates.
*/
protected IndexUpdateStatus indexUpdateStatus = IndexUpdateStatus.UNMODIFIED;
/**
* Set the max time allowed to transform content atomically
*
* @param maxAtomicTransformationTime long
*/
public void setMaxAtomicTransformationTime(long maxAtomicTransformationTime)
{
this.maxAtomicTransformationTime = maxAtomicTransformationTime;
}
/**
* Utility method to check we are in the correct state to do work Also keeps track of the dirty flag.
*
* @throws IndexerException
* @throws LuceneIndexException
*/
protected void checkAbleToDoWork(IndexUpdateStatus indexUpdateStatus)
{
if (this.indexUpdateStatus == IndexUpdateStatus.UNMODIFIED)
{
this.indexUpdateStatus = indexUpdateStatus;
}
else if (this.indexUpdateStatus == indexUpdateStatus)
{
return;
}
else
{
throw new IndexerException("Can not mix FTS and transactional updates");
}
switch (getStatus())
{
case UNKNOWN:
try
{
setStatus(TransactionStatus.ACTIVE);
}
catch (IOException e)
{
throw new LuceneIndexException("Failed to set TX active", e);
}
break;
case ACTIVE:
// OK
break;
default:
// All other states are a problem
throw new IndexerException(buildErrorString());
}
}
/**
* Utility method to report errors about invalid state.
*
* @return - an error based on status
*/
private String buildErrorString()
{
StringBuilder buffer = new StringBuilder(128);
buffer.append("The indexer is unable to accept more work: ");
switch (getStatus().getStatus())
{
case Status.STATUS_COMMITTED:
buffer.append("The indexer has been committed");
break;
case Status.STATUS_COMMITTING:
buffer.append("The indexer is committing");
break;
case Status.STATUS_MARKED_ROLLBACK:
buffer.append("The indexer is marked for rollback");
break;
case Status.STATUS_PREPARED:
buffer.append("The indexer is prepared to commit");
break;
case Status.STATUS_PREPARING:
buffer.append("The indexer is preparing to commit");
break;
case Status.STATUS_ROLLEDBACK:
buffer.append("The indexer has been rolled back");
break;
case Status.STATUS_ROLLING_BACK:
buffer.append("The indexer is rolling back");
break;
case Status.STATUS_UNKNOWN:
buffer.append("The indexer is in an unknown state");
break;
default:
break;
}
return buffer.toString();
}
/**
* Commit this index
*
* @throws LuceneIndexException
*/
public void commit() throws LuceneIndexException
{
if (s_logger.isDebugEnabled())
{
s_logger.debug(Thread.currentThread().getName() + " Starting Commit");
}
switch (getStatus().getStatus())
{
case Status.STATUS_COMMITTING:
throw new LuceneIndexException("Unable to commit: Transaction is committing");
case Status.STATUS_COMMITTED:
throw new LuceneIndexException("Unable to commit: Transaction is commited ");
case Status.STATUS_ROLLING_BACK:
throw new LuceneIndexException("Unable to commit: Transaction is rolling back");
case Status.STATUS_ROLLEDBACK:
throw new LuceneIndexException("Unable to commit: Transaction is aleady rolled back");
case Status.STATUS_MARKED_ROLLBACK:
throw new LuceneIndexException("Unable to commit: Transaction is marked for roll back");
case Status.STATUS_PREPARING:
throw new LuceneIndexException("Unable to commit: Transaction is preparing");
case Status.STATUS_ACTIVE:
// special case - commit from active
prepare();
// drop through to do the commit;
default:
if (getStatus().getStatus() != Status.STATUS_PREPARED)
{
throw new LuceneIndexException("Index must be prepared to commit");
}
try
{
setStatus(TransactionStatus.COMMITTING);
if (isModified())
{
doCommit();
}
setStatus(TransactionStatus.COMMITTED);
}
catch (LuceneIndexException e)
{
// If anything goes wrong we try and do a roll back
rollback();
if (s_logger.isDebugEnabled())
{
s_logger.debug(Thread.currentThread().getName() + " Commit Failed", e);
}
throw new LuceneIndexException("Commit failed", e);
}
catch (Throwable t)
{
// If anything goes wrong we try and do a roll back
rollback();
if (s_logger.isDebugEnabled())
{
s_logger.debug(Thread.currentThread().getName() + " Commit Failed", t);
}
throw new LuceneIndexException("Commit failed", t);
}
finally
{
if (s_logger.isDebugEnabled())
{
s_logger.debug(Thread.currentThread().getName() + " Ending Commit");
}
// Make sure we tidy up
// deleteDelta();
}
break;
}
}
/**
* Prepare to commit At the moment this makes sure we have all the locks TODO: This is not doing proper
* serialisation against the index as would a data base transaction.
*
* @return the tx state
* @throws LuceneIndexException
*/
public int prepare() throws LuceneIndexException
{
if (s_logger.isDebugEnabled())
{
s_logger.debug(Thread.currentThread().getName() + " Starting Prepare");
}
switch (getStatus().getStatus())
{
case Status.STATUS_COMMITTING:
throw new IndexerException("Unable to prepare: Transaction is committing");
case Status.STATUS_COMMITTED:
throw new IndexerException("Unable to prepare: Transaction is commited ");
case Status.STATUS_ROLLING_BACK:
throw new IndexerException("Unable to prepare: Transaction is rolling back");
case Status.STATUS_ROLLEDBACK:
throw new IndexerException("Unable to prepare: Transaction is aleady rolled back");
case Status.STATUS_MARKED_ROLLBACK:
throw new IndexerException("Unable to prepare: Transaction is marked for roll back");
case Status.STATUS_PREPARING:
throw new IndexerException("Unable to prepare: Transaction is already preparing");
case Status.STATUS_PREPARED:
throw new IndexerException("Unable to prepare: Transaction is already prepared");
default:
try
{
setStatus(TransactionStatus.PREPARING);
if (isModified())
{
doPrepare();
if (s_logger.isDebugEnabled())
{
s_logger.debug(Thread.currentThread().getName() + " Waiting to Finish Preparing");
}
}
setStatus(TransactionStatus.PREPARED);
return isModified() ? XAResource.XA_OK : XAResource.XA_RDONLY;
}
catch (LuceneIndexException e)
{
setRollbackOnly();
if (s_logger.isDebugEnabled())
{
s_logger.debug(Thread.currentThread().getName() + " Prepare Failed", e);
}
throw new LuceneIndexException("Index failed to prepare", e);
}
catch (Throwable t)
{
// If anything goes wrong we try and do a roll back
rollback();
if (s_logger.isDebugEnabled())
{
s_logger.debug(Thread.currentThread().getName() + " Prepare Failed", t);
}
throw new LuceneIndexException("Prepared failed", t);
}
finally
{
if (s_logger.isDebugEnabled())
{
s_logger.debug(Thread.currentThread().getName() + " Ending Prepare");
}
}
}
}
/**
* Has this index been modified?
*
* @return true if modified
*/
public boolean isModified()
{
return indexUpdateStatus != IndexUpdateStatus.UNMODIFIED;
}
/**
* Roll back the index changes (this just means they are never added)
*
* @throws LuceneIndexException
*/
public void rollback() throws LuceneIndexException
{
switch (getStatus().getStatus())
{
case Status.STATUS_COMMITTED:
throw new IndexerException("Unable to roll back: Transaction is committed ");
case Status.STATUS_ROLLING_BACK:
throw new IndexerException("Unable to roll back: Transaction is rolling back");
case Status.STATUS_ROLLEDBACK:
throw new IndexerException("Unable to roll back: Transaction is already rolled back");
case Status.STATUS_COMMITTING:
// Can roll back during commit
default:
try
{
setStatus(TransactionStatus.ROLLINGBACK);
doRollBack();
setStatus(TransactionStatus.ROLLEDBACK);
}
catch (IOException e)
{
throw new LuceneIndexException("rollback failed ", e);
}
break;
}
}
/**
* Mark this index for roll back only. This action can not be reversed. It will reject all other work and only allow
* roll back.
*/
public void setRollbackOnly()
{
switch (getStatus().getStatus())
{
case Status.STATUS_COMMITTING:
throw new IndexerException("Unable to mark for rollback: Transaction is committing");
case Status.STATUS_COMMITTED:
throw new IndexerException("Unable to mark for rollback: Transaction is committed");
default:
try
{
doSetRollbackOnly();
setStatus(TransactionStatus.MARKED_ROLLBACK);
}
catch (IOException e)
{
throw new LuceneIndexException("Set rollback only failed ", e);
}
break;
}
}
protected abstract void doPrepare() throws IOException;
protected abstract void doCommit() throws IOException;
protected abstract void doRollBack() throws IOException;
protected abstract void doSetRollbackOnly() throws IOException;
protected <T2> T2 doInReadthroughTransaction(final RetryingTransactionCallback<T2> callback)
{
if (isReadThrough)
{
return transactionService.getRetryingTransactionHelper().doInTransaction(
new RetryingTransactionCallback<T2>()
{
@Override
public T2 execute() throws Throwable
{
// ALF-18383: Regression in Lucene indexing performance in 4.x
// We accept the loss of some performance in order to ensure accuracy
// Request clean node data
if (bulkLoader != null)
{
bulkLoader.setCheckNodeConsistency();
}
try
{
return callback.execute();
}
catch (InvalidNodeRefException e)
{
// Turn InvalidNodeRefExceptions into retryable exceptions.
throw new ConcurrencyFailureException(
"Possible cache integrity issue during reindexing", e);
}
}
}, true, true);
}
else
{
try
{
return callback.execute();
}
catch (RuntimeException e)
{
throw e;
}
catch (Error e)
{
throw e;
}
catch (Throwable e)
{
throw new RuntimeException(e);
}
}
}
protected void index(T ref) throws LuceneIndexException
{
addCommand(new Command<T>(ref, Action.INDEX));
}
protected void reindex(T ref, boolean cascadeReindexDirectories) throws LuceneIndexException
{
addCommand(new Command<T>(ref, cascadeReindexDirectories ? Action.CASCADEREINDEX : Action.REINDEX));
}
protected void delete(T ref) throws LuceneIndexException
{
addCommand(new Command<T>(ref, Action.DELETE));
}
private void addCommand(Command<T> command)
{
if (commandList.size() > 0)
{
Command<T> last = commandList.get(commandList.size() - 1);
if ((last.action == command.action) && (last.ref.equals(command.ref)))
{
return;
}
}
purgeCommandList(command);
commandList.add(command);
if (commandList.size() > getLuceneConfig().getIndexerBatchSize())
{
flushPending();
}
}
private void purgeCommandList(Command<T> command)
{
removeFromCommandList(command, command.action != Action.DELETE);
}
private void removeFromCommandList(Command<T> command, boolean matchExact)
{
for (ListIterator<Command<T>> it = commandList.listIterator(commandList.size()); it.hasPrevious(); /**/)
{
Command<T> current = it.previous();
if (matchExact)
{
if (current.ref.equals(command.ref))
{
if ((current.action == command.action))
{
it.remove();
return;
}
// If there is an INDEX in this same transaction and the current command is a reindex, remove it and
// replace the current command with it
else if (command.action != Action.DELETE && current.action == Action.INDEX)
{
it.remove();
command.action = Action.INDEX;
}
}
}
else
{
if (current.ref.equals(command.ref))
{
it.remove();
}
}
}
}
/**
* Get the deletions
*
* @return - the ids to delete
*/
public Set<String> getDeletions()
{
return Collections.unmodifiableSet(deletions);
}
/**
* Get the container deletions
*
* @return - the ids to delete
*/
public Set<String> getContainerDeletions()
{
return Collections.unmodifiableSet(containerDeletions);
}
}

View File

@@ -1,33 +1,34 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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/>.
* #L%
*/
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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/>.
* #L%
*/
package org.alfresco.repo.search.impl.lucene;
import java.util.List;
import org.alfresco.repo.search.IndexerAndSearcher;
import org.alfresco.repo.search.impl.lucene.LuceneQueryLanguageSPI;
import org.springframework.beans.factory.InitializingBean;
/**

View File

@@ -1,69 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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/>.
* #L%
*/
package org.alfresco.repo.search.impl.lucene;
import java.io.IOException;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.store.Directory;
public class ClosingIndexSearcher extends IndexSearcher
{
IndexReader reader;
public ClosingIndexSearcher(String path) throws IOException
{
super(path);
}
public ClosingIndexSearcher(Directory directory) throws IOException
{
super(directory);
}
public ClosingIndexSearcher(IndexReader r)
{
super(r);
this.reader = r;
}
/*package*/ IndexReader getReader()
{
return reader;
}
@Override
public void close() throws IOException
{
super.close();
if(reader != null)
{
reader.close();
}
}
}

View File

@@ -1,276 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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/>.
* #L%
*/
package org.alfresco.repo.search.impl.lucene;
import org.jaxen.saxpath.Axis;
import org.jaxen.saxpath.SAXPathException;
import org.jaxen.saxpath.XPathHandler;
import org.jaxen.saxpath.base.XPathReader;
public class DebugXPathHandler implements XPathHandler
{
public DebugXPathHandler()
{
super();
// TODO Auto-generated constructor stub
}
public void endAbsoluteLocationPath() throws SAXPathException
{
System.out.println("End Absolute Location Path");
}
public void endAdditiveExpr(int arg0) throws SAXPathException
{
System.out.println("End Additive Expr: value = " + arg0);
}
public void endAllNodeStep() throws SAXPathException
{
System.out.println("End All Node Step");
}
public void endAndExpr(boolean arg0) throws SAXPathException
{
System.out.println("End And Expr: value = " + arg0);
}
public void endCommentNodeStep() throws SAXPathException
{
System.out.println("End Comment Node Step");
}
public void endEqualityExpr(int arg0) throws SAXPathException
{
System.out.println("End Equality Expr: value = " + arg0);
}
public void endFilterExpr() throws SAXPathException
{
System.out.println("End Filter Expr");
}
public void endFunction() throws SAXPathException
{
System.out.println("End Function");
}
public void endMultiplicativeExpr(int arg0) throws SAXPathException
{
System.out.println("End Multiplicative Expr: value = " + arg0);
}
public void endNameStep() throws SAXPathException
{
System.out.println("End Name Step");
}
public void endOrExpr(boolean arg0) throws SAXPathException
{
System.out.println("End Or Expr: value = " + arg0);
}
public void endPathExpr() throws SAXPathException
{
System.out.println("End Path Expression");
}
public void endPredicate() throws SAXPathException
{
System.out.println("End Predicate");
}
public void endProcessingInstructionNodeStep() throws SAXPathException
{
System.out.println("End Processing Instruction Node Step");
}
public void endRelationalExpr(int arg0) throws SAXPathException
{
System.out.println("End Relational Expr: value = " + arg0);
}
public void endRelativeLocationPath() throws SAXPathException
{
System.out.println("End Relative Location Path");
}
public void endTextNodeStep() throws SAXPathException
{
System.out.println("End Text Node Step");
}
public void endUnaryExpr(int arg0) throws SAXPathException
{
System.out.println("End Unary Expr: value = " + arg0);
}
public void endUnionExpr(boolean arg0) throws SAXPathException
{
System.out.println("End Union Expr: value = " + arg0);
}
public void endXPath() throws SAXPathException
{
System.out.println("End XPath");
}
public void literal(String arg0) throws SAXPathException
{
System.out.println("Literal = " + arg0);
}
public void number(double arg0) throws SAXPathException
{
System.out.println("Double = " + arg0);
}
public void number(int arg0) throws SAXPathException
{
System.out.println("Integer = " + arg0);
}
public void startAbsoluteLocationPath() throws SAXPathException
{
System.out.println("Start Absolute Location Path");
}
public void startAdditiveExpr() throws SAXPathException
{
System.out.println("Start Additive Expression");
}
public void startAllNodeStep(int arg0) throws SAXPathException
{
System.out.println("Start All Node Exp: Axis = " + Axis.lookup(arg0));
}
public void startAndExpr() throws SAXPathException
{
System.out.println("Start AndExpression");
}
public void startCommentNodeStep(int arg0) throws SAXPathException
{
System.out.println("Start Comment Node Step");
}
public void startEqualityExpr() throws SAXPathException
{
System.out.println("Start Equality Expression");
}
public void startFilterExpr() throws SAXPathException
{
System.out.println("Start Filter Expression");
}
public void startFunction(String arg0, String arg1) throws SAXPathException
{
System.out.println("Start Function arg0 = < " + arg0 + " > arg1 = < " + arg1 + " >");
}
public void startMultiplicativeExpr() throws SAXPathException
{
System.out.println("Start Multiplicative Expression");
}
public void startNameStep(int arg0, String arg1, String arg2) throws SAXPathException
{
System.out.println("Start Name Step Axis = <" + Axis.lookup(arg0) + " > arg1 = < " + arg1 + " > arg 2 <" + arg2
+ " >");
}
public void startOrExpr() throws SAXPathException
{
System.out.println("Start Or Expression");
}
public void startPathExpr() throws SAXPathException
{
System.out.println("Start Path Expression");
}
public void startPredicate() throws SAXPathException
{
System.out.println("Start Predicate");
}
public void startProcessingInstructionNodeStep(int arg0, String arg1) throws SAXPathException
{
System.out.println("Start Processing INstruction Node Step = < " + arg0 + " > arg1 = < " + arg1 + " >");
}
public void startRelationalExpr() throws SAXPathException
{
System.out.println("Start Relationship Expression");
}
public void startRelativeLocationPath() throws SAXPathException
{
System.out.println("Start Relative Location Path");
}
public void startTextNodeStep(int arg0) throws SAXPathException
{
System.out.println("Start Text Node Step: value = " + arg0);
}
public void startUnaryExpr() throws SAXPathException
{
System.out.println("Start Unary Expression");
}
public void startUnionExpr() throws SAXPathException
{
System.out.println("Start Union Expression");
}
public void startXPath() throws SAXPathException
{
System.out.println("Start XPath");
}
public void variableReference(String arg0, String arg1) throws SAXPathException
{
System.out.println("Variable Reference arg0 = < " + arg0 + " > arg1 = < " + arg1);
}
/**
* @param args String[]
* @throws SAXPathException
*/
public static void main(String[] args) throws SAXPathException
{
XPathReader reader = new XPathReader();
reader.setXPathHandler(new DebugXPathHandler());
reader
.parse("/ns:one[@woof='dog']/two/./../two[functionTest(@a, @b, $woof:woof)]/three/*/four//*/five/six[@exists1 and @exists2]");
}
}

View File

@@ -1,395 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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/>.
* #L%
*/
package org.alfresco.repo.search.impl.lucene;
import java.io.IOException;
import java.util.Set;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.alfresco.error.AlfrescoRuntimeException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.FilterIndexReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.index.TermDocs;
import org.apache.lucene.index.TermEnum;
import org.apache.lucene.index.TermPositions;
import org.apache.lucene.search.Hits;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Searcher;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.util.OpenBitSet;
/**
* An index reader that filters documents from another.
*
* @author andyh
*
*/
public class FilterIndexReaderByStringId extends FilterIndexReader
{
private static Log s_logger = LogFactory.getLog(FilterIndexReaderByStringId.class);
private OpenBitSet deletedDocuments;
private final Set<String> deletions;
private final Set<String> containerDeletions;
private final boolean deleteNodesOnly;
private final ReadWriteLock lock = new ReentrantReadWriteLock();
private final String id;
/**
* Apply the filter
*
* @param id String
* @param reader IndexReader
* @param deleteNodesOnly boolean
*/
public FilterIndexReaderByStringId(String id, IndexReader reader, Set<String> deletions, Set<String> containerDeletions, boolean deleteNodesOnly)
{
super(reader);
reader.incRef();
this.id = id;
this.deletions = deletions;
this.containerDeletions = containerDeletions;
this.deleteNodesOnly = deleteNodesOnly;
if (s_logger.isDebugEnabled())
{
s_logger.debug("Applying deletions FOR "+id +" (the index ito which these are applied is the previous one ...)");
}
}
public OpenBitSet getDeletedDocuments()
{
lock.readLock().lock();
try
{
if (deletedDocuments != null)
{
return deletedDocuments;
}
}
finally
{
lock.readLock().unlock();
}
lock.writeLock().lock();
try
{
if (deletedDocuments != null)
{
return deletedDocuments;
}
deletedDocuments = new OpenBitSet(in.maxDoc());
Searcher searcher = new IndexSearcher(in);
for (String stringRef : deletions)
{
if (!deleteNodesOnly || containerDeletions.contains(stringRef))
{
TermDocs td = in.termDocs(new Term("ID", stringRef));
while (td.next())
{
deletedDocuments.set(td.doc());
}
td.close();
}
else
{
boolean found = false;
TermDocs td = in.termDocs(new Term("LEAFID", stringRef));
while (td.next())
{
deletedDocuments.set(td.doc());
found = true;
}
td.close();
// For backward compatibility, use old method of locating non-container docs
if (!found)
{
TermQuery query = new TermQuery(new Term("ID", stringRef));
Hits hits = searcher.search(query);
if (hits.length() > 0)
{
for (int i = 0; i < hits.length(); i++)
{
Document doc = hits.doc(i);
// Exclude all containers except the root (which is also a node!)
Field path = doc.getField("PATH");
if (path == null || path.stringValue().length() == 0)
{
deletedDocuments.set(hits.id(i));
// There should only be one thing to delete
// break;
}
}
}
}
}
}
// searcher does not need to be closed, the reader is live
for (String stringRef : containerDeletions)
{
TermDocs td = in.termDocs(new Term("ANCESTOR", stringRef));
while (td.next())
{
deletedDocuments.set(td.doc());
}
td.close();
}
return deletedDocuments;
}
catch (IOException e)
{
s_logger.error("Error initialising "+id, e);
throw new AlfrescoRuntimeException("Failed to find deleted documents to filter", e);
}
finally
{
lock.writeLock().unlock();
}
}
// Prevent from actually setting the closed flag
@Override
protected void doClose() throws IOException
{
this.in.decRef();
}
/**
* Filter implementation
*
* @author andyh
*
*/
public class FilterTermDocs implements TermDocs
{
protected TermDocs in;
String id;
/**
* @param id String
* @param in TermDocs
*/
public FilterTermDocs(String id, TermDocs in)
{
this.in = in;
}
public void seek(Term term) throws IOException
{
// Seek is left to the base implementation
in.seek(term);
}
public void seek(TermEnum termEnum) throws IOException
{
// Seek is left to the base implementation
in.seek(termEnum);
}
public int doc()
{
// The current document info is valid in the base implementation
return in.doc();
}
public int freq()
{
// The frequency is valid in the base implementation
return in.freq();
}
public boolean next() throws IOException
{
try
{
if (!in.next())
{
return false;
}
OpenBitSet deletedDocuments = getDeletedDocuments();
while (deletedDocuments.get(in.doc()))
{
if (!in.next())
{
return false;
}
}
// Not masked
return true;
}
catch(IOException ioe)
{
s_logger.error("Error reading docs for "+id);
throw ioe;
}
}
public int read(int[] docs, int[] freqs) throws IOException
{
int[] innerDocs = new int[docs.length];
int[] innerFreq = new int[docs.length];
int count = in.read(innerDocs, innerFreq);
// Is the stream exhausted
if (count == 0)
{
return 0;
}
OpenBitSet deletedDocuments = getDeletedDocuments();
while (allDeleted(innerDocs, count, deletedDocuments))
{
count = in.read(innerDocs, innerFreq);
// Is the stream exhausted
if (count == 0)
{
return 0;
}
}
// Add non deleted
int insertPosition = 0;
for (int i = 0; i < count; i++)
{
if (!deletedDocuments.get(innerDocs[i]))
{
docs[insertPosition] = innerDocs[i];
freqs[insertPosition] = innerFreq[i];
insertPosition++;
}
}
return insertPosition;
}
private boolean allDeleted(int[] docs, int fillSize, OpenBitSet deletedDocuments)
{
for (int i = 0; i < fillSize; i++)
{
if (!deletedDocuments.get(docs[i]))
{
return false;
}
}
return true;
}
public boolean skipTo(int i) throws IOException
{
if (!in.skipTo(i))
{
return false;
}
OpenBitSet deletedDocuments = getDeletedDocuments();
while (deletedDocuments.get(in.doc()))
{
if (!in.next())
{
return false;
}
}
return true;
}
public void close() throws IOException
{
// Leave to internal implementation
in.close();
}
}
/** Base class for filtering {@code TermPositions} implementations. */
public class FilterTermPositions extends FilterTermDocs implements TermPositions
{
TermPositions tp;
/**
* @param id String
* @param in TermPositions
*/
public FilterTermPositions(String id, TermPositions in)
{
super(id, in);
tp = in;
}
public int nextPosition() throws IOException
{
return tp.nextPosition();
}
public byte[] getPayload(byte[] data, int offset) throws IOException
{
return tp.getPayload(data, offset);
}
public int getPayloadLength()
{
return tp.getPayloadLength();
}
public boolean isPayloadAvailable()
{
return tp.isPayloadAvailable();
}
}
@Override
public int numDocs()
{
return super.numDocs() - (int)getDeletedDocuments().cardinality();
}
@Override
public TermDocs termDocs() throws IOException
{
return new FilterTermDocs(id, super.termDocs());
}
@Override
public TermPositions termPositions() throws IOException
{
return new FilterTermPositions(id, super.termPositions());
}
}

View File

@@ -1,39 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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/>.
* #L%
*/
package org.alfresco.repo.search.impl.lucene;
/**
* Alfresco FTS Query language support
*
* @author andyh
*/
public class LuceneAlfrescoFtsQueryLanguage extends AbstractAlfrescoFtsQueryLanguage
{
public LuceneAlfrescoFtsQueryLanguage()
{
this.setName("index.fts");
}
}

View File

@@ -1,68 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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/>.
* #L%
*/
package org.alfresco.repo.search.impl.lucene;
import org.alfresco.opencmis.search.CMISQueryOptions;
import org.alfresco.opencmis.search.CMISQueryOptions.CMISQueryMode;
import org.alfresco.opencmis.search.CMISQueryService;
import org.alfresco.opencmis.search.CMISResultSetMetaData;
import org.alfresco.opencmis.search.CMISResultSetRow;
import org.alfresco.repo.search.results.ResultSetSPIWrapper;
import org.alfresco.service.cmr.search.ResultSet;
import org.alfresco.service.cmr.search.SearchParameters;
import org.alfresco.service.cmr.search.SearchService;
/**
* Support for sql-cmis-strict in the search service
* @author andyh
*
*/
public class LuceneAlfrescoSqlQueryLanguage extends AbstractLuceneQueryLanguage
{
private CMISQueryService cmisQueryService;
public LuceneAlfrescoSqlQueryLanguage()
{
this.setName(SearchService.LANGUAGE_CMIS_ALFRESCO);
}
/**
* Set the search service
*
* @param cmisQueryService CMISQueryService
*/
public void setCmisQueryService(CMISQueryService cmisQueryService)
{
this.cmisQueryService = cmisQueryService;
}
public ResultSet executeQuery(SearchParameters searchParameters)
{
CMISQueryOptions options = CMISQueryOptions.create(searchParameters);
options.setQueryMode(CMISQueryMode.CMS_WITH_ALFRESCO_EXTENSIONS);
return new ResultSetSPIWrapper<CMISResultSetRow, CMISResultSetMetaData>(cmisQueryService.query(options));
}
}

View File

@@ -1,68 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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/>.
* #L%
*/
package org.alfresco.repo.search.impl.lucene;
import org.alfresco.opencmis.search.CMISQueryOptions;
import org.alfresco.opencmis.search.CMISQueryOptions.CMISQueryMode;
import org.alfresco.opencmis.search.CMISQueryService;
import org.alfresco.opencmis.search.CMISResultSetMetaData;
import org.alfresco.opencmis.search.CMISResultSetRow;
import org.alfresco.repo.search.results.ResultSetSPIWrapper;
import org.alfresco.service.cmr.search.ResultSet;
import org.alfresco.service.cmr.search.SearchParameters;
import org.alfresco.service.cmr.search.SearchService;
/**
* Support for Alfresco SQL in the search service
* @author andyh
*
*/
public class LuceneCmisStrictSqlQueryLanguage extends AbstractLuceneQueryLanguage
{
private CMISQueryService cmisQueryService;
public LuceneCmisStrictSqlQueryLanguage()
{
this.setName(SearchService.LANGUAGE_CMIS_STRICT);
}
/**
* Set the search service
*
* @param cmisQueryService CMISQueryService
*/
public void setCmisQueryService(CMISQueryService cmisQueryService)
{
this.cmisQueryService = cmisQueryService;
}
public ResultSet executeQuery(SearchParameters searchParameters)
{
CMISQueryOptions options = CMISQueryOptions.create(searchParameters);
options.setQueryMode(CMISQueryMode.CMS_STRICT);
return new ResultSetSPIWrapper<CMISResultSetRow, CMISResultSetMetaData>(cmisQueryService.query(options));
}
}

View File

@@ -1,54 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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/>.
* #L%
*/
package org.alfresco.repo.search.impl.lucene;
import org.alfresco.repo.search.IndexerException;
/**
* Exceptions relating to indexing within the lucene implementation
*
* @author andyh
*
*/
public class LuceneIndexException extends IndexerException
{
/**
*
*/
private static final long serialVersionUID = 3688505480817422645L;
public LuceneIndexException(String message, Throwable cause)
{
super(message, cause);
}
public LuceneIndexException(String message)
{
super(message);
}
}

View File

@@ -1,44 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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/>.
* #L%
*/
package org.alfresco.repo.search.impl.lucene;
import java.util.Set;
import org.alfresco.repo.search.Indexer;
import org.alfresco.repo.search.TransactionSynchronisationAwareIndexer;
import org.alfresco.repo.search.impl.lucene.index.IndexInfo;
/**
* @author Andy Hind
*/
public interface LuceneIndexer extends Indexer, TransactionSynchronisationAwareIndexer
{
public String getDeltaId();
public Set<String> getDeletions();
public Set<String> getContainerDeletions();
public boolean getDeleteOnlyNodes();
public <R> R doReadOnly(IndexInfo.LockWork <R> lockWork);
}

View File

@@ -1,67 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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/>.
* #L%
*/
package org.alfresco.repo.search.impl.lucene;
import org.alfresco.opencmis.search.CMISQueryOptions;
import org.alfresco.opencmis.search.CMISQueryOptions.CMISQueryMode;
import org.alfresco.opencmis.search.CMISQueryService;
import org.alfresco.opencmis.search.CMISResultSetMetaData;
import org.alfresco.opencmis.search.CMISResultSetRow;
import org.alfresco.repo.search.results.ResultSetSPIWrapper;
import org.alfresco.service.cmr.search.ResultSet;
import org.alfresco.service.cmr.search.SearchParameters;
/**
* Support for sql-cmis-strict in the search service
*
* @author andyh
*/
public class LuceneOpenCMISAlfrescoSqlQueryLanguage extends AbstractLuceneQueryLanguage
{
private CMISQueryService cmisQueryService;
public LuceneOpenCMISAlfrescoSqlQueryLanguage()
{
this.setName("index.cmis.alfresco");
}
/**
* Set the search service
*
* @param cmisQueryService CMISQueryService
*/
public void setCmisQueryService(CMISQueryService cmisQueryService)
{
this.cmisQueryService = cmisQueryService;
}
public ResultSet executeQuery(SearchParameters searchParameters)
{
CMISQueryOptions options = CMISQueryOptions.create(searchParameters);
options.setQueryMode(CMISQueryMode.CMS_WITH_ALFRESCO_EXTENSIONS);
return new ResultSetSPIWrapper<CMISResultSetRow, CMISResultSetMetaData>(cmisQueryService.query(options));
}
}

View File

@@ -1,68 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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/>.
* #L%
*/
package org.alfresco.repo.search.impl.lucene;
import org.alfresco.opencmis.search.CMISQueryOptions;
import org.alfresco.opencmis.search.CMISQueryOptions.CMISQueryMode;
import org.alfresco.opencmis.search.CMISQueryService;
import org.alfresco.opencmis.search.CMISResultSetMetaData;
import org.alfresco.opencmis.search.CMISResultSetRow;
import org.alfresco.repo.search.results.ResultSetSPIWrapper;
import org.alfresco.service.cmr.search.ResultSet;
import org.alfresco.service.cmr.search.SearchParameters;
import org.alfresco.service.cmr.search.SearchService;
/**
* Support for Alfresco SQL in the search service
*
* @author andyh
*/
public class LuceneOpenCMISStrictSqlQueryLanguage extends AbstractLuceneQueryLanguage
{
private CMISQueryService cmisQueryService;
public LuceneOpenCMISStrictSqlQueryLanguage()
{
this.setName(SearchService.LANGUAGE_CMIS_STRICT);
}
/**
* Set the search service
*
* @param cmisQueryService CMISQueryService
*/
public void setCmisQueryService(CMISQueryService cmisQueryService)
{
this.cmisQueryService = cmisQueryService;
}
public ResultSet executeQuery(SearchParameters searchParameters)
{
CMISQueryOptions options = CMISQueryOptions.create(searchParameters);
options.setQueryMode(CMISQueryMode.CMS_STRICT);
return new ResultSetSPIWrapper<CMISResultSetRow, CMISResultSetMetaData>(cmisQueryService.query(options));
}
}

View File

@@ -1,355 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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/>.
* #L%
*/
package org.alfresco.repo.search.impl.lucene;
import java.io.IOException;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.List;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.node.NodeBulkLoader;
import org.alfresco.repo.search.AbstractResultSet;
import org.alfresco.repo.search.ResultSetRowIterator;
import org.alfresco.repo.search.SearcherException;
import org.alfresco.repo.search.SimpleResultSetMetaData;
import org.alfresco.repo.search.impl.lucene.index.CachingIndexReader;
import org.alfresco.repo.tenant.TenantService;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.search.LimitBy;
import org.alfresco.service.cmr.search.PermissionEvaluationMode;
import org.alfresco.service.cmr.search.ResultSetMetaData;
import org.alfresco.service.cmr.search.ResultSetRow;
import org.alfresco.service.cmr.search.SearchParameters;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.search.Hits;
import org.apache.lucene.search.Searcher;
/**
* Implementation of a ResultSet on top of Lucene Hits class.
*
* @author andyh
*/
public class LuceneResultSet extends AbstractResultSet
{
private static int DEFAULT_BULK_FETCH_SIZE = 1000;
/**
* The underlying hits
*/
Hits hits;
private Searcher searcher;
private NodeService nodeService;
private TenantService tenantService;
private SearchParameters searchParameters;
private LuceneConfig config;
private BitSet prefetch;
private boolean bulkFetch = true;
private int bulkFetchSize = DEFAULT_BULK_FETCH_SIZE;
/**
* Wrap a lucene seach result with node support
*
* @param hits Hits
* @param searcher Searcher
* @param nodeService nodeService
* @param tenantService tenant service
* @param searchParameters SearchParameters
* @param config - lucene config
*/
public LuceneResultSet(Hits hits, Searcher searcher, NodeService nodeService, TenantService tenantService, SearchParameters searchParameters,
LuceneConfig config)
{
super();
this.hits = hits;
this.searcher = searcher;
this.nodeService = nodeService;
this.tenantService = tenantService;
this.searchParameters = searchParameters;
this.config = config;
prefetch = new BitSet(hits.length());
}
/*
* ResultSet implementation
*/
public ResultSetRowIterator iterator()
{
return new LuceneResultSetRowIterator(this);
}
public int length()
{
return hits.length();
}
public NodeRef getNodeRef(int n)
{
try
{
prefetch(n);
// We have to get the document to resolve this
// It is possible the store ref is also stored in the index
if (searcher instanceof ClosingIndexSearcher)
{
ClosingIndexSearcher cis = (ClosingIndexSearcher) searcher;
IndexReader reader = cis.getReader();
if (reader instanceof CachingIndexReader)
{
int id = hits.id(n);
CachingIndexReader cir = (CachingIndexReader) reader;
String sid = cir.getId(id);
return tenantService.getBaseName(new NodeRef(sid));
}
}
Document doc = hits.doc(n);
String id = doc.get("ID");
return tenantService.getBaseName(new NodeRef(id));
}
catch (IOException e)
{
throw new SearcherException("IO Error reading reading node ref from the result set", e);
}
}
public float getScore(int n) throws SearcherException
{
try
{
return hits.score(n);
}
catch (IOException e)
{
throw new SearcherException("IO Error reading score from the result set", e);
}
}
public Document getDocument(int n)
{
try
{
prefetch(n);
Document doc = hits.doc(n);
return doc;
}
catch (IOException e)
{
throw new SearcherException("IO Error reading reading document from the result set", e);
}
}
private void prefetch(int n) throws IOException
{
NodeBulkLoader bulkLoader = config.getBulkLoader();
if (!getBulkFetch() || (bulkLoader == null))
{
// No prefetching
return;
}
if (prefetch.get(n))
{
// The document was already processed
return;
}
// Start at 'n' and process the the next bulk set
int bulkFetchSize = getBulkFetchSize();
List<NodeRef> fetchList = new ArrayList<NodeRef>(bulkFetchSize);
int totalHits = hits.length();
for (int i = 0; i < bulkFetchSize; i++)
{
int next = n + i;
if (next >= totalHits)
{
// We've hit the end
break;
}
if (prefetch.get(next))
{
// This one is in there already
continue;
}
// We store the node and mark it as prefetched
prefetch.set(next);
Document doc = hits.doc(next);
String nodeRefStr = doc.get("ID");
try
{
NodeRef nodeRef = tenantService.getBaseName(new NodeRef(nodeRefStr));
fetchList.add(nodeRef);
}
catch (AlfrescoRuntimeException e)
{
// Ignore IDs that don't parse as NodeRefs, e.g. FTSREF docs
}
}
// Now bulk fetch
if (fetchList.size() > 1)
{
bulkLoader.cacheNodes(fetchList);
}
}
public void close()
{
try
{
searcher.close();
}
catch (IOException e)
{
throw new SearcherException(e);
}
}
public NodeService getNodeService()
{
return nodeService;
}
public ResultSetRow getRow(int i)
{
if (i < length())
{
return new LuceneResultSetRow(this, i);
}
else
{
throw new SearcherException("Invalid row");
}
}
public ChildAssociationRef getChildAssocRef(int n)
{
return tenantService.getBaseName(getRow(n).getChildAssocRef());
}
public ResultSetMetaData getResultSetMetaData()
{
return new SimpleResultSetMetaData(LimitBy.UNLIMITED, PermissionEvaluationMode.EAGER, searchParameters);
}
public int getStart()
{
throw new UnsupportedOperationException();
}
public boolean hasMore()
{
throw new UnsupportedOperationException();
}
public TenantService getTenantService()
{
return tenantService;
}
/**
* Bulk fetch results in the cache
*
* @param bulkFetch boolean
*/
@Override
public boolean setBulkFetch(boolean bulkFetch)
{
boolean oldBulkFetch = this.bulkFetch;
this.bulkFetch = bulkFetch;
return oldBulkFetch;
}
/**
* Do we bulk fetch
*
* @return - true if we do
*/
@Override
public boolean getBulkFetch()
{
return bulkFetch;
}
/**
* Set the bulk fetch size
*
* @param bulkFetchSize int
*/
@Override
public int setBulkFetchSize(int bulkFetchSize)
{
int oldBulkFetchSize = this.bulkFetchSize;
this.bulkFetchSize = bulkFetchSize;
return oldBulkFetchSize;
}
/**
* Get the bulk fetch size.
*
* @return the fetch size
*/
@Override
public int getBulkFetchSize()
{
return bulkFetchSize;
}
/**
* @param index int
* @return int
*/
public int doc(int index)
{
try
{
return hits.id(index);
}
catch (IOException e)
{
throw new SearcherException(e);
}
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.search.ResultSetSPI#getNumberFound()
*/
@Override
public long getNumberFound()
{
return hits.length();
}
}

View File

@@ -1,166 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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/>.
* #L%
*/
package org.alfresco.repo.search.impl.lucene;
import java.io.Serializable;
import java.util.Map;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.search.AbstractResultSetRow;
import org.alfresco.repo.tenant.TenantService;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
/**
* A row in a result set. Created on the fly.
*
* @author Andy Hind
*
*/
public class LuceneResultSetRow extends AbstractResultSetRow
{
/**
* The current document - cached so we do not get it for each value
*/
private Document document;
private TenantService tenantService;
/**
* Wrap a position in a lucene Hits class with node support
*
* @param resultSet LuceneResultSet
* @param index int
*/
public LuceneResultSetRow(LuceneResultSet resultSet, int index)
{
super(resultSet, index);
tenantService = resultSet.getTenantService();
}
/**
* Support to cache the document for this row
*
* @return Document
*/
public Document getDocument()
{
if (document == null)
{
document = ((LuceneResultSet) getResultSet()).getDocument(getIndex());
}
return document;
}
/*
* ResultSetRow implementation
*/
protected Map<QName, Serializable> getDirectProperties()
{
LuceneResultSet lrs = (LuceneResultSet) getResultSet();
return lrs.getNodeService().getProperties(lrs.getNodeRef(getIndex()));
}
public QName getQName()
{
Field field = getDocument().getField("QNAME");
if (field != null)
{
String qname = field.stringValue();
if((qname == null) || (qname.length() == 0))
{
return null;
}
else
{
return QName.createQName(qname);
}
}
else
{
return null;
}
}
public QName getPrimaryAssocTypeQName()
{
Field field = getDocument().getField("PRIMARYASSOCTYPEQNAME");
if (field != null)
{
String qname = field.stringValue();
return QName.createQName(qname);
}
else
{
return ContentModel.ASSOC_CHILDREN;
}
}
@Override
public ChildAssociationRef getChildAssocRef()
{
Field field = getDocument().getField("PRIMARYPARENT");
String primaryParent = null;
if (field != null)
{
primaryParent = field.stringValue();
}
NodeRef childNodeRef = getNodeRef();
NodeRef parentNodeRef = primaryParent == null ? null : tenantService.getBaseName(new NodeRef(primaryParent));
return new ChildAssociationRef(getPrimaryAssocTypeQName(), parentNodeRef, getQName(), childNodeRef);
}
public NodeRef getNodeRef(String selectorName)
{
throw new UnsupportedOperationException();
}
public Map<String, NodeRef> getNodeRefs()
{
throw new UnsupportedOperationException();
}
public float getScore(String selectorName)
{
throw new UnsupportedOperationException();
}
public Map<String, Float> getScores()
{
throw new UnsupportedOperationException();
}
public int doc()
{
return ((LuceneResultSet)getResultSet()).doc(getIndex());
}
}

View File

@@ -1,59 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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/>.
* #L%
*/
package org.alfresco.repo.search.impl.lucene;
import org.alfresco.repo.search.AbstractResultSetRowIterator;
import org.alfresco.service.cmr.search.ResultSetRow;
/**
* Iterate over the rows in a LuceneResultSet
*
* @author andyh
*
*/
public class LuceneResultSetRowIterator extends AbstractResultSetRowIterator
{
/**
* Create an iterator over the result set. Follows standard ListIterator
* conventions
*
* @param resultSet LuceneResultSet
*/
public LuceneResultSetRowIterator(LuceneResultSet resultSet)
{
super(resultSet);
}
public ResultSetRow next()
{
return new LuceneResultSetRow((LuceneResultSet)getResultSet(), moveToNextPosition());
}
public ResultSetRow previous()
{
return new LuceneResultSetRow((LuceneResultSet)getResultSet(), moveToPreviousPosition());
}
}

View File

@@ -1,72 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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/>.
* #L%
*/
package org.alfresco.repo.search.impl.lucene;
import java.util.List;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.namespace.NamespacePrefixResolver;
import org.alfresco.util.Pair;
/**
* Lucene implementation specific entension to the seracher API
* @author andyh
*
*/
public interface LuceneSearcher extends SearchService
{
/**
* Check if the index exists
* @return - true if it exists
*/
public boolean indexExists();
/**
* Ste the node service
* @param nodeService NodeService
*/
public void setNodeService(NodeService nodeService);
/**
* Set the name space service
* @param namespacePrefixResolver NamespacePrefixResolver
*/
public void setNamespacePrefixResolver(NamespacePrefixResolver namespacePrefixResolver);
/**
* Get top terms
*
* @param field String
* @param count int
* @return List
*/
public List<Pair<String, Integer>> getTopTerms(String field, int count);
/**
* Get a lucene searcher
* @return ClosingIndexSearcher
*/
public ClosingIndexSearcher getClosingIndexSearcher();
}

View File

@@ -1,171 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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/>.
* #L%
*/
package org.alfresco.repo.search.impl.lucene.index;
/**
* Describes an entry in an index
*
* @author Andy Hind
*/
class IndexEntry
{
/**
* The type of the index entry
*/
private IndexType type;
/**
* The unique name of the index entry
*/
private String name;
/**
* The preceeding index name.
* Allows deltas etc to apply to the index or an overlay for example.
*/
private String parentName;
/**
* The status of the index entry
*/
private TransactionStatus status;
/**
* If merging, the id where the result is going
*/
private String mergeId;
private long documentCount;
private long deletions;
private boolean deletOnlyNodes;
IndexEntry(IndexType type, String name, String parentName, TransactionStatus status, String mergeId, long documentCount, long deletions, boolean deletOnlyNodes)
{
this.type = type;
this.name = name;
this.parentName = parentName;
this.status = status;
this.mergeId = mergeId;
this.documentCount = documentCount;
this.deletions = deletions;
this.deletOnlyNodes = deletOnlyNodes;
}
public String getMergeId()
{
return mergeId;
}
public void setMergeId(String mergeId)
{
this.mergeId = mergeId;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getParentName()
{
return parentName;
}
public void setParentName(String parentName)
{
this.parentName = parentName;
}
public TransactionStatus getStatus()
{
return status;
}
public void setStatus(TransactionStatus status)
{
this.status = status;
}
public IndexType getType()
{
return type;
}
public void setType(IndexType type)
{
this.type = type;
}
public long getDocumentCount()
{
return documentCount;
}
public void setDocumentCount(long documentCount)
{
this.documentCount = documentCount;
}
public long getDeletions()
{
return deletions;
}
public void setDeletions(long deletions)
{
this.deletions = deletions;
}
public boolean isDeletOnlyNodes()
{
return deletOnlyNodes;
}
public void setDeletOnlyNodes(boolean deletOnlyNodes)
{
this.deletOnlyNodes = deletOnlyNodes;
}
public String toString()
{
StringBuilder builder = new StringBuilder();
builder.append(" Name=").append(getName()).append(" ");
builder.append("Type=").append(getType()).append(" ");
builder.append("Status=").append(getStatus()).append(" ");
builder.append("Docs=").append(getDocumentCount()).append(" ");
builder.append("Deletions=").append(getDeletions()).append(" ");
return builder.toString();
}
}

View File

@@ -1,94 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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/>.
* #L%
*/
package org.alfresco.repo.search.impl.lucene.index;
import org.springframework.context.ApplicationEvent;
/**
* A class of event that notifies the listener of a significant event relating to a Lucene index. Useful for Monitoring
* purposes.
*
* @author dward
*/
public class IndexEvent extends ApplicationEvent
{
private static final long serialVersionUID = -4616231785087405506L;
/** The event description. */
private final String description;
/** Its instance count. */
private final int count;
/**
* The Constructor.
*
* @param source
* the source index monitor
* @param description
* the event description
* @param count
* its instance count
*/
public IndexEvent(IndexMonitor source, String description, int count)
{
super(source);
this.description = description;
this.count = count;
}
/**
* Gets the source index monitor.
*
* @return the index monitor
*/
public IndexMonitor getIndexMonitor()
{
return (IndexMonitor) getSource();
}
/**
* Gets the event description.
*
* @return the description
*/
public String getDescription()
{
return this.description;
}
/**
* Gets the event instance count.
*
* @return the count
*/
public int getCount()
{
return this.count;
}
}

View File

@@ -1,108 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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/>.
* #L%
*/
package org.alfresco.repo.search.impl.lucene.index;
import java.io.IOException;
import java.util.Map;
import org.springframework.context.ApplicationListener;
/**
* An interface that exposes information about a Lucene Index and that allows registration of a listener for event
* notifications.
*
* @author dward
*/
public interface IndexMonitor
{
/**
* Gets the relative path of the index directory.
*
* @return the relative path
*/
public String getRelativePath();
/**
* Gets a snapshot of the statuses of the individual entries in this index.
*
* @return a map of entry status names to entry counts
*/
public Map<String, Integer> getStatusSnapshot();
/**
* Gets the actual size of the index in bytes.
*
* @return the actual size in bytes
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public long getActualSize() throws IOException;
/**
* Gets the size used on disk by the index directory. A large discrepancy from the value returned by
* {@link #getActualSize()} may indicate that there are unused data files.
*
* @return the size on disk in bytes
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public long getUsedSize() throws IOException;
/**
* Gets the number of documents in the index.
*
* @return the number of documents
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public int getNumberOfDocuments() throws IOException;
/**
* Gets the number of fields known to the index.
*
* @return the number of fields
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public int getNumberOfFields() throws IOException;
/**
* Gets the number of indexed fields.
*
* @return the number of indexed fields
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public int getNumberOfIndexedFields() throws IOException;
/**
* Registers a listener for events on this index.
*
* @param listener
* the listener
*/
public void addApplicationListener(ApplicationListener listener);
}

View File

@@ -1,55 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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/>.
* #L%
*/
package org.alfresco.repo.search.impl.lucene.index;
/**
* The type of an entry in this index.
*
* @author Andy Hind
*/
public enum IndexType
{
/**
* Identifies the main index. This is always a fully optimised index.
*/
INDEX,
/**
* An overlay. This is an optimised index with a deletion list. To commit an overlay requires no deletions against other indexes. Deletions are done when an overlay turns
* into or is merged into a index. Overlays are periodically merged into an index. An overlay can require or have background properties indexed.
*/
DELTA,
/**
* A long running overlay definition against the index. Not yet supported.
* This, itself, may have transactional additions.
*/
OVERLAY,
OVERLAY_DELTA;
}

View File

@@ -1,69 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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/>.
* #L%
*/
package org.alfresco.repo.search.impl.lucene.index;
import java.io.IOException;
import java.util.Deque;
/**
* Reference counting and caching for read only index access.
*
* When this object is invalid for reuse and all referees have gone the implementation should release all
* resources held (release the caches, close the index readers etc)
*
* @author andyh
*
*/
public interface ReferenceCounting
{
public long getCreationTime();
public Deque<Throwable> getReferences();
/**
* Get the number of references
* @return int
*/
public int getReferenceCount();
/**
* Mark is invalid for reuse.
* @throws IOException
*/
public void setInvalidForReuse() throws IOException;
/**
* Determine if valid for reuse
* @return boolean
*/
public boolean isInvalidForReuse();
/**
* Get the id for this reader.
* @return String
*/
public String getId();
}

View File

@@ -1,752 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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/>.
* #L%
*/
package org.alfresco.repo.search.impl.lucene.index;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Deque;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Timer;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.search.impl.lucene.LuceneConfig;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.FieldSelector;
import org.apache.lucene.document.FieldSelectorResult;
import org.apache.lucene.document.Field.Index;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.index.FilterIndexReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.index.TermDocs;
import org.apache.lucene.index.TermEnum;
import org.apache.lucene.util.OpenBitSet;
public class ReferenceCountingReadOnlyIndexReaderFactory
{
private static Log s_logger = LogFactory.getLog(ReferenceCountingReadOnlyIndexReaderFactory.class);
private static WeakHashMap<String, ReferenceCountingReadOnlyIndexReader> log = new WeakHashMap<String, ReferenceCountingReadOnlyIndexReader>();
public static IndexReader createReader(String id, IndexReader indexReader, boolean enableCaching, LuceneConfig config)
{
ReferenceCountingReadOnlyIndexReader rc = new ReferenceCountingReadOnlyIndexReader(id, indexReader, enableCaching, config);
if (s_logger.isDebugEnabled())
{
if (log.containsKey(id))
{
s_logger.debug("Replacing ref counting reader for " + id);
}
s_logger.debug("Created ref counting reader for " + id + " " + rc.toString());
log.put(new String(id), rc); // Copy the key because the RCROIR references the ID
}
return rc;
}
public static void destroy()
{
log.clear();
}
public static String getState(String id)
{
if (s_logger.isDebugEnabled())
{
ReferenceCountingReadOnlyIndexReader rc = log.get(id);
if (rc != null)
{
StringBuilder builder = new StringBuilder();
builder.append("Id = " + rc.getId() + " Invalid = " + rc.getReferenceCount() + " invalid = " + rc.getInvalidForReuse() + " closed=" + rc.getClosed());
return builder.toString();
}
}
return ("<UNKNOWN>");
}
public static class ReferenceCountingReadOnlyIndexReader extends FilterIndexReader implements ReferenceCounting, CachingIndexReader
{
private static Log s_logger = LogFactory.getLog(ReferenceCountingReadOnlyIndexReader.class);
private static final long serialVersionUID = 7693185658022810428L;
private static java.lang.reflect.Field s_field;
String id;
int refCount = 0;
boolean invalidForReuse = false;
boolean allowsDeletions;
boolean wrapper_closed = false;
ConcurrentHashMap<Integer, Boolean> isCategory = new ConcurrentHashMap<Integer, Boolean>();
ConcurrentHashMap<Integer, WithUseCount<List<Field>>> documentCache = new ConcurrentHashMap<Integer, WithUseCount<List<Field>>>();
ConcurrentHashMap<Integer, WithUseCount<List<Field>>> idCache = new ConcurrentHashMap<Integer, WithUseCount<List<Field>>>();
ConcurrentHashMap<Integer, WithUseCount<Field>> pathCache = new ConcurrentHashMap<Integer, WithUseCount<Field>>();
ConcurrentHashMap<Integer, WithUseCount<Field>> typeCache = new ConcurrentHashMap<Integer, WithUseCount<Field>>();
ConcurrentHashMap<Integer, WithUseCount<List<Field>>> parentCache = new ConcurrentHashMap<Integer, WithUseCount<List<Field>>>();
ConcurrentHashMap<Integer, WithUseCount<List<Field>>> linkAspectCache = new ConcurrentHashMap<Integer, WithUseCount<List<Field>>>();
private boolean enableCaching;
private LuceneConfig config;
private final long creationTime;
private final Deque<Throwable> references;
static
{
Class<IndexReader> c = IndexReader.class;
try
{
s_field = c.getDeclaredField("closed");
s_field.setAccessible(true);
}
catch (SecurityException e)
{
throw new AlfrescoRuntimeException("Reference counting index reader needs access to org.apache.lucene.index.IndexReader.closed to work correctly", e);
}
catch (NoSuchFieldException e)
{
throw new AlfrescoRuntimeException(
"Reference counting index reader needs access to org.apache.lucene.index.IndexReader.closed to work correctly (incompatible version of lucene)", e);
}
}
ReferenceCountingReadOnlyIndexReader(String id, IndexReader indexReader, boolean enableCaching, LuceneConfig config)
{
super(indexReader);
this.creationTime = System.currentTimeMillis();
this.references = new LinkedList<Throwable>();
references.add(new Exception(this.refCount + ": " + indexReader.toString()));
this.id = id;
if (enableCaching && (config != null))
{
this.enableCaching = config.isCacheEnabled();
}
this.config = config;
}
@Override
public synchronized long getCreationTime()
{
return this.creationTime;
}
@Override
public synchronized Deque<Throwable> getReferences()
{
return this.references;
}
@Override
public synchronized void incRef()
{
if (wrapper_closed)
{
throw new IllegalStateException(Thread.currentThread().getName() + "Indexer is closed " + id);
}
if (refCount++ > 0)
{
super.incRef();
}
if (s_logger.isDebugEnabled())
{
s_logger.debug(Thread.currentThread().getName() + ": Reader " + id + " - increment - ref count is " + refCount + " ... " + super.toString());
}
if (!wrapper_closed)
{
try
{
s_field.set(this, false);
}
catch (IllegalArgumentException e)
{
throw new AlfrescoRuntimeException("Failed to mark index as open ..", e);
}
catch (IllegalAccessException e)
{
throw new AlfrescoRuntimeException("Failed to mark index as open ..", e);
}
}
references.add(new Exception(this.refCount + ": " + in.toString()));
}
private synchronized void decrementReferenceCount() throws IOException
{
refCount--;
if (s_logger.isDebugEnabled())
{
s_logger.debug(Thread.currentThread().getName() + ": Reader " + id + " - decrement - ref count is " + refCount + " ... " + super.toString());
}
closeIfRequired();
if (refCount < 0)
{
s_logger.error("Invalid reference count for Reader " + id + " is " + refCount + " ... " + super.toString());
}
}
private void closeIfRequired() throws IOException
{
if ((refCount == 0) && invalidForReuse && !wrapper_closed)
{
if (s_logger.isDebugEnabled())
{
s_logger.debug(Thread.currentThread().getName() + ": Reader " + id + " closed." + " ... " + super.toString());
}
if (enableCaching)
{
// No tidy up
}
// Pass on the last decRef
super.decRef();
wrapper_closed = true;
if (!references.isEmpty())
{
references.removeLast();
}
}
else
{
if (s_logger.isDebugEnabled())
{
s_logger.debug(Thread.currentThread().getName()
+ ": Reader " + id + " still open .... ref = " + refCount + " invalidForReuse = " + invalidForReuse + " ... " + super.toString());
}
}
}
public synchronized int getReferenceCount()
{
return refCount;
}
public synchronized boolean getInvalidForReuse()
{
return invalidForReuse;
}
public synchronized boolean getClosed()
{
return wrapper_closed;
}
public synchronized void setInvalidForReuse() throws IOException
{
if (wrapper_closed)
{
throw new IllegalStateException(Thread.currentThread().getName() + "Indexer is closed " + id);
}
invalidForReuse = true;
if (s_logger.isDebugEnabled())
{
s_logger.debug(Thread.currentThread().getName() + ": Reader " + id + " set invalid for reuse" + " ... " + super.toString());
}
closeIfRequired();
}
@Override
public synchronized void decRef() throws IOException
{
if (s_logger.isDebugEnabled())
{
s_logger.debug(Thread.currentThread().getName() + ": Reader " + id + " closing" + " ... " + super.toString());
}
if (wrapper_closed)
{
throw new IllegalStateException(Thread.currentThread().getName() + "Indexer is closed " + id);
}
decrementReferenceCount();
if (refCount > 0)
{
super.decRef();
if (!references.isEmpty())
{
references.removeLast();
}
}
}
/**
* We want to avoid setting the closed flag on our wrapped stream, passing on all decrefs.
**/
@Override
protected void doClose() throws IOException
{
in.decRef();
}
@Override
protected void doDelete(int n) throws IOException
{
throw new UnsupportedOperationException("Delete is not supported by read only index readers");
}
private interface Accessor<T>
{
T get(int n, FieldSelector fieldSelector) throws IOException;
}
private class ListFieldAccessor implements Accessor<List<Field>>
{
public List<Field> get(int n, FieldSelector fieldSelector) throws IOException
{
Document document = ReferenceCountingReadOnlyIndexReader.super.document(n, fieldSelector);
List<Field> fields = (List<Field>) document.getFields();
ArrayList<Field> cacheable = new ArrayList<Field>(fields.size());
cacheable.addAll(fields);
return cacheable;
}
}
private class MultipleValueFieldAccessor implements Accessor<List<Field>>
{
String fieldName;
MultipleValueFieldAccessor(String fieldName)
{
this.fieldName = fieldName;
}
public List<Field> get(int n, FieldSelector fieldSelector) throws IOException
{
Document document = ReferenceCountingReadOnlyIndexReader.super.document(n, fieldSelector);
Field[] fields = document.getFields(fieldName);
ArrayList<Field> cacheable = new ArrayList<Field>(fields.length);
for (Field field : fields)
{
cacheable.add(field);
}
return cacheable;
}
}
private class SingleValueFieldAccessor implements Accessor<Field>
{
String fieldName;
SingleValueFieldAccessor(String fieldName)
{
this.fieldName = fieldName;
}
public Field get(int n, FieldSelector fieldSelector) throws IOException
{
return new Field(fieldName, getStringValue(n, fieldName), Store.NO, Index.UN_TOKENIZED);
}
}
private final ListFieldAccessor LIST_FIELD_ACCESSOR = new ListFieldAccessor();
private final MultipleValueFieldAccessor MV_ID_FIELD_ACCESSOR = new MultipleValueFieldAccessor("ID");
private final SingleValueFieldAccessor SV_TYPE_FIELD_ACCESSOR = new SingleValueFieldAccessor("TYPE");
private final SingleValueFieldAccessor SV_PATH_FIELD_ACCESSOR = new SingleValueFieldAccessor("PATH");
private final MultipleValueFieldAccessor MV_PARENT_FIELD_ACCESSOR = new MultipleValueFieldAccessor("PARENT");
private final MultipleValueFieldAccessor MV_LINKASPECT_FIELD_ACCESSOR = new MultipleValueFieldAccessor("LINKASPECT");
private OpenBitSet nodes = null;
private <T> T manageCache(ConcurrentHashMap<Integer, WithUseCount<T>> cache, Accessor<T> accessor, int n, FieldSelector fieldSelector, int limit) throws IOException
{
Integer key = Integer.valueOf(n);
WithUseCount<T> value = cache.get(key);
if (value == null)
{
T made = accessor.get(n, fieldSelector);
value = new WithUseCount<T>(made, n);
cache.put(key, value);
// resize
if (limit >= 0)
{
if (cache.size() >= limit)
{
HashMap<Integer, WithUseCount<T>> keep = new HashMap<Integer, WithUseCount<T>>();
WithUseCount<T>[] existing = new WithUseCount[0];
synchronized (cache)
{
existing = cache.values().toArray(existing);
cache.clear();
}
Arrays.sort(existing);
for (WithUseCount<T> current : existing)
{
keep.put(Integer.valueOf(current.doc), current);
if ((current.count.get() == 0) || (keep.size() > (limit / 4)))
{
break;
}
}
keep.put(key, value);
cache.putAll(keep);
}
}
}
else
{
value.count.getAndIncrement();
}
return value.object;
}
@SuppressWarnings("unchecked")
public Document document(int n, FieldSelector fieldSelector) throws IOException
{
if ((fieldSelector == null) && enableCaching)
{
List<Field> listOfFields = manageCache(documentCache, LIST_FIELD_ACCESSOR, n, fieldSelector, config.getMaxDocumentCacheSize());
Document document = new Document();
document.getFields().addAll(listOfFields);
return document;
}
else
{
if (enableCaching && (fieldSelector instanceof SingleFieldSelector))
{
SingleFieldSelector sfs = (SingleFieldSelector) fieldSelector;
if (sfs.field.equals("ID") && !sfs.last)
{
List<Field> idFields = manageCache(idCache, MV_ID_FIELD_ACCESSOR, n, fieldSelector, config.getMaxDocIdCacheSize());
Document d = new Document();
d.getFields().addAll(idFields);
return d;
}
if (sfs.field.equals("ISCATEGORY") && sfs.last)
{
Integer key = Integer.valueOf(n);
Boolean isCat = isCategory.get(key);
if (isCat == null)
{
isCat = (getStringValue(n, "ISCATEGORY") != null);
isCategory.put(key, isCat);
}
Document d = new Document();
if (isCat)
{
d.add(new Field("ISCATEGORY", "T", Store.NO, Index.UN_TOKENIZED));
}
return d;
}
if (sfs.field.equals("PATH") && sfs.last)
{
Field pathField = manageCache(pathCache, SV_PATH_FIELD_ACCESSOR, n, fieldSelector, config.getMaxPathCacheSize());
Document d = new Document();
d.add(pathField);
return d;
}
if (sfs.field.equals("TYPE") && sfs.last)
{
Field typeField = manageCache(typeCache, SV_TYPE_FIELD_ACCESSOR, n, fieldSelector, config.getMaxTypeCacheSize());
Document d = new Document();
d.add(typeField);
return d;
}
if (sfs.field.equals("PARENT") && !sfs.last)
{
List<Field> listOfFields = manageCache(parentCache, MV_PARENT_FIELD_ACCESSOR, n, fieldSelector, config.getMaxParentCacheSize());
Document document = new Document();
document.getFields().addAll(listOfFields);
return document;
}
if (sfs.field.equals("LINKASPECT") && !sfs.last)
{
List<Field> listOfFields = manageCache(linkAspectCache, MV_LINKASPECT_FIELD_ACCESSOR, n, fieldSelector, config.getMaxLinkAspectCacheSize());
Document document = new Document();
document.getFields().addAll(listOfFields);
return document;
}
}
}
return super.document(n, fieldSelector);
}
public String getId()
{
return id;
}
public boolean isInvalidForReuse()
{
return invalidForReuse;
}
public String getId(int n) throws IOException
{
Document d = document(n, new SingleFieldSelector("ID", true));
return d.getField("ID").stringValue();
}
public String getPathLinkId(int n) throws IOException
{
Document document = document(n, new SingleFieldSelector("ID", true));
Field[] fields = document.getFields("ID");
Field field = fields[fields.length - 1];
return (field == null) ? null : field.stringValue();
}
public String[] getIds(int n) throws IOException
{
return getStringValues(n, "ID");
}
public String[] getLinkAspects(int n) throws IOException
{
// return getStringValues(n, "LINKASPECT");
Document d = document(n, new SingleFieldSelector("LINKASPECT", false));
return d.getValues("LINKASPECT");
}
public String[] getParents(int n) throws IOException
{
// return getStringValues(n, "PARENT");
Document d = document(n, new SingleFieldSelector("PARENT", false));
return d.getValues("PARENT");
}
public String getPath(int n) throws IOException
{
// return getStringValue(n, "PATH");
Document d = document(n, new SingleFieldSelector("PATH", true));
Field f = d.getField("PATH");
return f == null ? null : f.stringValue();
}
public String getType(int n) throws IOException
{
// return getStringValue(n, "TYPE");
Document d = document(n, new SingleFieldSelector("TYPE", true));
Field f = d.getField("TYPE");
return f == null ? null : f.stringValue();
}
public String getIsCategory(int n) throws IOException
{
Document d = document(n, new SingleFieldSelector("ISCATEGORY", true));
Field f = d.getField("ISCATEGORY");
return f == null ? null : f.stringValue();
}
// private String getLastStringValue(int n, String fieldName) throws IOException
// {
// Document document = document(n);
// Field[] fields = document.getFields(fieldName);
// Field field = fields[fields.length - 1];
// return (field == null) ? null : field.stringValue();
// }
private String getStringValue(int n, String fieldName) throws IOException
{
Document document = document(n);
Field field = document.getField(fieldName);
return (field == null) ? null : field.stringValue();
}
@SuppressWarnings("unchecked")
private String[] getStringValues(int n, String fieldName) throws IOException
{
Document document = document(n);
ArrayList<Field> fields = new ArrayList<Field>();
ArrayList<String> answer = new ArrayList<String>(2);
fields.addAll((List<Field>) document.getFields());
for (Field field : fields)
{
if (field.name().equals(fieldName))
{
answer.add(field.stringValue());
}
}
return answer.toArray(new String[answer.size()]);
}
public synchronized TermDocs getNodeDocs() throws IOException
{
if (nodes == null)
{
TermDocs nodeDocs = termDocs(new Term("ISNODE", "T"));
nodes = new OpenBitSet();
while (nodeDocs.next())
{
nodes.set(nodeDocs.doc());
}
nodeDocs.close();
}
return new TermDocSet(nodes);
}
}
static class WithUseCount<T> implements Comparable<WithUseCount<T>>
{
AtomicInteger count = new AtomicInteger(0);
T object;
int doc;
WithUseCount(T object, int doc)
{
this.object = object;
this.doc = doc;
}
public int compareTo(WithUseCount<T> other)
{
return other.count.get() - this.count.get();
}
}
private static class SingleFieldSelector implements FieldSelector
{
String field;
boolean last;
SingleFieldSelector(String field, boolean last)
{
this.field = field;
this.last = last;
}
public FieldSelectorResult accept(String fieldName)
{
if (fieldName.equals(field))
{
return FieldSelectorResult.LOAD;
}
else
{
return FieldSelectorResult.NO_LOAD;
}
}
}
static class TermDocSet implements TermDocs
{
OpenBitSet set;
int position = -1;
TermDocSet(OpenBitSet set)
{
this.set = set;
}
public void close() throws IOException
{
// Noop
}
public int doc()
{
return position;
}
public int freq()
{
return 1;
}
public boolean next() throws IOException
{
position++;
position = set.nextSetBit(position);
return (position != -1);
}
public int read(int[] docs, int[] freqs) throws IOException
{
throw new UnsupportedOperationException();
}
public void seek(Term term) throws IOException
{
throw new UnsupportedOperationException();
}
public void seek(TermEnum termEnum) throws IOException
{
throw new UnsupportedOperationException();
}
public boolean skipTo(int target) throws IOException
{
do
{
if (!next())
{
return false;
}
}
while (target > doc());
return true;
}
}
}

View File

@@ -1,533 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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/>.
* #L%
*/
package org.alfresco.repo.search.impl.lucene.index;
import javax.transaction.Status;
/**
* Status of indexes that make up the whole index. This starts with the value from javax.transaction.Status.
*
* Lifecycle ---------
*
* As a transaction starts, the delta is ACTIVE It may be MARKED_ROLLBACK -> ROLLED BACK -> PREPARING -> PREPARED -> COMMITTING -> COMMITTED... with roll back at any time
*
* If the index has any delayed indexing it commits to COMMITTED_REQUIRES_REINDEX and then the overlay can go from -> COMMITTED_REINDEXING -> COMMITTED_REINDEXED
*
* If there was no reindexing required the delat commits as COMMITTED
*
* A delta changes to an index overlay as it is committed.
*
* For an overlay in COMMITTED or COMMITTED_REINDEXED it can have its delete list applied to sub indexes. At this point it becomes a sub index.
*
* @author Andy Hind
*/
public enum TransactionStatus
{
/**
* Active TX
*/
ACTIVE
{
public boolean isCommitted()
{
return false;
}
public boolean isTransient()
{
return true;
}
public boolean canBeReordered()
{
return true;
}
public boolean follows(TransactionStatus previous)
{
return (previous == null) || (previous == ACTIVE);
}
public int getStatus()
{
return Status.STATUS_ACTIVE;
}
},
/**
* TX marked for rollback
*/
MARKED_ROLLBACK
{
public boolean isCommitted()
{
return false;
}
public boolean isTransient()
{
return true;
}
public boolean canBeReordered()
{
return true;
}
public boolean follows(TransactionStatus previous)
{
return previous.allowsRollbackOrMark(previous) || (previous == MARKED_ROLLBACK);
}
public int getStatus()
{
return Status.STATUS_MARKED_ROLLBACK;
}
},
/**
* TX prepared
*/
PREPARED
{
public boolean isCommitted()
{
return false;
}
public boolean isTransient()
{
return false;
}
public boolean canBeReordered()
{
return false;
}
public boolean follows(TransactionStatus previous)
{
return (previous == TransactionStatus.PREPARING) || (previous == PREPARED);
}
public int getStatus()
{
return Status.STATUS_PREPARED;
}
},
/**
* TX Committed
*/
COMMITTED
{
public boolean isCommitted()
{
return true;
}
public boolean isTransient()
{
return false;
}
public boolean canBeReordered()
{
return false;
}
public boolean follows(TransactionStatus previous)
{
return (previous == TransactionStatus.COMMITTING) || (previous == COMMITTED);
}
public int getStatus()
{
return Status.STATUS_COMMITTED;
}
},
/**
* TX rolled back
*/
ROLLEDBACK
{
public boolean isCommitted()
{
return false;
}
public boolean isTransient()
{
return true;
}
public boolean canBeReordered()
{
return true;
}
public boolean follows(TransactionStatus previous)
{
return (previous == TransactionStatus.ROLLINGBACK) || (previous == ROLLEDBACK);
}
public int getStatus()
{
return Status.STATUS_ROLLEDBACK;
}
},
/**
* TX state is unknown
*/
UNKNOWN
{
public boolean isCommitted()
{
return false;
}
public boolean isTransient()
{
return true;
}
public boolean canBeReordered()
{
return true;
}
public boolean follows(TransactionStatus previous)
{
return (previous == UNKNOWN);
}
public int getStatus()
{
return Status.STATUS_UNKNOWN;
}
},
/**
* No transaction
*/
NO_TRANSACTION
{
public boolean isCommitted()
{
return false;
}
public boolean isTransient()
{
return true;
}
public boolean canBeReordered()
{
return true;
}
public boolean follows(TransactionStatus previous)
{
return (previous == NO_TRANSACTION);
}
public int getStatus()
{
return Status.STATUS_NO_TRANSACTION;
}
},
/**
* TX is preparing
*/
PREPARING
{
public boolean isCommitted()
{
return false;
}
public boolean isTransient()
{
return true;
}
public boolean canBeReordered()
{
return true;
}
public boolean follows(TransactionStatus previous)
{
return (previous == TransactionStatus.ACTIVE) || (previous == PREPARING);
}
public int getStatus()
{
return Status.STATUS_PREPARING;
}
},
/**
* TX is committing
*/
COMMITTING
{
public boolean isCommitted()
{
return false;
}
public boolean isTransient()
{
return true;
}
public boolean canBeReordered()
{
return false;
}
public boolean follows(TransactionStatus previous)
{
return (previous == TransactionStatus.PREPARED) || (previous == COMMITTING);
}
public int getStatus()
{
return Status.STATUS_COMMITTING;
}
},
/**
* TX rolling back
*/
ROLLINGBACK
{
public boolean isCommitted()
{
return false;
}
public boolean isTransient()
{
return true;
}
public boolean canBeReordered()
{
return true;
}
public boolean follows(TransactionStatus previous)
{
return previous.allowsRollbackOrMark(previous) || (previous == ROLLINGBACK);
}
public int getStatus()
{
return Status.STATUS_ROLLING_BACK;
}
},
/**
* This entry is the source for an active merge. The result will be in a new index.
*/
MERGE
{
public boolean isCommitted()
{
return true;
}
public boolean isTransient()
{
return false;
}
public boolean canBeReordered()
{
return false;
}
public boolean follows(TransactionStatus previous)
{
return (previous == MERGE);
}
public int getStatus()
{
return Status.STATUS_COMMITTED;
}
},
/**
* A new index element that is being made by a merge.
*/
MERGE_TARGET
{
public boolean isCommitted()
{
return false;
}
public boolean isTransient()
{
return false;
}
public boolean canBeReordered()
{
return false;
}
public boolean follows(TransactionStatus previous)
{
return (previous == MERGE_TARGET);
}
public int getStatus()
{
return Status.STATUS_ACTIVE;
}
},
/**
* Pending deleted are being committed to for the delta.
*/
COMMITTED_DELETING
{
public boolean isCommitted()
{
return true;
}
public boolean isTransient()
{
return false;
}
public boolean canBeReordered()
{
return false;
}
public boolean follows(TransactionStatus previous)
{
return (previous == COMMITTED_DELETING);
}
public int getStatus()
{
return Status.STATUS_COMMITTED;
}
},
/**
* An entry that may be deleted
*/
DELETABLE
{
public boolean isCommitted()
{
return false;
}
public boolean isTransient()
{
return false;
}
public boolean canBeReordered()
{
return false;
}
public boolean follows(TransactionStatus previous)
{
return true;
}
public int getStatus()
{
return Status.STATUS_UNKNOWN;
}
};
/**
* Is this a commited inex entry?
* @return - true if committed
*/
public abstract boolean isCommitted();
/**
* Is this transient
* @return - true if no information needs to be persisted
*/
public abstract boolean isTransient();
/**
* Can this be reordered with respect to other TXs
* @return - true if this can be reordered (fixed after prepare)
*/
public abstract boolean canBeReordered();
/**
* Can this state follow the one given?
* @param previous state
* @return - true if transition to this state is allowed
*/
public abstract boolean follows(TransactionStatus previous);
/**
* Get the javax.transaction.Status best matching this state
*
* @return - the int TX state
*/
public abstract int getStatus();
private boolean allowsRollbackOrMark(TransactionStatus previous)
{
switch (previous)
{
case ACTIVE:
case MARKED_ROLLBACK:
case PREPARED:
case PREPARING:
case COMMITTING:
return true;
default:
return false;
}
}
}

View File

@@ -23,28 +23,28 @@
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.search.impl.noindex;
import java.util.Collections;
import java.util.List;
import org.alfresco.repo.search.impl.lucene.LuceneCategoryServiceImpl;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.Pair;
/**
* @author Andy
*
*/
public class NoIndexCategoryServiceImpl extends LuceneCategoryServiceImpl
{
@Override
public List<Pair<NodeRef, Integer>> getTopCategories(StoreRef storeRef, QName aspectName, int count)
{
return Collections.<Pair<NodeRef, Integer>>emptyList();
}
}
package org.alfresco.repo.search.impl.noindex;
import java.util.Collections;
import java.util.List;
import org.alfresco.repo.search.impl.AbstractCategoryServiceImpl;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.Pair;
/**
* @author Andy
*
*/
public class NoIndexCategoryServiceImpl extends AbstractCategoryServiceImpl
{
@Override
public List<Pair<NodeRef, Integer>> getTopCategories(StoreRef storeRef, QName aspectName, int count)
{
return Collections.<Pair<NodeRef, Integer>>emptyList();
}
}

View File

@@ -1,300 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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/>.
* #L%
*/
package org.alfresco.repo.search.impl.querymodel.impl.lucene;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import org.alfresco.repo.search.SearcherException;
import org.alfresco.repo.search.impl.lucene.ClosingIndexSearcher;
import org.alfresco.repo.search.impl.lucene.LuceneIndexerAndSearcher;
import org.alfresco.repo.search.impl.lucene.LuceneResultSet;
import org.alfresco.repo.search.impl.lucene.LuceneSearcher;
import org.alfresco.repo.search.impl.lucene.PagingLuceneResultSet;
import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext;
import org.alfresco.repo.search.impl.querymodel.Query;
import org.alfresco.repo.search.impl.querymodel.QueryEngine;
import org.alfresco.repo.search.impl.querymodel.QueryEngineResults;
import org.alfresco.repo.search.impl.querymodel.QueryModelFactory;
import org.alfresco.repo.search.impl.querymodel.QueryOptions;
import org.alfresco.repo.search.results.SortedResultSet;
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.LimitBy;
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.namespace.NamespaceService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.search.Hits;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.SortField;
/**
* @author andyh
*/
@SuppressWarnings("deprecation")
public class LuceneQueryEngine implements QueryEngine
{
protected static final Log logger = LogFactory.getLog(LuceneQueryEngine.class);
private DictionaryService dictionaryService;
private LuceneIndexerAndSearcher indexAndSearcher;
private NodeService nodeService;
private TenantService tenantService;
private NamespaceService namespaceService;
private boolean useInMemorySort = true;
private int maxRawResultSetSizeForInMemorySort = 1000;
/**
* @param dictionaryService
* the dictionaryService to set
*/
public void setDictionaryService(DictionaryService dictionaryService)
{
this.dictionaryService = dictionaryService;
}
/**
* @param indexAndSearcher
* the indexAndSearcher to set
*/
public void setIndexAndSearcher(LuceneIndexerAndSearcher indexAndSearcher)
{
this.indexAndSearcher = indexAndSearcher;
}
/**
* @param nodeService
* the nodeService to set
*/
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
/**
* @param tenantService
* the tenantService to set
*/
public void setTenantService(TenantService tenantService)
{
this.tenantService = tenantService;
}
/**
* @param namespaceService
* the namespaceService to set
*/
public void setNamespaceService(NamespaceService namespaceService)
{
this.namespaceService = namespaceService;
}
public QueryModelFactory getQueryModelFactory()
{
return new LuceneQueryModelFactory<org.apache.lucene.search.Query, Sort, ParseException>();
}
/**
* @return the useInMemorySort
*/
public boolean isUseInMemorySort()
{
return useInMemorySort;
}
/**
* @param useInMemorySort the useInMemorySort to set
*/
public void setUseInMemorySort(boolean useInMemorySort)
{
this.useInMemorySort = useInMemorySort;
}
/**
* @return the maxRawResultSetSizeForInMemorySort
*/
public int getMaxRawResultSetSizeForInMemorySort()
{
return maxRawResultSetSizeForInMemorySort;
}
/**
* @param maxRawResultSetSizeForInMemorySort the maxRawResultSetSizeForInMemorySort to set
*/
public void setMaxRawResultSetSizeForInMemorySort(int maxRawResultSetSizeForInMemorySort)
{
this.maxRawResultSetSizeForInMemorySort = maxRawResultSetSizeForInMemorySort;
}
public QueryEngineResults executeQuery(Query query, QueryOptions options, FunctionEvaluationContext functionContext)
{
Set<String> selectorGroup = null;
if (query.getSource() != null)
{
List<Set<String>> selectorGroups = query.getSource().getSelectorGroups(functionContext);
if (selectorGroups.size() == 0)
{
throw new UnsupportedOperationException("No selectors");
}
if (selectorGroups.size() > 1)
{
throw new UnsupportedOperationException("Advanced join is not supported");
}
selectorGroup = selectorGroups.get(0);
}
SearchParameters searchParameters = new SearchParameters();
if(options.getLocales().size() > 0)
{
for(Locale locale: options.getLocales())
{
searchParameters.addLocale(locale);
}
}
searchParameters.excludeDataInTheCurrentTransaction(!options.isIncludeInTransactionData());
searchParameters.setSkipCount(options.getSkipCount());
searchParameters.setMaxPermissionChecks(options.getMaxPermissionChecks());
searchParameters.setMaxPermissionCheckTimeMillis(options.getMaxPermissionCheckTimeMillis());
searchParameters.setDefaultFieldName(options.getDefaultFieldName());
searchParameters.setMlAnalaysisMode(options.getMlAnalaysisMode());
if (options.getMaxItems() >= 0)
{
searchParameters.setLimitBy(LimitBy.FINAL_SIZE);
searchParameters.setLimit(options.getMaxItems());
searchParameters.setMaxItems(options.getMaxItems());
}
else
{
searchParameters.setLimitBy(LimitBy.UNLIMITED);
}
searchParameters.setUseInMemorySort(options.getUseInMemorySort());
searchParameters.setMaxRawResultSetSizeForInMemorySort(options.getMaxRawResultSetSizeForInMemorySort());
searchParameters.setBulkFetchEnabled(options.isBulkFetchEnabled());
searchParameters.setQueryConsistency(options.getQueryConsistency());
try
{
StoreRef storeRef = options.getStores().get(0);
searchParameters.addStore(storeRef);
if (query instanceof LuceneQueryBuilder)
{
SearchService searchService = indexAndSearcher.getSearcher(storeRef, options.isIncludeInTransactionData());
if (searchService instanceof LuceneSearcher)
{
LuceneSearcher luceneSearcher = (LuceneSearcher) searchService;
ClosingIndexSearcher searcher = luceneSearcher.getClosingIndexSearcher();
LuceneQueryBuilderContext<org.apache.lucene.search.Query, Sort, ParseException> luceneContext = new LuceneQueryBuilderContextImpl(dictionaryService, namespaceService, tenantService, searchParameters, indexAndSearcher.getDefaultMLSearchAnalysisMode(),
searcher.getIndexReader());
@SuppressWarnings("unchecked")
LuceneQueryBuilder<org.apache.lucene.search.Query, Sort, ParseException> builder = (LuceneQueryBuilder<org.apache.lucene.search.Query, Sort, ParseException>) query;
org.apache.lucene.search.Query luceneQuery = builder.buildQuery(selectorGroup, luceneContext, functionContext);
if(logger.isDebugEnabled())
{
logger.debug("Executing lucene query: "+luceneQuery);
}
Sort sort = builder.buildSort(selectorGroup, luceneContext, functionContext);
Hits hits = searcher.search(luceneQuery);
boolean postSort = false;;
if(sort != null)
{
postSort = searchParameters.usePostSort(hits.length(), useInMemorySort, maxRawResultSetSizeForInMemorySort);
if(postSort == false)
{
hits = searcher.search(luceneQuery, sort);
}
}
ResultSet answer;
ResultSet result = new LuceneResultSet(hits, searcher, nodeService, tenantService, searchParameters, indexAndSearcher);
if(postSort)
{
if(sort != null)
{
for(SortField sf : sort.getSort())
{
searchParameters.addSort(sf.getField(), !sf.getReverse());
}
}
ResultSet sorted = new SortedResultSet(result, nodeService, builder.buildSortDefinitions(selectorGroup, luceneContext, functionContext), namespaceService, dictionaryService, searchParameters.getSortLocale());
answer = sorted;
}
else
{
answer = result;
}
ResultSet rs = new PagingLuceneResultSet(answer, searchParameters, nodeService);
Map<Set<String>, ResultSet> map = new HashMap<Set<String>, ResultSet>(1);
map.put(selectorGroup, rs);
return new QueryEngineResults(map);
}
else
{
throw new UnsupportedOperationException();
}
}
else
{
throw new UnsupportedOperationException();
}
}
catch (ParseException e)
{
throw new SearcherException("Failed to parse query: " + e);
}
catch (IOException e)
{
throw new SearcherException("IO exception during search", e);
}
}
}

View File

@@ -34,7 +34,7 @@ import java.io.UnsupportedEncodingException;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.search.impl.lucene.LuceneQueryParserException;
import org.alfresco.repo.search.QueryParserException;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
@@ -83,7 +83,7 @@ public abstract class AbstractSolrAdminHTTPClient
}
if (get.getStatusCode() != HttpServletResponse.SC_OK)
{
throw new LuceneQueryParserException("Request failed " + get.getStatusCode() + " " + url.toString());
throw new QueryParserException("Request failed " + get.getStatusCode() + " " + url.toString());
}
Reader reader = new BufferedReader(new InputStreamReader(get.getResponseBodyAsStream(), get.getResponseCharSet()));

View File

@@ -33,7 +33,7 @@ import java.io.UnsupportedEncodingException;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.repo.search.impl.lucene.LuceneQueryParserException;
import org.alfresco.repo.search.QueryParserException;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
@@ -105,7 +105,7 @@ public abstract class AbstractSolrQueryHTTPClient
}
if (post.getStatusCode() != HttpServletResponse.SC_OK)
{
throw new LuceneQueryParserException("Request failed " + post.getStatusCode() + " " + url.toString());
throw new QueryParserException("Request failed " + post.getStatusCode() + " " + url.toString());
}
Reader reader = new BufferedReader(new InputStreamReader(post.getResponseBodyAsStream(), post.getResponseCharSet()));

Some files were not shown because too many files have changed in this diff Show More