Merged DEV/SWIFT to HEAD

27125: Subtasks of ALF-7072: RSOLR 013: Remote API to get ACLs and readers
          - ALF-8334: RSOLR 013: Modify ACL schema to record change times
          - ALF-8336: RSOLR 013: DB upgrade scripts for ACL changes
          - TODO: Query APIs
   27128: Added TooManyResultsException as a concurrency detection trigger
          - Usually too many results indicates that the DB table key is not as specific as it should be,
            but it's AVM that showed this up.
   27132: Clean up: javadocs; non-javadocs; uncommented fields; @since tags; etc.
   27134: Removed empty directory
   27135: Fix for ALF-8333: CMIS query: JOIN on an aspect results in CmisInvalidArgumentException
          - incorrect scope used when building orderings
   27139: Fixed SORL transaction tracking queries
          - Queries were using incompatible boolean comparisons
          - Added SOLRDAO to test suite
          - Cleaned up code and reformatted code
   27141: Minor additions to CannedQuery interface
          - get parameter bean
          - construct sort details from a list
          - ALF-7167: Canned queries
   27146: RINF 09 / RINF 10: DB-based paged query for get children (DocLib & CMIS) 
          - milestone check-in for sprint demo & review (WIP)
          - added new FileFolderService (paged) list query (public API is subject to change)
          - moved temp JavaScript sorting to Java
          - example usage by DocLib (via ScriptNode) and CMIS (via AlfrescoCmisService)
          - implemented as demo "canned query" including embedded use of "list" permission interceptor
          - ALF-7402 / ALF-7168
   27150: RINF 09 / RINF 10: DB-based paged query for get children (DocLib & CMIS) 
          - missed file (follow-on to r27146)
   27158: ALF-7070, ALF-7072: SOLR tracking (node and changeset)
          - Pulled non-DAO code into SOLRTrackingComponent
          - DAO code and related tests just test basic CRUD
          - SOLRTrackingComponent does complex cross-schema manipulation
   27159: Fixed line ending and removed svn:eol-style
   27160: ALF-8334: RSOLR 013: Fixed SQL Server syntax
   27165: RINF 09 / RINF 10: DB-based paged query for get children (DocLib & CMIS) 
          - fix listDeepFolders (causing Imap*Test to fail) 
          - all private methods now order files followed by folders
		    (consistent with existing public APIs such as FileFolderService.search & ScriptNode.childFileFolders*)
          - follow-on to r27146
   28271: Consolidate diagnostic logging for max perm checks (ALF-8388 + ALF-8419)
          - note: this should be a trivial merge to HEAD

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@28292 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Derek Hulley
2011-06-08 17:29:54 +00:00
parent ed487863f7
commit c47ecc4208
11 changed files with 194 additions and 224 deletions

View File

