diff --git a/config/alfresco/content-services-context.xml b/config/alfresco/content-services-context.xml index 67dd4d0d3c..a04badb9ac 100644 --- a/config/alfresco/content-services-context.xml +++ b/config/alfresco/content-services-context.xml @@ -99,6 +99,9 @@ + + ${policy.content.update.ignoreEmpty} + diff --git a/config/alfresco/repository.properties b/config/alfresco/repository.properties index c5c3a25253..895f0989cf 100644 --- a/config/alfresco/repository.properties +++ b/config/alfresco/repository.properties @@ -377,6 +377,11 @@ repo.remote.endpoint=/service # Create home folders as people are created (true) or create them lazily (false) home.folder.creation.eager=true +# Should we consider zero byte content to be the same as no content when firing +# content update policies? Prevents 'premature' firing of inbound content rules +# for some clients such as Mac OS X Finder +policy.content.update.ignoreEmpty=false + # The well known RMI registry port is defined in the alfresco-shared.properties file # host will need to be changed from localhost to make the services available to other # computers. diff --git a/source/java/org/alfresco/cmis/search/CMISQueryServiceImpl.java b/source/java/org/alfresco/cmis/search/CMISQueryServiceImpl.java index 6dc270f4ae..fbbcc79adb 100644 --- a/source/java/org/alfresco/cmis/search/CMISQueryServiceImpl.java +++ b/source/java/org/alfresco/cmis/search/CMISQueryServiceImpl.java @@ -36,6 +36,7 @@ import org.alfresco.repo.search.impl.querymodel.QueryEngine; import org.alfresco.repo.search.impl.querymodel.QueryEngineResults; import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.search.LimitBy; import org.alfresco.service.cmr.search.ResultSet; /** @@ -135,7 +136,12 @@ public class CMISQueryServiceImpl implements CMISQueryService wrapped.put(selector, current); } } - CMISResultSet cmis = new CMISResultSetImpl(wrapped, options, nodeService, query, cmisDictionaryService, alfrescoDictionaryService); + 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 CMISResultSetImpl(wrapped, options, limitBy, nodeService, query, cmisDictionaryService, alfrescoDictionaryService); return cmis; } diff --git a/source/java/org/alfresco/cmis/search/CMISResultSetImpl.java b/source/java/org/alfresco/cmis/search/CMISResultSetImpl.java index b3da974f2e..9a2e8921a8 100644 --- a/source/java/org/alfresco/cmis/search/CMISResultSetImpl.java +++ b/source/java/org/alfresco/cmis/search/CMISResultSetImpl.java @@ -37,6 +37,7 @@ import org.alfresco.service.cmr.dictionary.DictionaryService; 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.ResultSet; import org.alfresco.service.cmr.search.ResultSetRow; @@ -48,6 +49,8 @@ public class CMISResultSetImpl implements CMISResultSet, Serializable private static final long serialVersionUID = 2014688399588268994L; private Map wrapped; + + private LimitBy limitBy; CMISQueryOptions options; @@ -59,11 +62,12 @@ public class CMISResultSetImpl implements CMISResultSet, Serializable DictionaryService alfrescoDictionaryService; - public CMISResultSetImpl(Map wrapped, CMISQueryOptions options, NodeService nodeService, Query query, CMISDictionaryService cmisDictionaryService, - DictionaryService alfrescoDictionaryService) + public CMISResultSetImpl(Map wrapped, CMISQueryOptions options, LimitBy limitBy, NodeService nodeService, Query query, + CMISDictionaryService cmisDictionaryService, DictionaryService alfrescoDictionaryService) { this.wrapped = wrapped; this.options = options; + this.limitBy = limitBy; this.nodeService = nodeService; this.query = query; this.cmisDictionaryService = cmisDictionaryService; @@ -94,7 +98,7 @@ public class CMISResultSetImpl implements CMISResultSet, Serializable */ public CMISResultSetMetaData getMetaData() { - return new CMISResultSetMetaDataImpl(options, query, cmisDictionaryService, alfrescoDictionaryService); + return new CMISResultSetMetaDataImpl(options, query, limitBy, cmisDictionaryService, alfrescoDictionaryService); } /* diff --git a/source/java/org/alfresco/cmis/search/CMISResultSetMetaDataImpl.java b/source/java/org/alfresco/cmis/search/CMISResultSetMetaDataImpl.java index a709c39b4b..e2223d1dd0 100644 --- a/source/java/org/alfresco/cmis/search/CMISResultSetMetaDataImpl.java +++ b/source/java/org/alfresco/cmis/search/CMISResultSetMetaDataImpl.java @@ -49,16 +49,18 @@ public class CMISResultSetMetaDataImpl implements CMISResultSetMetaData { private CMISQueryOptions options; private SearchParameters searchParams; + private LimitBy limitBy; private Map columnMetaData; private Map selectorMetaData; - public CMISResultSetMetaDataImpl(CMISQueryOptions options, Query query, CMISDictionaryService cmisDictionaryService, DictionaryService alfrescoDictionaryService) + public CMISResultSetMetaDataImpl(CMISQueryOptions options, Query query, LimitBy limitBy, CMISDictionaryService cmisDictionaryService, + DictionaryService alfrescoDictionaryService) { this.options = options; this.searchParams = new SearchParameters(options); - + this.limitBy = limitBy; Map selectors = query.getSource().getSelectors(); selectorMetaData = new LinkedHashMap(); for(Selector selector : selectors.values()) @@ -177,7 +179,7 @@ public class CMISResultSetMetaDataImpl implements CMISResultSetMetaData public LimitBy getLimitedBy() { - throw new UnsupportedOperationException(); + return limitBy; } public PermissionEvaluationMode getPermissionEvaluationMode() diff --git a/source/java/org/alfresco/repo/content/ContentServiceImpl.java b/source/java/org/alfresco/repo/content/ContentServiceImpl.java index 1ac48bd755..6cdf598e8b 100644 --- a/source/java/org/alfresco/repo/content/ContentServiceImpl.java +++ b/source/java/org/alfresco/repo/content/ContentServiceImpl.java @@ -96,6 +96,8 @@ public class ContentServiceImpl implements ContentService, ApplicationContextAwa /** the store for all temporarily created content */ private ContentStore tempStore; private ContentTransformer imageMagickContentTransformer; + /** Should we consider zero byte content to be the same as no content? */ + private boolean ignoreEmptyContent; /** * The policy component @@ -153,8 +155,12 @@ public class ContentServiceImpl implements ContentService, ApplicationContextAwa { this.imageMagickContentTransformer = imageMagickContentTransformer; } - - + + public void setIgnoreEmptyContent(boolean ignoreEmptyContent) + { + this.ignoreEmptyContent = ignoreEmptyContent; + } + /* (non-Javadoc) * @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext) */ @@ -232,8 +238,10 @@ public class ContentServiceImpl implements ContentService, ApplicationContextAwa { ContentData beforeValue = (ContentData) before.get(propertyQName); ContentData afterValue = (ContentData) after.get(propertyQName); - boolean hasContentBefore = ContentData.hasContent(beforeValue); - boolean hasContentAfter = ContentData.hasContent(afterValue); + boolean hasContentBefore = ContentData.hasContent(beforeValue) + && (!ignoreEmptyContent || beforeValue.getSize() > 0); + boolean hasContentAfter = ContentData.hasContent(afterValue) + && (!ignoreEmptyContent || afterValue.getSize() > 0); // There are some shortcuts here if (!hasContentBefore && !hasContentAfter) diff --git a/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneIndexerImpl.java b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneIndexerImpl.java index fc6d6ef05d..217fb5c4a9 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneIndexerImpl.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneIndexerImpl.java @@ -1443,6 +1443,10 @@ public class ADMLuceneIndexerImpl extends AbstractLuceneIndexerImpl imp private boolean isCategorised(AspectDefinition aspDef) { + if(aspDef == null) + { + return false; + } AspectDefinition current = aspDef; while (current != null) { diff --git a/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneSearcherImpl.java b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneSearcherImpl.java index 7ff76523cd..985bde4c64 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneSearcherImpl.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneSearcherImpl.java @@ -316,7 +316,6 @@ public class ADMLuceneSearcherImpl extends AbstractLuceneBase implements LuceneS field = expandAttributeFieldName(field); PropertyDefinition propertyDef = getDictionaryService().getProperty(QName.createQName(field.substring(1))); - // Handle .size and .mimetype if(propertyDef == null) { if(field.endsWith(".size")) diff --git a/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneTest.java b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneTest.java index 059e6b886b..c5c21ccb4e 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneTest.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneTest.java @@ -1099,8 +1099,35 @@ public class ADMLuceneTest extends TestCase implements DictionaryListener // ftsQueryWithCount(searcher, "TEXT:(brown *(5) dog)", 1); // ftsQueryWithCount(searcher, "TEXT:(brown *(6) dog)", 1); // -// // ftsQueryWithCount(searcher, "brown..dog", 1); // is this allowed?? -// // ftsQueryWithCount(searcher, "cm:content:brown..dog", 1); +// try +// { +// ftsQueryWithCount(searcher, "brown..dog", 1); // is this allowed?? +// fail("Range query should not be supported against type d:content"); +// } +// catch(UnsupportedOperationException e) +// { +// +// } +// +// try +// { +// ftsQueryWithCount(searcher, "TEXT:brown..dog", 1); +// fail("Range query should not be supported against type d:content"); +// } +// catch(UnsupportedOperationException e) +// { +// +// } +// +// try +// { +// ftsQueryWithCount(searcher, "cm:content:brown..dog", 1); +// fail("Range query should not be supported against type d:content"); +// } +// catch(UnsupportedOperationException e) +// { +// +// } // // QName qname = QName.createQName(TEST_NAMESPACE, "float\\-ista"); // ftsQueryWithCount(searcher, qname + ":3.40", 1); @@ -3068,6 +3095,25 @@ public class ADMLuceneTest extends TestCase implements DictionaryListener results = searcher.query(spN); results.close(); + // test sort on unkown properties ALF-4193 + + spN = new SearchParameters(); + spN.addStore(rootNodeRef.getStoreRef()); + spN.setLanguage(SearchService.LANGUAGE_LUCENE); + spN.setQuery("PATH:\"//.\""); + spN.addSort("PARENT", false); + results = searcher.query(spN); + results.close(); + + spN = new SearchParameters(); + spN.addStore(rootNodeRef.getStoreRef()); + spN.setLanguage(SearchService.LANGUAGE_LUCENE); + spN.setQuery("PATH:\"//.\""); + spN.addSort("@PARENT:PARENT", false); + results = searcher.query(spN); + results.close(); + + luceneFTS.resume();