From db49919005d72de79665bee889307ac05661e849 Mon Sep 17 00:00:00 2001 From: Kevin Roast Date: Wed, 6 Feb 2013 11:00:59 +0000 Subject: [PATCH] Merged BRANCHES/DEV/V4.1-BUG-FIX to HEAD 45144: Fix for ALF-16790 - upload ignores additional aspects for updateNodes 45174: Merged V4.1-BUG-FIX-2012_11_22 to V4.1-BUG-FIX 43940: ALF-15209: Add Dashlet to User or Site Dashboard not working when IE8 is operating in Compatibility Mode. Fix check p_el.attributes["id"] to avoid errors for "IE8 compatibility mode 45175: Fix for ALF-17260 - Tags list not updated after moving/copying an high number of nodes with taggable aspect but no tags 45188: ALF-16254 ("Leave Site" behaviour for group based site membership) 45204: Fix for ALF-17335 - OnCreateNodePolicy not fired when custom type is used in the Share flash upload 45218: ALF-17248 BaseAssociationEditor.java does not return any results when the query filter consists of "firstname + lastname" 45221: Merged V4.1.3 (4.1.3) to V4.1-BUG-FIX (4.1.4) RECORD ONLY 45220: Merged: V4.1-BUG-FIX (4.1.4) to V4.1.3 (4.1.3) 44054: Fix for ALF-16337. Datalist assignee not searchable by full name. 45218: ALF-17248 BaseAssociationEditor.java does not return any results when the query filter consists of "firstname + lastname" 45245: ALF-17089 (Displaying Url Name instead of site Name in Select form) 45257: ALF-17318 Unnecessary Canned Query in .getPeople(String,...) on startup. - Just one extra query on each run of the FeedNotifier was being made at the end. The sequence of queries are necessary. 45336: Merged DEV to V4.1-BUG-FIX (4.1.4) 45318: ALF-14086: CLONE - Sort order of folders including hyphens ( - ) are different in folder-tree and view on folders (in Share) Sort groups and users on the Java server side using collators. - Deprecated a few methods not deprecated in DEV and removed one which had just been added to 4.1.4 45362: Merged V3.4-BUG-FIX (3.4.13) to V4.1-BUG-FIX <> 45361: Merged V3.4 (3.4.12) to V3.4-BUG-FIX (3.4.13) 45360: ALF-17431: Merged V4.1 (4.1.2) to V3.4 (3.4.12) 43622: ALF-16757: Sharepoint doesn't work correct with SSO - Fix by Pavel 45385: Merged V4.1.3 (4.1.3) to V4.1-BUG-FIX (4.1.4) 45384: ALF-17097 60k Site Performance: Admin Console | Groups | Browse Groups (include sys groups): Results isn't appeared. - Error in authorities comparator causing test failure of ALF 14086 in 4.1.4 only. 4.1.3 was okay as ALF 14086 now uses the change made for ALF-17097 but only in 4.1.4 45452: Corrected config check for ALF-16413 - Share asks for Basic-Auth while not needed trying to access RSS feeds (thus breaking SSO). 45467: Fix for ALF-17509 - patches the FreeMarker built-in ?js_string to correctly encode the "/" character. 45468: ALF-17492 - WebScript errors must contain useful information - SpringSurf libs 1217 provide additional INFO log information on the HTTP method, URL+params that caused the exception. 45475: Fix for ALF-17510 - Upgrade of htmlparser from 1.6 to 2.1 45566: Fixed ALF-17530 - Refactored "successCallback" & "successScope" parameters for multipart uploads to be simply "success" (same for failure) 45574: Fixed ALF-17528 - Asserting that request is made using application/json 45662: Merged HEAD to BRANCHES/DEV/V4.1-BUG-FIX: 45660: Fixes: ALF-17539 - The server was failing to parse the date. It shouldn't have been trying to parse it at all. 45849: Merged HEAD to BRANCHES/DEV/V4.1-BUG-FIX: 45824: Fixes: ALF-13676: Event edit times are now presented using the date-format.shortTime setting & may be entered in either 24h or 12hr formats. 45876: ALF-17642: Fix broken HtmlParserContentTransformerTest after upgrade of htmlparser to 2.1 - Since the upgrade slightly changed the behaviour of the transformer, I added some explanatory comments to the test and to the transformer class. 45927: Fix for ALF-17302 DocLib sort is determined by server locale rather than browser locale - GetChildrenCannedQuery was not using locale based collation 46014: Fix for ALF-17732 - SWF files are considered insecure content and should not be displayed directly in the browser. 46160: Fix for ALF-17759 - HTML files are stripped from metadata and style information after they are uploaded. 46186: Fix for ALF-17786 - Site dashboard page issues too many requests (Site Members dashlet issues avatar requests when it doesn't need too) git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@46287 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../activities/feed/FeedNotifierImpl.java | 7 + .../HtmlParserContentTransformer.java | 22 +++- .../HtmlParserContentTransformerTest.java | 32 ++--- .../org/alfresco/repo/jscript/People.java | 123 ++++++++++++++++-- .../getchildren/GetChildrenCannedQuery.java | 3 +- .../authority/GetAuthoritiesCannedQuery.java | 4 +- .../security/authority/script/Authority.java | 21 ++- .../script/ScriptAuthorityService.java | 21 ++- .../authority/script/ScriptGroup.java | 61 +++++++-- .../org/alfresco/repo/site/script/Site.java | 22 +++- .../repo/tagging/TaggingServiceImplTest.java | 84 ++++++++++++ .../UpdateTagScopesActionExecuter.java | 2 +- .../repo/tagging/script/test_alf_17260.js | 21 +++ 13 files changed, 358 insertions(+), 65 deletions(-) create mode 100644 source/java/org/alfresco/repo/tagging/script/test_alf_17260.js diff --git a/source/java/org/alfresco/repo/activities/feed/FeedNotifierImpl.java b/source/java/org/alfresco/repo/activities/feed/FeedNotifierImpl.java index 4055120a9a..8514b4d6e6 100644 --- a/source/java/org/alfresco/repo/activities/feed/FeedNotifierImpl.java +++ b/source/java/org/alfresco/repo/activities/feed/FeedNotifierImpl.java @@ -1,6 +1,7 @@ package org.alfresco.repo.activities.feed; import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -335,6 +336,7 @@ public class FeedNotifierImpl implements FeedNotifier, ApplicationContextAware { private int skip = 0; private int maxItems = batchSize; + private boolean hasMore = true; @Override public int getTotalEstimatedWorkSize() @@ -345,8 +347,13 @@ public class FeedNotifierImpl implements FeedNotifier, ApplicationContextAware @Override public Collection getNextWork() { + if (!hasMore) + { + return Collections.emptyList(); + } PagingResults people = personService.getPeople(null, true, null, new PagingRequest(skip, maxItems)); skip += maxItems; + hasMore = people.hasMoreItems(); return people.getPage(); } }; diff --git a/source/java/org/alfresco/repo/content/transform/HtmlParserContentTransformer.java b/source/java/org/alfresco/repo/content/transform/HtmlParserContentTransformer.java index 6685b2ba96..96559d278c 100644 --- a/source/java/org/alfresco/repo/content/transform/HtmlParserContentTransformer.java +++ b/source/java/org/alfresco/repo/content/transform/HtmlParserContentTransformer.java @@ -33,12 +33,25 @@ import org.htmlparser.beans.StringBean; import org.htmlparser.util.ParserException; /** - * @see http://htmlparser.sourceforge.net/ - * @see org.htmlparser.beans.StringBean + * Content transformer which wraps the HTML Parser library for + * parsing HTML content. * - * Tika Note - could be convered to use the Tika HTML parser, + *