@@ -21,6 +21,8 @@ function getDoclist()
// Try to find a filter query based on the passed-in arguments
var allNodes = [],
totalRecords,
paged = false,
favourites = Common.getFavourites(),
filterParams = Filters.getFilterParams(filter, parsedArgs,
{
@@ -39,30 +41,28 @@ function getDoclist()
{
var ignoreTypes=["cm:thumbnail", "fm:forums","fm:forum","fm:topic","fm:post"];
allNodes = parentNode.childFileFolders(true, true, ignoreTypes);
var skip = -1;
var max = -1;
// TODO push down sorting to FileFolderService.list (see also AlfrescoCmisService.getChildren)
if ((args.sortField == null) || (args.sortField == "cm:name"))
if (args.size != null)
{
sortByName(allNodes, args.sortAsc);
}
else if (args.sortField == "cm:content.size")
max = args.size;
if (args.pos > 0)
{
sortBySize(allNodes, args.sortAsc);
skip = (args.pos - 1) * max;
}
else if (args.sortField == "cm:content.mimetype")
{
sortByMimetype(allNodes, args.sortAsc);
}
else if ((args.sortField == "cm:created") || (args.sortField == "cm:modified"))
{
sortByPropDate(allNodes, args.sortAsc, args.sortField);
}
else
{
// assume string (=> supports toLowerCase)
sortByPropStr(allNodes, args.sortAsc, args.sortField);
}
var sortField = (args.sortField == null ? "cm:name" : args.sortField);
var sortAsc = (((args.sortAsc == null) || (args.sortAsc == "true")) ? true : false);
var pagedResult = parentNode.childFileFolders(true, true, ignoreTypes, skip, max, sortField, sortAsc);
allNodes = pagedResult.result;
totalRecords = pagedResult.totalCount;
paged = true;
}
}
else
@@ -112,7 +112,7 @@ function getDoclist()
// Node type counts
var folderNodesCount = folderNodes.length,
documentNodesCount = documentNodes.length,
nodes, totalRecords;
nodes;
if (parsedArgs.type === "documents")
{
@@ -123,15 +123,19 @@ function getDoclist()
// TODO: Sorting with folders at end -- swap order of concat()
nodes = folderNodes.concat(documentNodes);
}
totalRecords = nodes.length;
// Pagination
var pageSize = args.size || nodes.length,
pagePos = args.pos || "1",
startIndex = (pagePos - 1) * pageSize;
if (! paged)
{
totalRecords = nodes.length;
// Trim the nodes array down to the page size
nodes = nodes.slice(startIndex, pagePos * pageSize);
}
// Common or variable parent container?
var parent = null;
@@ -257,89 +261,6 @@ function getDoclist()
});
}
// TEMP
function sortByName(arr, sortAsc)
{
arr.sort
(
function( a, b )
{
return ((sortAsc == null) || (sortAsc == "true"))
? (b.name.toLowerCase() > a.name.toLowerCase() ? -1 : 1)
: (a.name.toLowerCase() > b.name.toLowerCase() ? -1 : 1);
}
);
}
// TEMP
function sortBySize(arr, sortAsc)
{
arr.sort
(
function( a, b )
{
return ((sortAsc == null) || (sortAsc == "true"))
? (b.size > a.size ? -1 : 1)
: (a.size > b.size ? -1 : 1);
}
);
}
// TEMP
function sortByMimetype(arr, sortAsc)
{
arr.sort
(
function( a, b )
{
return ((sortAsc == null) || (sortAsc == "true"))
? (b.mimetype.toLowerCase() > a.mimetype.toLowerCase() ? -1 : 1)
: (a.mimetype.toLowerCase() > b.mimetype.toLowerCase() ? -1 : 1);
}
);
}
// TEMP
function sortByPropStr(arr, sortAsc, sortField)
{
arr.sort
(
function( a, b )
{
var aStr = a.properties[sortField];
if (aStr == null)
{
aStr = "";
}
var bStr = b.properties[sortField];
if (bStr == null)
{
bStr = "";
}
return ((sortAsc == null) || (sortAsc == "true"))
? (bStr == "" && aStr != "" ? -1 : (bStr != "" && aStr == "" ? 1 : (bStr.toLowerCase() > aStr.toLowerCase() ? -1 : 1)))
: (aStr == "" && bStr != "" ? -1 : (aStr != "" && bStr == "" ? 1 : (aStr.toLowerCase() > bStr.toLowerCase() ? -1 : 1)));
}
);
}
// TEMP
function sortByPropDate(arr, sortAsc, sortField)
{
arr.sort
(
function( a, b )
{
return ((sortAsc == null) || (sortAsc == "true"))
? (b.properties[sortField] - a.properties[sortField])
: (a.properties[sortField] - b.properties[sortField]);
}
);
}
/**
* Document List Component: doclist
*/

View File

@@ -1230,19 +1230,19 @@
<bean id="webscript.org.alfresco.repository.solr.getTransactions.get"
class="org.alfresco.repo.web.scripts.solr.GetTransactions"
parent="webscript">
<property name="solrDAO" ref="solrDAO"/>
<property name="solrTrackingComponent" ref="solrTrackingComponent"/>
</bean>
<bean id="webscript.org.alfresco.repository.solr.getNodes.post"
class="org.alfresco.repo.web.scripts.solr.GetNodes"
parent="webscript">
<property name="solrDAO" ref="solrDAO"/>
<property name="solrTrackingComponent" ref="solrTrackingComponent"/>
</bean>
<bean id="webscript.org.alfresco.repository.solr.getNodesMetaData.post"
class="org.alfresco.repo.web.scripts.solr.GetNodesMetaData"
parent="webscript">
<property name="solrDAO" ref="solrDAO"/>
<property name="solrTrackingComponent" ref="solrTrackingComponent"/>
<property name="solrSerializer" ref="solrSerializer"/>
</bean>

View File

