diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/comments/comments.post.json.js b/config/alfresco/templates/webscripts/org/alfresco/repository/comments/comments.post.json.js
index 945340d55a..978d75d0cf 100644
--- a/config/alfresco/templates/webscripts/org/alfresco/repository/comments/comments.post.json.js
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/comments/comments.post.json.js
@@ -21,6 +21,12 @@ function addComment(node)
// get a unique name
var name = getUniqueChildName(commentsFolder, "comment");
+ // Add the comments rollup aspect to the commented-upon node.
+ if (!node.hasAspect("fm:commentsRollup"))
+ {
+ node.addAspect("fm:commentsRollup");
+ }
+
// create the comment
var commentNode = commentsFolder.createNode(name, "fm:post");
commentNode.mimetype = "text/html";
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/forms/form.post.js b/config/alfresco/templates/webscripts/org/alfresco/repository/forms/form.post.js
index a115121ada..8d37d17839 100644
--- a/config/alfresco/templates/webscripts/org/alfresco/repository/forms/form.post.js
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/forms/form.post.js
@@ -1,8 +1,8 @@
function main()
{
// Extract template args
- var itemKind = url.templateArgs["item_kind"];
- var itemId = url.templateArgs["item_id"];
+ var itemKind = decodeURIComponent(url.templateArgs["item_kind"]);
+ var itemId = decodeURIComponent(url.templateArgs["item_id"]);
if (logger.isLoggingEnabled())
{
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/forms/form.post.json.js b/config/alfresco/templates/webscripts/org/alfresco/repository/forms/form.post.json.js
index 56a5dae4c8..53e6f35db5 100644
--- a/config/alfresco/templates/webscripts/org/alfresco/repository/forms/form.post.json.js
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/forms/form.post.json.js
@@ -1,8 +1,8 @@
function main()
{
// Extract template args
- var itemKind = url.templateArgs["item_kind"];
- var itemId = url.templateArgs["item_id"];
+ var itemKind = decodeURIComponent(url.templateArgs["item_kind"]);
+ var itemId = decodeURIComponent(url.templateArgs["item_id"]);
if (logger.isLoggingEnabled())
{
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/forms/formdefinition.post.json.js b/config/alfresco/templates/webscripts/org/alfresco/repository/forms/formdefinition.post.json.js
index e7553f1940..9be6d7a239 100644
--- a/config/alfresco/templates/webscripts/org/alfresco/repository/forms/formdefinition.post.json.js
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/forms/formdefinition.post.json.js
@@ -96,10 +96,9 @@ function main()
var submissionUrl = formScriptObj.submissionUrl;
if (submissionUrl === null)
{
- // replace characters that can cause issues in URLs
- var escapedItemId = itemId.replace(':', '_');
-
- submissionUrl = '/api/' + itemKind + '/' + escapedItemId + '/formprocessor';
+ // encode the item id and item kind using URI encoding scheme, however, the encoded / character
+ // causes problems when posting back to Apache so change these back
+ submissionUrl = '/api/' + encodeURIComponent(itemKind) + '/' + encodeURIComponent(itemId).replace(/%2f/g, "/") + '/formprocessor';
}
// create form model
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/solr/aclChangeSets.get.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/repository/solr/aclChangeSets.get.desc.xml
index 00acd29eaa..812a849a5f 100644
--- a/config/alfresco/templates/webscripts/org/alfresco/repository/solr/aclChangeSets.get.desc.xml
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/solr/aclChangeSets.get.desc.xml
@@ -7,4 +7,18 @@
required
internal
SOLR
+
+
+ fromId
+ Smallest changset ID (inclusive)
+
+
+ fromTime
+ Smallest commit time (inclusive)
+
+
+ maxResults
+ Maximum number of results (optional: default 1024)
+
+
\ No newline at end of file
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/solr/acls.post.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/repository/solr/acls.post.desc.xml
new file mode 100644
index 0000000000..736ca07ab1
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/solr/acls.post.desc.xml
@@ -0,0 +1,26 @@
+
+ Get ACLs
+ Get the ACLs for given ChangeSets.
+ /api/solr/acls?fromId={fromId?}&maxResults={maxResults?}
+ argument
+ admin
+ required
+ internal
+ SOLR
+
+
+ fromId
+ Minimum ACL ID that can be specified when exactly one ACL ChangeSet ID is given
+
+
+ maxResults
+ Maximum number of results (optional: default 1024)
+
+
+ POST content
+
+ { aclChangeSetIds : [ 1, 2, ..., n] }
+
+
+
+
\ No newline at end of file
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/solr/acls.post.json.ftl b/config/alfresco/templates/webscripts/org/alfresco/repository/solr/acls.post.json.ftl
new file mode 100644
index 0000000000..abe52028cd
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/solr/acls.post.json.ftl
@@ -0,0 +1,10 @@
+<#import "solr.lib.ftl" as solrLib/>
+{
+ "acls" :
+ [
+ <#list acls as acl>
+ <@solrLib.aclJSON acl=acl/>
+ <#if acl_has_next>,#if>
+ #list>
+ ]
+}
\ No newline at end of file
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/solr/aclsReaders.post.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/repository/solr/aclsReaders.post.desc.xml
new file mode 100644
index 0000000000..93bf614bdf
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/solr/aclsReaders.post.desc.xml
@@ -0,0 +1,18 @@
+
+ Get ACLs readers
+ Get the readers for given ACLs.
+ /api/solr/aclsReaders
+ argument
+ admin
+ required
+ internal
+ SOLR
+
+
+ POST content
+
+ { aclIds: [1, 2, 3, ..., N] }
+
+
+
+
\ No newline at end of file
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/solr/aclsReaders.post.json.ftl b/config/alfresco/templates/webscripts/org/alfresco/repository/solr/aclsReaders.post.json.ftl
new file mode 100644
index 0000000000..4669dec557
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/solr/aclsReaders.post.json.ftl
@@ -0,0 +1,10 @@
+<#import "solr.lib.ftl" as solrLib/>
+{
+ "aclsReaders" :
+ [
+ <#list aclsReaders as aclReaders>
+ <@solrLib.aclReadersJSON aclReaders=aclReaders/>
+ <#if aclReaders_has_next>,#if>
+ #list>
+ ]
+}
\ No newline at end of file
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/solr/solr.lib.ftl b/config/alfresco/templates/webscripts/org/alfresco/repository/solr/solr.lib.ftl
index d43c81d64a..cd0a62e974 100644
--- a/config/alfresco/templates/webscripts/org/alfresco/repository/solr/solr.lib.ftl
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/solr/solr.lib.ftl
@@ -6,6 +6,26 @@
}
#macro>
+<#macro aclJSON acl>
+ {
+ "id": ${acl.id?c},
+ "aclChangeSetId": ${acl.aclChangeSetId?c}
+ }
+#macro>
+
+<#macro aclReadersJSON aclReaders>
+ {
+ "aclId": ${aclReaders.aclId?c},
+ "readers" :
+ [
+ <#list aclReaders.readers as reader>
+ ${reader?string}
+ <#if reader_has_next>,#if>
+ #list>
+ ]
+ }
+#macro>
+
<#macro transactionJSON txn>
{
"id": ${txn.id?c},
diff --git a/config/alfresco/templates/webscripts/org/alfresco/slingshot/documentlibrary/doclist.get.js b/config/alfresco/templates/webscripts/org/alfresco/slingshot/documentlibrary/doclist.get.js
index 912ef5d58d..ad1ea906a7 100644
--- a/config/alfresco/templates/webscripts/org/alfresco/slingshot/documentlibrary/doclist.get.js
+++ b/config/alfresco/templates/webscripts/org/alfresco/slingshot/documentlibrary/doclist.get.js
@@ -22,6 +22,7 @@ function getDoclist()
// Try to find a filter query based on the passed-in arguments
var allNodes = [],
totalRecords,
+ totalRecordsUpper,
paged = false,
favourites = Common.getFavourites(),
filterParams = Filters.getFilterParams(filter, parsedArgs,
@@ -56,11 +57,14 @@ function getDoclist()
var sortField = (args.sortField == null ? "cm:name" : args.sortField);
var sortAsc = (((args.sortAsc == null) || (args.sortAsc == "true")) ? true : false);
+
+ // TODO review
+ var pagedResult = parentNode.childFileFolders(true, true, ignoreTypes, skip, max, (skip + 1000), sortField, sortAsc, "TODO");
- var pagedResult = parentNode.childFileFolders(true, true, ignoreTypes, skip, max, sortField, sortAsc);
+ allNodes = pagedResult.page;
- allNodes = pagedResult.result;
- totalRecords = pagedResult.totalCount;
+ totalRecords = pagedResult.totalResultCountLower;
+ totalRecordsUpper = pagedResult.totalResultCountUpper;
paged = true;
}
@@ -240,15 +244,22 @@ function getDoclist()
}
}
}
-
+
+ var paging =
+ {
+ totalRecords: totalRecords,
+ startIndex: startIndex
+ };
+
+ if (paged && (! (totalRecords === totalRecordsUpper)))
+ {
+ paging.totalRecordsUpper = totalRecordsUpper;
+ }
+
return (
{
luceneQuery: query,
- paging:
- {
- totalRecords: totalRecords,
- startIndex: startIndex
- },
+ paging: paging,
container: parsedArgs.rootNode,
parent: parent,
onlineEditing: utils.moduleInstalled("org.alfresco.module.vti"),
diff --git a/config/alfresco/templates/webscripts/org/alfresco/slingshot/documentlibrary/doclist.get.json.ftl b/config/alfresco/templates/webscripts/org/alfresco/slingshot/documentlibrary/doclist.get.json.ftl
index 489362a34c..101de008c3 100644
--- a/config/alfresco/templates/webscripts/org/alfresco/slingshot/documentlibrary/doclist.get.json.ftl
+++ b/config/alfresco/templates/webscripts/org/alfresco/slingshot/documentlibrary/doclist.get.json.ftl
@@ -2,6 +2,9 @@
<#escape x as jsonUtils.encodeJSONString(x)>
{
"totalRecords": ${doclist.paging.totalRecords?c},
+ <#if doclist.paging.totalRecordsUpper??>
+ "totalRecordsUpper": ${doclist.paging.totalRecordsUpper?c},
+ #if>
"startIndex": ${doclist.paging.startIndex?c},
"metadata":
{
diff --git a/config/alfresco/templates/webscripts/org/alfresco/slingshot/documentlibrary/treenode.get.js b/config/alfresco/templates/webscripts/org/alfresco/slingshot/documentlibrary/treenode.get.js
index 487d514dcd..5997b71bd2 100644
--- a/config/alfresco/templates/webscripts/org/alfresco/slingshot/documentlibrary/treenode.get.js
+++ b/config/alfresco/templates/webscripts/org/alfresco/slingshot/documentlibrary/treenode.get.js
@@ -24,32 +24,29 @@ function getTreeNode()
{
return;
}
-
- // Look for folders in the pathNode
- var folders = parsedArgs.pathNode.childFileFolders(false, true, ignoredTypes);
- for each (item in folders)
+
+ // Look for folders in the pathNode - sort by ascending name
+ var pagedResult = parsedArgs.pathNode.childFileFolders(false, true, ignoredTypes, 0, maxItems, 0, "cm:name", true, "TODO");
+
+ if (pagedResult.hasMoreItems() == true)
+ {
+ resultsTrimmed = true;
+ }
+
+ for each (item in pagedResult.page)
{
if (evalChildFolders)
{
- hasSubfolders = item.childFileFolders(false, true, "fm:forum").length > 0;
+ hasSubfolders = item.childFileFolders(false, true, ignoredTypes, 1).page.length > 0;
}
-
+
items.push(
{
- node: item,
- hasSubfolders: hasSubfolders
+ node: item,
+ hasSubfolders: hasSubfolders
});
-
- if (maxItems !== -1 && items.length > maxItems)
- {
- items.pop();
- resultsTrimmed = true;
- break;
- }
}
-
- items.sort(sortByName);
-
+
return (
{
parent: parsedArgs.pathNode,
@@ -62,11 +59,4 @@ function getTreeNode()
status.setCode(status.STATUS_INTERNAL_SERVER_ERROR, e.toString());
return;
}
-}
-
-
-/* Sort the results by case-insensitive name */
-function sortByName(a, b)
-{
- return (b.node.name.toLowerCase() > a.node.name.toLowerCase() ? -1 : 1);
}
\ No newline at end of file
diff --git a/config/alfresco/web-scripts-application-context.xml b/config/alfresco/web-scripts-application-context.xml
index 040a21811c..74f7b85c70 100644
--- a/config/alfresco/web-scripts-application-context.xml
+++ b/config/alfresco/web-scripts-application-context.xml
@@ -1233,6 +1233,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/source/java/org/alfresco/repo/web/scripts/RepoStore.java b/source/java/org/alfresco/repo/web/scripts/RepoStore.java
index 173d6a7878..535f48d88c 100644
--- a/source/java/org/alfresco/repo/web/scripts/RepoStore.java
+++ b/source/java/org/alfresco/repo/web/scripts/RepoStore.java
@@ -34,7 +34,7 @@ import java.util.regex.Pattern;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.model.filefolder.FileFolderServiceImpl;
-import org.alfresco.repo.search.impl.lucene.LuceneQueryParser;
+import org.alfresco.repo.search.impl.lucene.AbstractLuceneQueryParser;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.tenant.TenantAdminService;
import org.alfresco.repo.tenant.TenantDeployer;
@@ -483,12 +483,12 @@ public class RepoStore extends AbstractStore implements TenantDeployer
}
else
{
- result.append(LuceneQueryParser.escape(token));
+ result.append(AbstractLuceneQueryParser.escape(token));
}
}
else
{
- result.append(LuceneQueryParser.escape(token));
+ result.append(AbstractLuceneQueryParser.escape(token));
}
}
return result.toString();
diff --git a/source/java/org/alfresco/repo/web/scripts/site/SiteServiceTest.java b/source/java/org/alfresco/repo/web/scripts/site/SiteServiceTest.java
index 4b6ed636f9..5c13d4b833 100644
--- a/source/java/org/alfresco/repo/web/scripts/site/SiteServiceTest.java
+++ b/source/java/org/alfresco/repo/web/scripts/site/SiteServiceTest.java
@@ -171,8 +171,7 @@ public class SiteServiceTest extends BaseWebScriptTest
Response response = sendRequest(new GetRequest(URL_SITES), 200);
JSONArray result = new JSONArray(response.getContentAsString());
assertNotNull(result);
- int sitesBefore = result.length();
- assertTrue("There should be at least one site present", sitesBefore > 0);
+ final int preexistingSiteCount = result.length();
createSite("myPreset", GUID.generate(), "myTitle", "myDescription", SiteVisibility.PUBLIC, 200);
createSite("myPreset", GUID.generate(), "myTitle", "myDescription", SiteVisibility.PUBLIC, 200);
@@ -183,17 +182,17 @@ public class SiteServiceTest extends BaseWebScriptTest
response = sendRequest(new GetRequest(URL_SITES), 200);
result = new JSONArray(response.getContentAsString());
assertNotNull(result);
- assertEquals(5 + sitesBefore, result.length());
+ assertEquals("Wrong site count", preexistingSiteCount + 5, result.length());
response = sendRequest(new GetRequest(URL_SITES + "?size=3"), 200);
result = new JSONArray(response.getContentAsString());
assertNotNull(result);
- assertEquals(3, result.length());
+ assertEquals("Wrong site count (?size=3)", 3, result.length());
response = sendRequest(new GetRequest(URL_SITES + "?size=13"), 200);
result = new JSONArray(response.getContentAsString());
assertNotNull(result);
- assertEquals(5 + sitesBefore, result.length());
+ assertEquals("Wrong site count (?size=13)", Math.min(13, preexistingSiteCount + 5), result.length());
}
/**
diff --git a/source/java/org/alfresco/repo/web/scripts/solr/AclsGet.java b/source/java/org/alfresco/repo/web/scripts/solr/AclsGet.java
new file mode 100644
index 0000000000..4b74d6690f
--- /dev/null
+++ b/source/java/org/alfresco/repo/web/scripts/solr/AclsGet.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2005-2011 Alfresco Software Limited.
+ *
+ * This file is part of Alfresco
+ *
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ */
+package org.alfresco.repo.web.scripts.solr;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.alfresco.repo.solr.Acl;
+import org.alfresco.repo.solr.SOLRTrackingComponent;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.springframework.extensions.surf.util.Content;
+import org.springframework.extensions.webscripts.DeclarativeWebScript;
+import org.springframework.extensions.webscripts.Status;
+import org.springframework.extensions.webscripts.WebScriptException;
+import org.springframework.extensions.webscripts.WebScriptRequest;
+
+/**
+ * Support for SOLR: Track ACLs
+ *
+ * @since 4.0
+ */
+public class AclsGet extends DeclarativeWebScript
+{
+ protected static final Log logger = LogFactory.getLog(AclsGet.class);
+
+ private SOLRTrackingComponent solrTrackingComponent;
+
+ public void setSolrTrackingComponent(SOLRTrackingComponent solrTrackingComponent)
+ {
+ this.solrTrackingComponent = solrTrackingComponent;
+ }
+
+ protected Map executeImpl(WebScriptRequest req, Status status)
+ {
+ try
+ {
+ Map model = buildModel(req);
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("Result: \n\tRequest: " + req + "\n\tModel: " + model);
+ }
+ return model;
+ }
+ catch(IOException e)
+ {
+ throw new WebScriptException("IO exception parsing request", e);
+ }
+ catch(JSONException e)
+ {
+ throw new WebScriptException("Invalid JSON", e);
+ }
+ }
+
+ private Map buildModel(WebScriptRequest req) throws JSONException, IOException
+ {
+ List aclChangeSetIds = null;
+
+ Content content = req.getContent();
+ if (content == null)
+ {
+ throw new WebScriptException("Request content is empty");
+ }
+ JSONObject o = new JSONObject(content.getContent());
+ JSONArray aclChangeSetIdsJSON = o.has("aclChangeSetIds") ? o.getJSONArray("aclChangeSetIds") : null;
+ if (aclChangeSetIdsJSON == null)
+ {
+ throw new WebScriptException(
+ Status.STATUS_BAD_REQUEST,
+ "Parameter 'aclChangeSetIds' not provided in request content.");
+ }
+ else if (aclChangeSetIdsJSON.length() == 0 || aclChangeSetIdsJSON.length() > 512)
+ {
+ throw new WebScriptException(
+ Status.STATUS_BAD_REQUEST,
+ "Parameter 'aclChangeSetIds' must hold from 1 to 512 IDs.");
+ }
+ aclChangeSetIds = new ArrayList(aclChangeSetIdsJSON.length());
+ for (int i = 0; i < aclChangeSetIdsJSON.length(); i++)
+ {
+ aclChangeSetIds.add(aclChangeSetIdsJSON.getLong(i));
+ }
+
+ String fromIdParam = req.getParameter("fromId");
+ String maxResultsParam = req.getParameter("maxResults");
+
+ Long fromId = (fromIdParam == null ? null : Long.valueOf(fromIdParam));
+ int maxResults = (maxResultsParam == null ? 1024 : Integer.valueOf(maxResultsParam));
+
+ // Request according to the paging query style required
+ List acls = solrTrackingComponent.getAcls(aclChangeSetIds, fromId, maxResults);
+
+ Map model = new HashMap(1, 1.0f);
+ model.put("acls", acls);
+
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("Result: \n\tRequest: " + req + "\n\tModel: " + model);
+ }
+
+ return model;
+ }
+}
diff --git a/source/java/org/alfresco/repo/web/scripts/solr/AclsReadersGet.java b/source/java/org/alfresco/repo/web/scripts/solr/AclsReadersGet.java
new file mode 100644
index 0000000000..5f8c5ab021
--- /dev/null
+++ b/source/java/org/alfresco/repo/web/scripts/solr/AclsReadersGet.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2005-2011 Alfresco Software Limited.
+ *
+ * This file is part of Alfresco
+ *
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ */
+package org.alfresco.repo.web.scripts.solr;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.alfresco.repo.solr.AclReaders;
+import org.alfresco.repo.solr.SOLRTrackingComponent;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.springframework.extensions.surf.util.Content;
+import org.springframework.extensions.webscripts.DeclarativeWebScript;
+import org.springframework.extensions.webscripts.Status;
+import org.springframework.extensions.webscripts.WebScriptException;
+import org.springframework.extensions.webscripts.WebScriptRequest;
+
+/**
+ * Support for SOLR: Track ACLs
+ *
+ * @since 4.0
+ */
+public class AclsReadersGet extends DeclarativeWebScript
+{
+ protected static final Log logger = LogFactory.getLog(AclsReadersGet.class);
+
+ private SOLRTrackingComponent solrTrackingComponent;
+
+ public void setSolrTrackingComponent(SOLRTrackingComponent solrTrackingComponent)
+ {
+ this.solrTrackingComponent = solrTrackingComponent;
+ }
+
+ protected Map executeImpl(WebScriptRequest req, Status status)
+ {
+ try
+ {
+ Map model = buildModel(req);
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("Result: \n\tRequest: " + req + "\n\tModel: " + model);
+ }
+ return model;
+ }
+ catch(IOException e)
+ {
+ throw new WebScriptException("IO exception parsing request", e);
+ }
+ catch(JSONException e)
+ {
+ throw new WebScriptException("Invalid JSON", e);
+ }
+ }
+
+ private Map buildModel(WebScriptRequest req) throws JSONException, IOException
+ {
+ List aclIds = null;
+
+ Content content = req.getContent();
+ if (content == null)
+ {
+ throw new WebScriptException("Request content is empty");
+ }
+ JSONObject o = new JSONObject(content.getContent());
+ JSONArray aclIdsJSON = o.has("aclIds") ? o.getJSONArray("aclIds") : null;
+ if (aclIdsJSON == null)
+ {
+ throw new WebScriptException(
+ Status.STATUS_BAD_REQUEST,
+ "Parameter 'aclIds' not provided in request content.");
+ }
+ else if (aclIdsJSON.length() == 0 || aclIdsJSON.length() > 512)
+ {
+ throw new WebScriptException(
+ Status.STATUS_BAD_REQUEST,
+ "Parameter 'aclIds' must hold from 1 to 512 IDs.");
+ }
+ aclIds = new ArrayList(aclIdsJSON.length());
+ for (int i = 0; i < aclIdsJSON.length(); i++)
+ {
+ aclIds.add(aclIdsJSON.getLong(i));
+ }
+
+ // Request according to the paging query style required
+ List aclsReaders = solrTrackingComponent.getAclsReaders(aclIds);
+
+ Map model = new HashMap(1, 1.0f);
+ model.put("aclsReaders", aclsReaders);
+
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("Result: \n\tRequest: " + req + "\n\tModel: " + model);
+ }
+
+ return model;
+ }
+}
diff --git a/source/java/org/alfresco/repo/web/scripts/solr/NodesGet.java b/source/java/org/alfresco/repo/web/scripts/solr/NodesGet.java
index 8f3398a51d..4a1fadd135 100644
--- a/source/java/org/alfresco/repo/web/scripts/solr/NodesGet.java
+++ b/source/java/org/alfresco/repo/web/scripts/solr/NodesGet.java
@@ -180,19 +180,20 @@ public class NodesGet extends DeclarativeWebScript
/**
* Callback for DAO get nodes query
- *
*/
private static class WebNodeQueryCallback implements NodeQueryCallback
{
private ArrayList nodes;
- public WebNodeQueryCallback(int count) {
+ public WebNodeQueryCallback(int count)
+ {
super();
nodes = new ArrayList(count == 0 || count == Integer.MAX_VALUE ? 100 : count);
}
@Override
- public boolean handleNode(Node node) {
+ public boolean handleNode(Node node)
+ {
nodes.add(node);
// continue - get next node
@@ -204,5 +205,4 @@ public class NodesGet extends DeclarativeWebScript
return nodes;
}
}
-
}
\ No newline at end of file
diff --git a/source/java/org/alfresco/repo/web/scripts/solr/SOLRSerializer.java b/source/java/org/alfresco/repo/web/scripts/solr/SOLRSerializer.java
index 16d7ab7599..66d791b7a2 100644
--- a/source/java/org/alfresco/repo/web/scripts/solr/SOLRSerializer.java
+++ b/source/java/org/alfresco/repo/web/scripts/solr/SOLRSerializer.java
@@ -41,6 +41,7 @@ import org.alfresco.service.cmr.repository.Path;
import org.alfresco.service.cmr.repository.Path.AttributeElement;
import org.alfresco.service.cmr.repository.Path.ChildAssocElement;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
+import org.alfresco.service.cmr.repository.datatype.TypeConversionException;
import org.alfresco.service.cmr.repository.datatype.TypeConverter;
import org.alfresco.service.cmr.repository.datatype.TypeConverter.Converter;
import org.alfresco.service.namespace.NamespaceService;
@@ -92,16 +93,24 @@ import org.json.JSONObject;
this.namespaceService = namespaceService;
}
+ public String serializeToString(Serializable value)
+ {
+ if (value != null && typeConverter.INSTANCE.getConverter(value.getClass(), String.class) == null)
+ {
+ // There is no converter
+ return value.toString();
+ }
+ else
+ {
+ return typeConverter.INSTANCE.convert(String.class, value);
+ }
+ }
+
public T serializeValue(Class targetClass, Object value) throws JSONException
{
return typeConverter.INSTANCE.convert(targetClass, value);
}
- public String serializeToString(Serializable value)
- {
- return typeConverter.INSTANCE.convert(String.class, value);
- }
-
@SuppressWarnings("unchecked")
public PropertyValue serialize(QName propName, Serializable value) throws IOException, JSONException
{
@@ -111,13 +120,12 @@ import org.json.JSONObject;
}
PropertyDefinition propertyDef = dictionaryService.getProperty(propName);
- if(propertyDef == null)
+ if (propertyDef == null)
{
- throw new IllegalArgumentException("Could not find property definition for property " + propName);
+ // Treat it as text
+ return new PropertyValue(true, serializeToString(value));
}
-
- boolean isMulti = propertyDef.isMultiValued();
- if(isMulti)
+ else if (propertyDef.isMultiValued())
{
if(!(value instanceof Collection))
{
@@ -129,7 +137,7 @@ import org.json.JSONObject;
JSONArray body = new JSONArray();
for(Serializable o : c)
{
- body.put(serializeValue(String.class, o));
+ body.put(serializeToString(o));
}
return new PropertyValue(false, body.toString());
@@ -151,7 +159,7 @@ import org.json.JSONObject;
{
encodeString = true;
}
- return new PropertyValue(encodeString, serializeValue(String.class, value));
+ return new PropertyValue(encodeString, serializeToString(value));
}
}
diff --git a/source/java/org/alfresco/repo/web/scripts/solr/SOLRWebScriptTest.java b/source/java/org/alfresco/repo/web/scripts/solr/SOLRWebScriptTest.java
index b1b7ffcd8f..2eb5292529 100644
--- a/source/java/org/alfresco/repo/web/scripts/solr/SOLRWebScriptTest.java
+++ b/source/java/org/alfresco/repo/web/scripts/solr/SOLRWebScriptTest.java
@@ -26,17 +26,21 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.domain.node.NodeDAO;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
+import org.alfresco.repo.solr.Acl;
+import org.alfresco.repo.solr.AclChangeSet;
+import org.alfresco.repo.solr.AclReaders;
+import org.alfresco.repo.solr.SOLRTrackingComponent;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.repo.web.scripts.BaseWebScriptTest;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.model.FileInfo;
-import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.Path;
@@ -61,19 +65,15 @@ import org.springframework.extensions.webscripts.TestWebScriptServer.Response;
*
* @since 4.0
*/
-// TODO check txn ids are correct - how to get txn ids?
-// TODO create a node in txn1 and delete it in txn2 - only the delete in txn2 appears. Will SOLR not then see this as deletion of a non-existent node?
-// TODO test getTxns: combinations of fromTxnId, fromCommitTime, maxResults
-// TODO move/duplicate tests to SOLRDAO tests
public class SOLRWebScriptTest extends BaseWebScriptTest
{
protected static final Log logger = LogFactory.getLog(SOLRWebScriptTest.class);
private ApplicationContext ctx;
+ private SOLRTrackingComponent solrTrackingComponent;
private NodeDAO nodeDAO;
private TransactionService transactionService;
private NodeService nodeService;
- private ContentService contentService;
private FileFolderService fileFolderService;
private RetryingTransactionHelper txnHelper;
private NamespaceService namespaceService;
@@ -81,33 +81,8 @@ public class SOLRWebScriptTest extends BaseWebScriptTest
private String admin;
private StoreRef storeRef;
- private StoreRef storeRef1;
private NodeRef rootNodeRef;
- private NodeRef rootNodeRef1;
-
- private NodeRef container1;
- private NodeRef container2;
private NodeRef container3;
- private NodeRef container4;
- private NodeRef container5;
- private NodeRef content1;
- private NodeRef content2;
- private NodeRef content3;
-
- private long container1NodeID;
- private long container2NodeID;
- private long container3NodeID;
- private long container4NodeID;
- private long container5NodeID;
- private long content1NodeID;
- private long content2NodeID;
- private long content3NodeID;
- private long content4NodeID;
- private long content5NodeID;
-
- private JSONObject firstNode;
- private JSONObject secondNode;
- private JSONObject thirdNode;
private ArrayList contents = new ArrayList(100);
private List nodeIDs = new ArrayList(100);
@@ -121,11 +96,11 @@ public class SOLRWebScriptTest extends BaseWebScriptTest
ServiceRegistry serviceRegistry = (ServiceRegistry) ctx.getBean(ServiceRegistry.SERVICE_REGISTRY);
transactionService = serviceRegistry.getTransactionService();
nodeService = serviceRegistry.getNodeService();
- contentService = serviceRegistry.getContentService();
fileFolderService = serviceRegistry.getFileFolderService();
namespaceService = serviceRegistry.getNamespaceService();
txnHelper = transactionService.getRetryingTransactionHelper();
nodeDAO = (NodeDAO)ctx.getBean("nodeDAO");
+ solrTrackingComponent = (SOLRTrackingComponent) ctx.getBean("solrTrackingComponent");
admin = AuthenticationUtil.getAdminUserName();
@@ -133,9 +108,6 @@ public class SOLRWebScriptTest extends BaseWebScriptTest
storeRef = nodeService.createStore(StoreRef.PROTOCOL_WORKSPACE, getName() + ".1." + System.currentTimeMillis());
rootNodeRef = nodeService.getRootNode(storeRef);
-
- storeRef1 = nodeService.createStore(StoreRef.PROTOCOL_WORKSPACE, getName() + ".2." + System.currentTimeMillis());
- rootNodeRef1 = nodeService.getRootNode(storeRef1);
}
@Override
@@ -160,7 +132,7 @@ public class SOLRWebScriptTest extends BaseWebScriptTest
JSONArray transactions = json.getJSONArray("transactions");
- System.out.println("Got " + transactions.length() + " txns in " + (endTime - startTime) + " ms");
+ logger.debug("Got " + transactions.length() + " txns in " + (endTime - startTime) + " ms");
return transactions;
}
@@ -181,7 +153,119 @@ public class SOLRWebScriptTest extends BaseWebScriptTest
JSONArray aclChangeSets = json.getJSONArray("aclChangeSets");
- System.out.println("Got " + aclChangeSets.length() + " txns in " + (endTime - startTime) + " ms");
+ logger.debug("Got " + aclChangeSets.length() + " txns in " + (endTime - startTime) + " ms");
+ }
+
+ public void testAclsGet() throws Exception
+ {
+ List aclChangeSets = solrTrackingComponent.getAclChangeSets(null, null, 100);
+ if (aclChangeSets.size() == 0)
+ {
+ return; // Can't test, but very unlikely
+ }
+ // Build JSON using these
+ JSONObject json = new JSONObject();
+ JSONArray aclChangeSetIdsJSON = new JSONArray();
+ int count = 0;
+ List aclChangeSetIds = new ArrayList();
+ for (AclChangeSet aclChangeSet : aclChangeSets)
+ {
+ if (count >= 512)
+ {
+ break;
+ }
+ if (aclChangeSet.getAclCount() == 0)
+ {
+ continue; // No ACLs
+ }
+ Long aclChangeSetId = aclChangeSet.getId();
+ aclChangeSetIdsJSON.put(aclChangeSetId);
+ aclChangeSetIds.add(aclChangeSetId);
+ count++;
+ }
+ json.put("aclChangeSetIds", aclChangeSetIdsJSON);
+
+ String url = "/api/solr/acls";
+ TestWebScriptServer.PostRequest req = new TestWebScriptServer.PostRequest(url, json.toString(), "application/json");
+ Response response = sendRequest(req, Status.STATUS_OK, admin);
+ if(logger.isDebugEnabled())
+ {
+ logger.debug(response.getContentAsString());
+ }
+ json = new JSONObject(response.getContentAsString());
+ JSONArray acls = json.getJSONArray("acls");
+
+ // Check
+ List aclsCheck = solrTrackingComponent.getAcls(aclChangeSetIds, null, 512);
+ assertEquals("Script and API returned different number of results", aclsCheck.size(), acls.length());
+ }
+
+ public void testAclReadersGet() throws Exception
+ {
+ List aclChangeSets = solrTrackingComponent.getAclChangeSets(null, null, 1024);
+ List aclChangeSetIds = new ArrayList(50);
+ for (AclChangeSet aclChangeSet : aclChangeSets)
+ {
+ if (aclChangeSet.getAclCount() > 0)
+ {
+ aclChangeSetIds.add(aclChangeSet.getId());
+ break;
+ }
+ }
+ if (aclChangeSetIds.size() == 0)
+ {
+ // No ACLs; not likely
+ }
+ List acls = solrTrackingComponent.getAcls(aclChangeSetIds, null, 1024);
+ List aclIds = new ArrayList(acls.size());
+ JSONObject json = new JSONObject();
+ JSONArray aclIdsJSON = new JSONArray();
+ for (Acl acl : acls)
+ {
+ Long aclId = acl.getId();
+ aclIds.add(aclId);
+ aclIdsJSON.put(aclId);
+ }
+ json.put("aclIds", aclIdsJSON);
+
+ // Now get the readers
+ List aclsReaders = solrTrackingComponent.getAclsReaders(aclIds);
+ assertEquals("Should have same number of ACLs as supplied", aclIds.size(), aclsReaders.size());
+ assertTrue("Must have *some* ACLs here", aclIds.size() > 0);
+ Map> readersByAclId = new HashMap>();
+ for (AclReaders aclReaders : aclsReaders)
+ {
+ readersByAclId.put(aclReaders.getAclId(), aclReaders.getReaders());
+ }
+
+ // Now query using the webscript
+ String url = "/api/solr/aclsReaders";
+ TestWebScriptServer.PostRequest req = new TestWebScriptServer.PostRequest(url, json.toString(), "application/json");
+ Response response = sendRequest(req, Status.STATUS_OK, admin);
+ if(logger.isDebugEnabled())
+ {
+ logger.debug(response.getContentAsString());
+ }
+ json = new JSONObject(response.getContentAsString());
+ JSONArray aclsReadersJSON = json.getJSONArray("aclsReaders");
+ // Check
+ assertEquals("Script and API returned different number of results", readersByAclId.size(), aclsReadersJSON.length());
+
+ // Iterate of the JSON and ensure that the list of ACL readers is correct
+ for (int i = 0; i < aclsReadersJSON.length(); i++)
+ {
+ // Choose an ACL and check the readers
+ JSONObject aclReadersJSON = aclsReadersJSON.getJSONObject(i);
+ Long aclIdJSON = aclReadersJSON.getLong("aclId");
+ Set readersCheck = readersByAclId.get(aclIdJSON);
+ JSONArray readersJSON = aclReadersJSON.getJSONArray("readers");
+ assertEquals("Readers list for ACL " + aclIdJSON + " is wrong. ", readersCheck.size(), readersJSON.length());
+ for (int j = 0; j < readersJSON.length(); j++)
+ {
+ String readerJSON = readersJSON.getString(j);
+ assertTrue("Found reader not in check set: " + readerJSON, readersCheck.contains(readerJSON));
+ }
+ }
}
private JSONArray getNodes(GetNodesParameters parameters, int maxResults, int expectedNumNodes) throws Exception
@@ -253,7 +337,7 @@ public class SOLRWebScriptTest extends BaseWebScriptTest
{
logger.debug(response.getContentAsString());
}
- //System.out.println("getNodes: " + response.getContentAsString());
+ //logger.debug("getNodes: " + response.getContentAsString());
JSONObject jsonResponse = new JSONObject(response.getContentAsString());
jsonResponse.write(new PrintWriter(System.out));
@@ -261,129 +345,13 @@ public class SOLRWebScriptTest extends BaseWebScriptTest
//assertEquals("Node count is incorrect", nodes.length(), json.getInt("count"));
- System.out.println("Got " + nodes.length() + " nodes in " + (endTime - startTime) + " ms");
+ logger.debug("Got " + nodes.length() + " nodes in " + (endTime - startTime) + " ms");
assertEquals("Number of returned node meta data results is incorrect", expectedNumNodes, nodes.length());
return nodes;
}
- private void buildTransactions1()
- {
- txnHelper.doInTransaction(new RetryingTransactionCallback()
- {
- public Void execute() throws Throwable
- {
- PropertyMap props = new PropertyMap();
- props.put(ContentModel.PROP_NAME, "Container1");
- container1 = nodeService.createNode(
- rootNodeRef,
- ContentModel.ASSOC_CHILDREN,
- ContentModel.ASSOC_CHILDREN,
- ContentModel.TYPE_FOLDER,
- props).getChildRef();
-
- System.out.println("container1 = " + container1);
-
- FileInfo content1Info = fileFolderService.create(container1, "Content1", ContentModel.TYPE_CONTENT);
- content1 = content1Info.getNodeRef();
-
- container1NodeID = getNodeID(container1);
- content1NodeID = getNodeID(content1);
-
- if(logger.isDebugEnabled())
- {
- logger.debug("content1 = " + content1);
- }
-
- return null;
- }
- });
-
- txnHelper.doInTransaction(new RetryingTransactionCallback()
- {
- public Void execute() throws Throwable
- {
- FileInfo content2Info = fileFolderService.create(container1, "Content2", ContentModel.TYPE_CONTENT);
- content2 = content2Info.getNodeRef();
- content2NodeID = getNodeID(content2);
-
- if(logger.isDebugEnabled())
- {
- logger.debug("content2 = " + content2);
- }
-
- nodeService.addAspect(content1, ContentModel.ASPECT_TEMPORARY, null);
- fileFolderService.delete(content1);
-
- return null;
- }
- });
- }
-
- private void buildTransactions2()
- {
- txnHelper.doInTransaction(new RetryingTransactionCallback()
- {
- public Void execute() throws Throwable
- {
- PropertyMap props = new PropertyMap();
- props.put(ContentModel.PROP_NAME, "Container2");
- container2 = nodeService.createNode(
- rootNodeRef,
- ContentModel.ASSOC_CHILDREN,
- ContentModel.ASSOC_CHILDREN,
- ContentModel.TYPE_FOLDER,
- props).getChildRef();
- container2NodeID = getNodeID(container2);
- if(logger.isDebugEnabled())
- {
- logger.debug("container2 = " + container2);
- }
-
- FileInfo content1Info = fileFolderService.create(container2, "Content1", ContentModel.TYPE_CONTENT);
- content1 = content1Info.getNodeRef();
- content1NodeID = getNodeID(content1);
-
- if(logger.isDebugEnabled())
- {
- logger.debug("content1 = " + content1);
- }
-
- FileInfo content2Info = fileFolderService.create(container2, "Content2", ContentModel.TYPE_CONTENT);
- content2 = content2Info.getNodeRef();
- content2NodeID = getNodeID(content2);
- if(logger.isDebugEnabled())
- {
- logger.debug("content2 = " + content2);
- }
-
- return null;
- }
- });
-
- txnHelper.doInTransaction(new RetryingTransactionCallback()
- {
- public Void execute() throws Throwable
- {
- FileInfo content3Info = fileFolderService.create(container2, "Content3", ContentModel.TYPE_CONTENT);
- content3 = content3Info.getNodeRef();
- content3NodeID = getNodeID(content3);
- if(logger.isDebugEnabled())
- {
- logger.debug("content3 = " + content3);
- }
-
- nodeService.addAspect(content1, ContentModel.ASPECT_TEMPORARY, null);
- fileFolderService.delete(content1);
-
- nodeService.setProperty(content3, ContentModel.PROP_NAME, "Content 3 New Name");
-
- return null;
- }
- });
- }
-
private List getTransactionIds(JSONArray transactions) throws JSONException
{
List txnIds = new ArrayList(transactions.length());
@@ -398,18 +366,20 @@ public class SOLRWebScriptTest extends BaseWebScriptTest
return txnIds;
}
- public static String join(Collection s, String delimiter) {
+ public static String join(Collection