+ * Since HTML Parser was updated from v1.6 to v2.1, META tags + * defining an encoding for the content via http-equiv=Content-Type + * will ONLY be respected if the encoding of the content item + * itself is set to ISO-8859-1. + *

+ * + *

+ * Tika Note - could be converted to use the Tika HTML parser, * but we'd potentially need a custom text handler to replicate * the current settings around links and non-breaking spaces. + *

+ * + * @see http://htmlparser.sourceforge.net/ + * @see org.htmlparser.beans.StringBean + * @see http://sourceforge.net/tracker/?func=detail&aid=1644504&group_id=24399&atid=381401 * * @author Derek Hulley */ @@ -72,7 +85,8 @@ public class HtmlParserContentTransformer extends AbstractContentTransformer2 File htmlFile = TempFileProvider.createTempFile("HtmlParserContentTransformer_", ".html"); reader.getContent(htmlFile); - // Fetch the encoding of the HTML, if it's set in Alfresco + // Fetch the encoding of the HTML, as set in the ContentReader + // This will default to 'UTF-8' if not specifically set String encoding = reader.getEncoding(); // Create the extractor diff --git a/source/java/org/alfresco/repo/content/transform/HtmlParserContentTransformerTest.java b/source/java/org/alfresco/repo/content/transform/HtmlParserContentTransformerTest.java index 9c776d95da..1eb6f2cfb0 100644 --- a/source/java/org/alfresco/repo/content/transform/HtmlParserContentTransformerTest.java +++ b/source/java/org/alfresco/repo/content/transform/HtmlParserContentTransformerTest.java @@ -147,37 +147,23 @@ public class HtmlParserContentTransformerTest extends AbstractContentTransformer tmpS.delete(); tmpD.delete(); + // Note - since HTML Parser 2.0 META tags specifying the + // document encoding will ONLY be respected if the original + // content type was set to ISO-8859-1. + // + // This means there is now only one test which we can perform + // to ensure that this now-limited overriding of the encoding + // takes effect. - // Nothing on the content, meta set to ISO 8865-1 + // Content set to ISO 8859-1, meta set to UTF-8 tmpS = File.createTempFile("test", ".html"); content = new FileContentWriter(tmpS); content.setMimetype(MimetypeMap.MIMETYPE_HTML); String str = partA+ - "" + - partB+partC; - content.putContent(new ByteArrayInputStream(str.getBytes("ISO-8859-1"))); - - tmpD = File.createTempFile("test", ".txt"); - dest = new FileContentWriter(tmpD); - dest.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN); - - transformer.transform(content.getReader(), dest); - assertEquals( - TITLE + "\n" + TEXT_P1 + "\n" + TEXT_P2 + "\n" + TEXT_P3 + "\n", - dest.getReader().getContentString() - ); - tmpS.delete(); - tmpD.delete(); - - - // Nothing on the content, meta set to UTF-8 - tmpS = File.createTempFile("test", ".html"); - content = new FileContentWriter(tmpS); - content.setMimetype(MimetypeMap.MIMETYPE_HTML); - str = partA+ "" + partB+partC; content.putContent(new ByteArrayInputStream(str.getBytes("UTF-8"))); + content.setEncoding("ISO-8859-1"); tmpD = File.createTempFile("test", ".txt"); dest = new FileContentWriter(tmpD); diff --git a/source/java/org/alfresco/repo/jscript/People.java b/source/java/org/alfresco/repo/jscript/People.java index 29147d9f0c..76b5c5e25b 100644 --- a/source/java/org/alfresco/repo/jscript/People.java +++ b/source/java/org/alfresco/repo/jscript/People.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2012 Alfresco Software Limited. + * Copyright (C) 2005-2013 Alfresco Software Limited. * * This file is part of Alfresco * @@ -18,7 +18,11 @@ */ package org.alfresco.repo.jscript; +import java.io.Serializable; +import java.text.Collator; import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -37,6 +41,7 @@ import org.alfresco.repo.tenant.TenantDomainMismatchException; import org.alfresco.repo.tenant.TenantService; import org.alfresco.service.ServiceRegistry; 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.ResultSet; @@ -58,6 +63,7 @@ import org.apache.commons.logging.LogFactory; import org.mozilla.javascript.Context; import org.mozilla.javascript.Scriptable; import org.springframework.beans.factory.InitializingBean; +import org.springframework.extensions.surf.util.I18NUtil; import org.springframework.extensions.surf.util.ParameterCheck; /** @@ -508,6 +514,26 @@ public final class People extends BaseScopableProcessorExtension implements Init * @return people collection as a JavaScript array */ public Scriptable getPeople(String filter, int maxResults) + { + return getPeople(filter, maxResults, null, true); + } + + /** + * Get the collection of people stored in the repository. + * An optional filter query may be provided by which to filter the people collection. + * Space separate the query terms i.e. "john bob" will find all users who's first or + * second names contain the strings "john" or "bob". + * Method supports sorting by specifying sortBy and sortAsc params. + * + * @param filter filter query string by which to filter the collection of people. + * If
null
then all people stored in the repository are returned + * @param maxResults maximum results to return or all if <= 0 + * @param sortBy field for sorting + * @param sortAsc sort ascending or not + * + * @return people collection as a JavaScript array + */ + public Scriptable getPeople(String filter, int maxResults, String sortBy, boolean sortAsc) { boolean useCQ = false; if (filter != null) @@ -529,7 +555,7 @@ public final class People extends BaseScopableProcessorExtension implements Init if ((filter == null || filter.length() == 0) || useCQ) { - people = getPeopleImplDB(filter, maxResults); + people = getPeopleImplDB(filter, maxResults, sortBy, sortAsc); } else { @@ -546,14 +572,14 @@ public final class People extends BaseScopableProcessorExtension implements Init try { - people = getPeopleImplSearch(term, t, propIndex, maxResults); + people = getPeopleImplSearch(term, t, propIndex, maxResults, sortBy, sortAsc); } catch (Throwable err) { if (useCQ) { // search unavailable and/or parser exception - try CQ instead - people = getPeopleImplDB(term, maxResults); + people = getPeopleImplDB(term, maxResults, sortBy, sortAsc); } } } @@ -568,10 +594,11 @@ public final class People extends BaseScopableProcessorExtension implements Init } // canned query - private Object[] getPeopleImplDB(String term, int maxResults) + private Object[] getPeopleImplDB(String term, int maxResults, final String sortBy, boolean sortAsc) { Long start = (logger.isDebugEnabled() ? System.currentTimeMillis() : null); - Object[] people = null; + + List peopleRefs = new ArrayList(); // simple non-FTS filter: firstname or lastname or username starting with term (ignoring case) @@ -585,24 +612,27 @@ public final class People extends BaseScopableProcessorExtension implements Init PagingRequest pagingRequest = new PagingRequest(maxResults, null); List persons = personService.getPeople(term, filterProps, sortProps, pagingRequest).getPage(); - people = new Object[persons.size()]; - for (int i=0; i peopleRefs = new ArrayList(); Object[] people = null; SearchParameters params = new SearchParameters(); @@ -712,7 +742,7 @@ public final class People extends BaseScopableProcessorExtension implements Init try { results = services.getSearchService().query(params); - people = results.getNodeRefs().toArray(); + people = getSortedPeopleObjects(results.getNodeRefs(), sortBy, sortAsc); if (start != null) { @@ -739,6 +769,75 @@ public final class People extends BaseScopableProcessorExtension implements Init return people; } + private Object[] getSortedPeopleObjects(List peopleRefs, final String sortBy, boolean sortAsc) + { + final Collator col = Collator.getInstance(I18NUtil.getLocale()); + final NodeService nodeService = services.getNodeService(); + final int orderMultiplicator = sortAsc ? 1 : -1; + Collections.sort(peopleRefs, new Comparator() + { + @Override + public int compare(NodeRef n1, NodeRef n2) + { + String p1 = getProperty(n1); + String p2 = getProperty(n2); + + return col.compare(p1, p2) * orderMultiplicator; + } + + public String getProperty(NodeRef nodeRef) + { + Serializable result; + + if ("fullName".equalsIgnoreCase(sortBy)) + { + String firstName = nodeService.getProperty(nodeRef, ContentModel.PROP_FIRSTNAME).toString(); + String lastName = nodeService.getProperty(nodeRef, ContentModel.PROP_LASTNAME).toString(); + String fullName = firstName; + if (lastName != null && lastName.length() > 0) + { + fullName = fullName + " " + lastName; + } + + result = fullName; + } + else if ("jobtitle".equalsIgnoreCase(sortBy)) + { + result = nodeService.getProperty(nodeRef, ContentModel.PROP_JOBTITLE); + } + else if ("email".equalsIgnoreCase(sortBy)) + { + result = nodeService.getProperty(nodeRef, ContentModel.PROP_EMAIL); + } + else if ("usage".equalsIgnoreCase(sortBy)) + { + result = nodeService.getProperty(nodeRef, ContentModel.PROP_SIZE_CURRENT); + } + else if ("quota".equalsIgnoreCase(sortBy)) + { + result = nodeService.getProperty(nodeRef, ContentModel.PROP_SIZE_QUOTA); + } + else + { + // Default + result = nodeService.getProperty(nodeRef, ContentModel.PROP_USERNAME); + } + + if (result == null) + { + result = ""; + } + + return result.toString(); + } + + }); + + Object[] people = new Object[peopleRefs.size()]; + peopleRefs.toArray(people); + + return people; + } /** * Gets the Person given the username * diff --git a/source/java/org/alfresco/repo/node/getchildren/GetChildrenCannedQuery.java b/source/java/org/alfresco/repo/node/getchildren/GetChildrenCannedQuery.java index 295042123a..af36afe923 100644 --- a/source/java/org/alfresco/repo/node/getchildren/GetChildrenCannedQuery.java +++ b/source/java/org/alfresco/repo/node/getchildren/GetChildrenCannedQuery.java @@ -61,6 +61,7 @@ import org.alfresco.util.Pair; import org.alfresco.util.ParameterCheck; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.springframework.extensions.surf.util.I18NUtil; /** * GetChidren canned query @@ -362,7 +363,7 @@ public class GetChildrenCannedQuery extends AbstractCannedQueryPermissions> sortProps) { this.sortProps = sortProps; - this.collator = Collator.getInstance(); // note: currently default locale + this.collator = Collator.getInstance(I18NUtil.getContentLocale()); } public int compare(FilterSortNode n1, FilterSortNode n2) diff --git a/source/java/org/alfresco/repo/security/authority/GetAuthoritiesCannedQuery.java b/source/java/org/alfresco/repo/security/authority/GetAuthoritiesCannedQuery.java index d491201314..5bcaf523bb 100644 --- a/source/java/org/alfresco/repo/security/authority/GetAuthoritiesCannedQuery.java +++ b/source/java/org/alfresco/repo/security/authority/GetAuthoritiesCannedQuery.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2012 Alfresco Software Limited. + * Copyright (C) 2005-2013 Alfresco Software Limited. * * This file is part of Alfresco * @@ -190,7 +190,7 @@ public class GetAuthoritiesCannedQuery extends AbstractCannedQueryPermissions nameCache; private String sortBy; + private Collator col; + private int orderMultiplicator = 1; public AuthorityComparator(String sortBy) { + this.col = Collator.getInstance(I18NUtil.getLocale()); this.sortBy = sortBy; this.nameCache = new HashMap(); } + public AuthorityComparator(String sortBy, boolean sortAsc) + { + col = Collator.getInstance(I18NUtil.getLocale()); + this.sortBy = sortBy; + this.nameCache = new HashMap(); + if (!sortAsc) + { + orderMultiplicator = -1; + } + } + @Override public int compare(Authority g1, Authority g2) { - return get(g1).compareTo( get(g2) ); + return col.compare(get(g1), get(g2)) * orderMultiplicator; } private String get(Authority g) diff --git a/source/java/org/alfresco/repo/security/authority/script/ScriptAuthorityService.java b/source/java/org/alfresco/repo/security/authority/script/ScriptAuthorityService.java index e31d292ea5..83a732464f 100644 --- a/source/java/org/alfresco/repo/security/authority/script/ScriptAuthorityService.java +++ b/source/java/org/alfresco/repo/security/authority/script/ScriptAuthorityService.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2011 Alfresco Software Limited. + * Copyright (C) 2005-2013 Alfresco Software Limited. * * This file is part of Alfresco * @@ -43,7 +43,6 @@ import org.alfresco.util.Pair; import org.alfresco.util.ScriptPagingDetails; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.mozilla.javascript.Scriptable; /** * Script object representing the authority service. @@ -267,6 +266,15 @@ public class ScriptAuthorityService extends BaseScopableProcessorExtension return getGroupsInZone(filter, null, paging, sortBy); } + /** + * @deprecated + * @since 4.0 + */ + public ScriptGroup[] getGroupsInZone(String filter, String zone, ScriptPagingDetails paging, String sortBy) + { + return getGroupsInZone(filter, zone, paging, sortBy, true); + } + /** * Retrieves groups matching the given filter from the given zone. * @@ -277,10 +285,11 @@ public class ScriptAuthorityService extends BaseScopableProcessorExtension * @param paging Paging details * @param sortBy Field to sort by, can be shortName, displayName or * authorityName, the default is displayName + * @param sortAsc sort ascending or not * @return Array of matching groups - * @since 4.0 + * @since 4.1.4 */ - public ScriptGroup[] getGroupsInZone(String filter, String zone, ScriptPagingDetails paging, String sortBy) + public ScriptGroup[] getGroupsInZone(String filter, String zone, ScriptPagingDetails paging, String sortBy, boolean sortAsc) { if (sortBy == null) { @@ -306,10 +315,10 @@ public class ScriptAuthorityService extends BaseScopableProcessorExtension paging.setRequestTotalCountMax(10000); // get the paged results (NOTE: we can only sort by display name currently) - PagingResults groups = authorityService.getAuthoritiesInfo(AuthorityType.GROUP, zone, filter, sortBy, true, paging); + PagingResults groups = authorityService.getAuthoritiesInfo(AuthorityType.GROUP, zone, filter, sortBy, sortAsc, paging); // create ScriptGroup array from paged results - scriptGroups = makeScriptGroupsInfo(groups, paging, serviceRegistry, this.getScope()); + scriptGroups = makeScriptGroupsInfo(groups, paging, sortBy, sortAsc, serviceRegistry, this.getScope()); } catch (UnknownAuthorityException e) { diff --git a/source/java/org/alfresco/repo/security/authority/script/ScriptGroup.java b/source/java/org/alfresco/repo/security/authority/script/ScriptGroup.java index 97b9f22d19..10fef13048 100644 --- a/source/java/org/alfresco/repo/security/authority/script/ScriptGroup.java +++ b/source/java/org/alfresco/repo/security/authority/script/ScriptGroup.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2012 Alfresco Software Limited. + * Copyright (C) 2005-2013 Alfresco Software Limited. * * This file is part of Alfresco * @@ -539,6 +539,9 @@ public class ScriptGroup implements Authority, Serializable childAuthorityNames = null; } + /** + * @deprecated + */ public static ScriptGroup[] makeScriptGroups(Collection authorities, ScriptPagingDetails paging, ServiceRegistry serviceRegistry, Scriptable scope) @@ -546,11 +549,20 @@ public class ScriptGroup implements Authority, Serializable return makeScriptGroups(authorities, paging, null, serviceRegistry, scope); } + /** + * @deprecated + */ public static ScriptGroup[] makeScriptGroups(Collection authorities, ScriptPagingDetails paging, String sortBy, ServiceRegistry serviceRegistry, Scriptable scope) { + return makeScriptGroups(authorities, paging, sortBy, true, serviceRegistry, scope); + } + public static ScriptGroup[] makeScriptGroups(Collection authorities, + ScriptPagingDetails paging, final String sortBy, boolean sortAsc, ServiceRegistry serviceRegistry, + Scriptable scope) + { final ArrayList authList = new ArrayList(authorities); final Map scriptGroupCache = new HashMap(); @@ -562,7 +574,7 @@ public class ScriptGroup implements Authority, Serializable { scriptGroupCache.put(authority, new ScriptGroup(authority, serviceRegistry, scope)); } - final AuthorityComparator c2 = new AuthorityComparator(sortBy); + final AuthorityComparator c2 = new AuthorityComparator(sortBy, sortAsc); Collections.sort(authList, new Comparator() { @Override public int compare(String g1, String g2) @@ -606,18 +618,31 @@ public class ScriptGroup implements Authority, Serializable return groups; } + /** + * @deprecated + * @since 4.0 + */ + public static ScriptGroup[] makeScriptGroups(PagingResults pagedGroups, ScriptPagingDetails paging, + ServiceRegistry serviceRegistry, Scriptable scope) + { + return makeScriptGroups(pagedGroups, paging, null, true, serviceRegistry, scope); + } + /** * Returns an array of ScriptGroup objects representing the given paged results. * * @param groups The paged results * @param paging Object representing the paging details + * @param sortBy field for sorting + * @param sortAsc sort ascending or not * @param serviceRegistry * @param scope * @return Array of ScriptGroup objects * - * @since 4.0 + * @since 4.1.4 */ - public static ScriptGroup[] makeScriptGroups(PagingResults pagedGroups, ScriptPagingDetails paging, + public static ScriptGroup[] makeScriptGroups(PagingResults pagedGroups, ScriptPagingDetails paging, + String sortBy, boolean sortAsc, ServiceRegistry serviceRegistry, Scriptable scope) { // set the total on the paging object @@ -625,11 +650,15 @@ public class ScriptGroup implements Authority, Serializable // retrive the page of results and create a ScriptGroup for each one List groupNames = pagedGroups.getPage(); - ScriptGroup[] groups = new ScriptGroup[groupNames.size()]; - for (int i=0; i groupList= new ArrayList(); + for (int i=0; i pagedGroups, ScriptPagingDetails paging, + public static ScriptGroup[] makeScriptGroupsInfo(PagingResults pagedGroups, ScriptPagingDetails paging, + String sortBy, boolean sortAsc, ServiceRegistry serviceRegistry, Scriptable scope) { // set the total on the paging object @@ -653,12 +683,17 @@ public class ScriptGroup implements Authority, Serializable // retrive the page of results and create a ScriptGroup for each one List groupInfo = pagedGroups.getPage(); - ScriptGroup[] groups = new ScriptGroup[groupInfo.size()]; - for (int i=0; i groupList= new ArrayList(); + + for (int i=0; i(){ + + @Override + public Void execute() throws Throwable + { + // Add some tag scopes + taggingService.addTagScope(folder); + return null; + } + }); + + // Generate ~1800 audit entries, none of which are updates, as determined by UpdateTagScopesActionExecuter + asyncOccurs.awaitExecution(new RetryingTransactionCallback() + { + @Override + public Void execute() throws Throwable + { + Map model = new HashMap(0); + model.put("folder", folder); + + ScriptLocation location = new ClasspathScriptLocation("org/alfresco/repo/tagging/script/test_alf_17260.js"); + scriptService.executeScript(location, model); + + // Let the script run + return null; + } + }); + + // The tag scope of our container should be empty at this stage. + asyncOccurs.awaitExecution(new RetryingTransactionCallback() + { + @Override + public Void execute() throws Throwable + { + // re get the tag scopes + TagScope ts1 = taggingService.findTagScope(folder); + + // Check that the tag scopes got populated + assertEquals("Wrong tags on sub folder: " + ts1.getTags(), 0, ts1.getTags().size()); + return null; + } + }); + + // Add some tags which should update the tag scope. + asyncOccurs.awaitExecution(new RetryingTransactionCallback() + { + @Override + public Void execute() throws Throwable + { + taggingService.addTag(subDocument, TAG_1); // folder+subfolder + return null; + } + }); + + // Prior to fixing ALF-17260, the tag scope of our container wasn't being updated correctly. These + // assertions were failing. + asyncOccurs.awaitExecution(new RetryingTransactionCallback() + { + @Override + public Void execute() throws Throwable + { + // re get the tag scopes + TagScope ts1 = taggingService.findTagScope(folder); + + // Check that the tag scopes got populated + assertEquals("Wrong tags on folder: " + ts1.getTags(), 1, ts1.getTags().size()); + assertEquals("Wrong tag name", TAG_1, ts1.getTags().get(0).getName()); + assertEquals("Wrong number of documents", 1, ts1.getTags().get(0).getCount()); + return null; + } + }); + } } diff --git a/source/java/org/alfresco/repo/tagging/UpdateTagScopesActionExecuter.java b/source/java/org/alfresco/repo/tagging/UpdateTagScopesActionExecuter.java index b379c32085..6a3e816472 100644 --- a/source/java/org/alfresco/repo/tagging/UpdateTagScopesActionExecuter.java +++ b/source/java/org/alfresco/repo/tagging/UpdateTagScopesActionExecuter.java @@ -244,7 +244,7 @@ public class UpdateTagScopesActionExecuter extends ActionExecuterAbstractBase } // Does any work remain? - if(updates.size() == 0) + if(entryIds.size() == 0) { updatesRemain.setValue(0); return null; diff --git a/source/java/org/alfresco/repo/tagging/script/test_alf_17260.js b/source/java/org/alfresco/repo/tagging/script/test_alf_17260.js new file mode 100644 index 0000000000..fb4dbc7335 --- /dev/null +++ b/source/java/org/alfresco/repo/tagging/script/test_alf_17260.js @@ -0,0 +1,21 @@ +for (var j = 0; j < 10 ; j ++) +{ + var test1 = folder.createFolder("Test1"); + var test2 = folder.createFolder("Test2"); + + for(var i=0;i<102;i++) + { + var node = test1.createNode(j + "_test_"+i+".text","cm:content"); + node.addTag(j + "testTag" + i); + } + + for each (child in test1.children){ + child.clearTags(); + } + + test1.move(test2); + if (j < 9) + { + test2.remove(); + } +} \ No newline at end of file