@@ -0,0 +1,74 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package org.alfresco.repo.web.scripts.solr;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.alfresco.repo.domain.solr.SOLRDAO;
import org.alfresco.repo.domain.solr.Transaction;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.extensions.webscripts.DeclarativeWebScript;
import org.springframework.extensions.webscripts.Status;
import org.springframework.extensions.webscripts.WebScriptRequest;
/**
* Support for SOLR: Track ACL Change Sets
*
* @since 4.0
*/
public class GetAclChangeSets extends DeclarativeWebScript
{
protected static final Log logger = LogFactory.getLog(GetAclChangeSets.class);
private SOLRDAO solrDAO;
/**
* @param solrDAO the SOLDAO to set
*/
public void setSolrDAO(SOLRDAO solrDAO)
{
this.solrDAO = solrDAO;
}
protected Map<String, Object> executeImpl(WebScriptRequest req, Status status)
{
String minAclChangeSetIdParam = req.getParameter("minAclChangeSetId");
String fromCommitTimeParam = req.getParameter("fromCommitTime");
String maxResultsParam = req.getParameter("maxResults");
Long minAclChangeSetId = (minAclChangeSetIdParam == null ? null : Long.valueOf(minAclChangeSetIdParam));
Long fromCommitTime = (fromCommitTimeParam == null ? null : Long.valueOf(fromCommitTimeParam));
int maxResults = (maxResultsParam == null ? 0 : Integer.valueOf(maxResultsParam));
List<Transaction> transactions = solrDAO.getTransactions(minAclChangeSetId, fromCommitTime, maxResults);
Map<String, Object> model = new HashMap<String, Object>(1, 1.0f);
model.put("transactions", transactions);
if (logger.isDebugEnabled())
{
logger.debug("Result: \n\tRequest: " + req + "\n\tModel: " + model);
}
return model;
}
}

View File

@@ -22,7 +22,6 @@ import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
@@ -37,7 +36,6 @@ import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.TransformationOptions;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.Pair;
import org.apache.commons.httpclient.HttpStatus;
@@ -48,12 +46,10 @@ import org.springframework.extensions.webscripts.WebScriptRequest;
import org.springframework.extensions.webscripts.WebScriptResponse;
/**
*
* A web service to return the text content (transformed if required) of a node's
* content property.
*
* @since 4.0
*
*/
public class GetNodeContent extends StreamContent
{
@@ -87,7 +83,7 @@ public class GetNodeContent extends StreamContent
}
/**
* @see org.alfresco.web.scripts.WebScript#execute(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse)
* @in
*/
public void execute(WebScriptRequest req, WebScriptResponse res) throws IOException
{
@@ -155,19 +151,11 @@ public class GetNodeContent extends StreamContent
return;
}
// optimisation - already text so just return the content directly
// TODO - better way of doing this?
if(reader.getMimetype().startsWith("text/"))
{
textReader = reader;
}
else
{
// Perform transformation catering for mimetype AND encoding
ContentWriter writer = contentService.getTempWriter();
writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN);
writer.setEncoding("UTF-8");
writer.setEncoding("UTF-8"); // Expect transformers to produce UTF-8
TransformationOptions options = new TransformationOptions();
ContentTransformer transformer = contentService.getTransformer(reader.getMimetype(), MimetypeMap.MIMETYPE_TEXT_PLAIN);
if(transformer == null)
{
@@ -178,7 +166,6 @@ public class GetNodeContent extends StreamContent
try
{
// TODO how to ensure UTF-8 in the transformed text?
transformer.transform(reader, writer);
}
catch (ContentIOException e)
@@ -193,11 +180,11 @@ public class GetNodeContent extends StreamContent
// Check that the reader is a view onto something concrete
if (textReader == null || !textReader.exists())
{
transformException = new ContentIOException("The transformation did not write any content, yet: \n"
transformException = new ContentIOException(
"The transformation did not write any content, yet: \n"
+ " transformer: " + transformer + "\n" + " temp writer: " + writer);
}
}
}
if(transformException != null)
{
@@ -210,17 +197,5 @@ public class GetNodeContent extends StreamContent
res.setStatus(HttpStatus.SC_OK);
streamContentImpl(req, res, textReader, false, modified, String.valueOf(modified.getTime()), null);
}
/* writer.addListener(new ContentStreamListener()
{
@Override
public void contentStreamClosed() throws ContentIOException
{
// TODO Auto-generated method stub
}
});*/
}
}

View File

@@ -27,9 +27,9 @@ import java.util.Map;
import java.util.Set;
import org.alfresco.repo.domain.node.Node;
import org.alfresco.repo.domain.solr.NodeParameters;
import org.alfresco.repo.domain.solr.SOLRDAO;
import org.alfresco.repo.domain.solr.SOLRDAO.NodeQueryCallback;
import org.alfresco.repo.solr.NodeParameters;
import org.alfresco.repo.solr.SOLRTrackingComponent;
import org.alfresco.repo.solr.SOLRTrackingComponent.NodeQueryCallback;
import org.alfresco.service.namespace.QName;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -43,11 +43,11 @@ import org.springframework.extensions.webscripts.WebScriptException;
import org.springframework.extensions.webscripts.WebScriptRequest;
/**
* Support for SOLR. Get a list of nodes in the given transactions.
*
* Supports fromNodeId, toNodeId, count (all optional) to control the number of nodes returned
* e.g. (null, null, 1000) will return at most 1000 nodes starting from the first node in the first transaction.
* e.g. (1234, null, 1000) will return at most 1000 nodes starting from the node id 1234.
* Support for SOLR: Get a list of nodes in the given transactions.
* <p/>
* Supports fromNodeId, toNodeId, count (all optional) to control the number of nodes returned<br/>
* e.g. (null, null, 1000) will return at most 1000 nodes starting from the first node in the first transaction.<br/>
* e.g. (1234, null, 1000) will return at most 1000 nodes starting from the node id 1234.<br/>
*
* @since 4.0
*/
@@ -55,20 +55,13 @@ public class GetNodes extends DeclarativeWebScript
{
protected static final Log logger = LogFactory.getLog(GetNodes.class);
private SOLRDAO solrDAO;
private SOLRTrackingComponent solrTrackingComponent;
/**
* @param solrDAO the solrDAO to set
*/
public void setSolrDAO(SOLRDAO solrDAO)
public void setSolrTrackingComponent(SOLRTrackingComponent solrTrackingComponent)
{
this.solrDAO = solrDAO;
this.solrTrackingComponent = solrTrackingComponent;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.Status)
*/
@Override
protected Map<String, Object> executeImpl(WebScriptRequest req, Status status)
{
@@ -162,7 +155,7 @@ public class GetNodes extends DeclarativeWebScript
nodeParameters.setStoreProtocol(storeProtocol);
nodeParameters.setStoreIdentifier(storeIdentifier);
nodeParameters.setMaxResults(maxResults);
solrDAO.getNodes(nodeParameters, nodeQueryCallback);
solrTrackingComponent.getNodes(nodeParameters, nodeQueryCallback);
Map<String, Object> model = new HashMap<String, Object>(1, 1.0f);
List<Node> nodes = nodeQueryCallback.getNodes();

View File

@@ -27,11 +27,11 @@ import java.util.Map;
import java.util.Set;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.domain.solr.MetaDataResultsFilter;
import org.alfresco.repo.domain.solr.NodeMetaData;
import org.alfresco.repo.domain.solr.NodeMetaDataParameters;
import org.alfresco.repo.domain.solr.SOLRDAO;
import org.alfresco.repo.domain.solr.SOLRDAO.NodeMetaDataQueryCallback;
import org.alfresco.repo.solr.MetaDataResultsFilter;
import org.alfresco.repo.solr.NodeMetaData;
import org.alfresco.repo.solr.NodeMetaDataParameters;
import org.alfresco.repo.solr.SOLRTrackingComponent;
import org.alfresco.repo.solr.SOLRTrackingComponent.NodeMetaDataQueryCallback;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.Path;
@@ -49,21 +49,24 @@ import org.springframework.extensions.webscripts.WebScriptException;
import org.springframework.extensions.webscripts.WebScriptRequest;
// todo url parameter to remove whitespace in results - make it the default?
/**
* Support for SOLR: Get metadata for nodes given IDs, ranges of IDs, etc.
* <p/>
*
* @since 4.0
*/
public class GetNodesMetaData extends DeclarativeWebScript
{
protected static final Log logger = LogFactory.getLog(GetNodesMetaData.class);
private static final int INITIAL_DEFAULT_SIZE = 100;
private static final int BATCH_SIZE = 50;
private SOLRDAO solrDAO;
private SOLRTrackingComponent solrTrackingComponent;
private SOLRSerializer solrSerializer;
/**
* @param solrDAO the solrDAO to set
*/
public void setSolrDAO(SOLRDAO solrDAO)
public void setSolrTrackingComponent(SOLRTrackingComponent solrTrackingComponent)
{
this.solrDAO = solrDAO;
this.solrTrackingComponent = solrTrackingComponent;
}
public void setSolrSerializer(SOLRSerializer solrSerializer)
@@ -71,10 +74,6 @@ public class GetNodesMetaData extends DeclarativeWebScript
this.solrSerializer = solrSerializer;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.Status)
*/
@Override
protected Map<String, Object> executeImpl(WebScriptRequest req, Status status)
{
@@ -168,11 +167,12 @@ public class GetNodesMetaData extends DeclarativeWebScript
params.setToNodeId(toNodeId);
params.setMaxResults(maxResults);
solrDAO.getNodesMetadata(params, filter, new NodeMetaDataQueryCallback()
solrTrackingComponent.getNodesMetadata(params, filter, new NodeMetaDataQueryCallback()
{
private int counter = BATCH_SIZE;
private int numBatches = 0;
@Override
public boolean handleNodeMetaData(NodeMetaData nodeMetaData)
{
// need to perform data structure conversions that are compatible with Freemarker
@@ -218,8 +218,10 @@ public class GetNodesMetaData extends DeclarativeWebScript
}
}
/*
/**
* Bean to store node meta data for use by FreeMarker templates
*
* @since 4.0
*/
public static class FreemarkerNodeMetaData
{
@@ -232,7 +234,6 @@ public class GetNodesMetaData extends DeclarativeWebScript
private List<String> paths;
private List<ChildAssociationRef> childAssocs;
@SuppressWarnings("unchecked")
public FreemarkerNodeMetaData(SOLRSerializer solrSerializer, NodeMetaData nodeMetaData) throws IOException, JSONException
{
setNodeId(nodeMetaData.getNodeId());

View File

@@ -23,6 +23,11 @@ import java.util.Set;
import org.alfresco.service.namespace.QName;
/**
* Input parameters for retrieving node details for SOLR.
*
* @since 4.0
*/
public class GetNodesParameters
{
private List<Long> transactionIds;

View File

@@ -24,6 +24,7 @@ import java.util.Map;
import org.alfresco.repo.domain.solr.SOLRDAO;
import org.alfresco.repo.domain.solr.Transaction;
import org.alfresco.repo.solr.SOLRTrackingComponent;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.extensions.webscripts.DeclarativeWebScript;
@@ -31,31 +32,21 @@ import org.springframework.extensions.webscripts.Status;
import org.springframework.extensions.webscripts.WebScriptRequest;
/**
* Support for SOLR. Get a list of transactions with a commit time greater than or equal to the given parameter.
* Support for SOLR: Get a list of transactions with a commit time greater than or equal to the given parameter.
*
* @since 4.0
*/
// TODO check that this does not return incomplete transactions i.e. commitTimeMs is set - does
// the sql account for this?
public class GetTransactions extends DeclarativeWebScript
{
protected static final Log logger = LogFactory.getLog(GetTransactions.class);
private SOLRDAO solrDAO;
private SOLRTrackingComponent solrTrackingComponent;
/**
* @param solrDAO the SOLDAO to set
*/
public void setSolrDAO(SOLRDAO solrDAO)
public void setSolrTrackingComponent(SOLRTrackingComponent solrTrackingComponent)
{
this.solrDAO = solrDAO;
this.solrTrackingComponent = solrTrackingComponent;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.Status)
*/
@Override
protected Map<String, Object> executeImpl(WebScriptRequest req, Status status)
{
String minTxnIdParam = req.getParameter("minTxnId");
@@ -66,7 +57,7 @@ public class GetTransactions extends DeclarativeWebScript
Long fromCommitTime = (fromCommitTimeParam == null ? null : Long.valueOf(fromCommitTimeParam));
int maxResults = (maxResultsParam == null ? 0 : Integer.valueOf(maxResultsParam));
List<Transaction> transactions = solrDAO.getTransactions(minTxnId, fromCommitTime, maxResults);
List<Transaction> transactions = solrTrackingComponent.getTransactions(minTxnId, fromCommitTime, maxResults);
Map<String, Object> model = new HashMap<String, Object>(1, 1.0f);
model.put("transactions", transactions);

View File

@@ -26,6 +26,11 @@ import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.Path;
import org.alfresco.service.namespace.QName;
/**
* Bean to carry node metadata
*
* @since 4.0
*/
public class NodeMetaData
{
private long id;

View File

@@ -1,6 +1,6 @@
package org.alfresco.repo.web.scripts.solr;
/*
/**
* Represents a property value to be used by Freemarker
*
* @since 4.0

View File

@@ -52,7 +52,12 @@ import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
class SOLRSerializer
/**
* SOLR conversions of values to JSON-compatible <tt>String</tt>.
*
* @since 4.0
*/
/* package */ class SOLRSerializer
{
protected static final Log logger = LogFactory.getLog(SOLRSerializer.class);