diff --git a/source/java/org/alfresco/rest/api/NetworkWebScriptGet.java b/source/java/org/alfresco/rest/api/NetworkWebScriptGet.java index bbfaeae9e7..6994e935c3 100644 --- a/source/java/org/alfresco/rest/api/NetworkWebScriptGet.java +++ b/source/java/org/alfresco/rest/api/NetworkWebScriptGet.java @@ -37,6 +37,7 @@ import org.alfresco.rest.framework.core.exceptions.ApiException; import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException; import org.alfresco.rest.framework.jacksonextensions.JacksonHelper.Writer; import org.alfresco.rest.framework.resource.parameters.Params; +import org.alfresco.rest.framework.tools.ResponseWriter; import org.alfresco.rest.framework.webscripts.ApiWebScript; import org.alfresco.rest.framework.webscripts.ResourceWebScriptHelper; import org.codehaus.jackson.JsonGenerationException; @@ -48,7 +49,7 @@ import org.springframework.extensions.webscripts.WebScriptException; import org.springframework.extensions.webscripts.WebScriptRequest; import org.springframework.extensions.webscripts.WebScriptResponse; -public class NetworkWebScriptGet extends ApiWebScript +public class NetworkWebScriptGet extends ApiWebScript implements ResponseWriter { private Networks networks; private ResourceWebScriptHelper helper; @@ -108,11 +109,11 @@ public class NetworkWebScriptGet extends ApiWebScript } catch (ApiException | WebScriptException apiException) { - assistant.renderException(apiException, res); + renderException(apiException, res, assistant); } catch (RuntimeException runtimeException) { - assistant.renderException(runtimeException, res); + renderException(runtimeException, res, assistant); } } } diff --git a/source/java/org/alfresco/rest/api/NetworksWebScriptGet.java b/source/java/org/alfresco/rest/api/NetworksWebScriptGet.java index 2abce4aaf8..bcbd3786a9 100644 --- a/source/java/org/alfresco/rest/api/NetworksWebScriptGet.java +++ b/source/java/org/alfresco/rest/api/NetworksWebScriptGet.java @@ -39,6 +39,8 @@ import org.alfresco.rest.framework.jacksonextensions.JacksonHelper.Writer; import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; import org.alfresco.rest.framework.resource.parameters.Paging; import org.alfresco.rest.framework.resource.parameters.Params; +import org.alfresco.rest.framework.tools.RecognizedParamsExtractor; +import org.alfresco.rest.framework.tools.ResponseWriter; import org.alfresco.rest.framework.webscripts.ApiWebScript; import org.alfresco.rest.framework.webscripts.ResourceWebScriptHelper; import org.codehaus.jackson.JsonGenerationException; @@ -56,7 +58,7 @@ import org.springframework.extensions.webscripts.WebScriptResponse; * @author steveglover * */ -public class NetworksWebScriptGet extends ApiWebScript +public class NetworksWebScriptGet extends ApiWebScript implements RecognizedParamsExtractor, ResponseWriter { private Networks networks; private ResourceWebScriptHelper helper; @@ -82,7 +84,7 @@ public class NetworksWebScriptGet extends ApiWebScript @Override public Void execute() throws Throwable { - final Paging paging = ResourceWebScriptHelper.findPaging(req); + final Paging paging = findPaging(req); // apply content type res.setContentType(Format.JSON.mimetype() + ";charset=UTF-8"); @@ -116,11 +118,11 @@ public class NetworksWebScriptGet extends ApiWebScript } catch (ApiException | WebScriptException apiException) { - assistant.renderException(apiException, res); + renderException(apiException, res, assistant); } catch (RuntimeException runtimeException) { - assistant.renderException(runtimeException, res); + renderException(runtimeException, res, assistant); } } } \ No newline at end of file diff --git a/source/java/org/alfresco/rest/api/PublicApiTenantWebScriptServletRuntime.java b/source/java/org/alfresco/rest/api/PublicApiTenantWebScriptServletRuntime.java index 7d715bbe3d..667fbc5eb0 100644 --- a/source/java/org/alfresco/rest/api/PublicApiTenantWebScriptServletRuntime.java +++ b/source/java/org/alfresco/rest/api/PublicApiTenantWebScriptServletRuntime.java @@ -33,12 +33,13 @@ import javax.servlet.http.HttpServletResponse; import org.alfresco.repo.web.scripts.TenantWebScriptServletRuntime; import org.alfresco.rest.framework.tools.ApiAssistant; +import org.alfresco.rest.framework.tools.ResponseWriter; import org.springframework.extensions.config.ServerProperties; import org.springframework.extensions.surf.util.URLDecoder; import org.springframework.extensions.webscripts.*; import org.springframework.extensions.webscripts.servlet.ServletAuthenticatorFactory; -public class PublicApiTenantWebScriptServletRuntime extends TenantWebScriptServletRuntime +public class PublicApiTenantWebScriptServletRuntime extends TenantWebScriptServletRuntime implements ResponseWriter { private static final Pattern CMIS_URI_PATTERN = Pattern.compile(".*/cmis/versions/[0-9]+\\.[0-9]+/.*"); private ApiAssistant apiAssistant; @@ -142,7 +143,7 @@ public class PublicApiTenantWebScriptServletRuntime extends TenantWebScriptServl else { try { - apiAssistant.renderException((Exception)exception, response); + renderException((Exception)exception, response, apiAssistant); } catch (IOException e) { logger.error("Internal error", e); throw new WebScriptException("Internal error", e); diff --git a/source/java/org/alfresco/rest/api/Queries.java b/source/java/org/alfresco/rest/api/Queries.java index 71d929d8a7..93d5b5f3c1 100644 --- a/source/java/org/alfresco/rest/api/Queries.java +++ b/source/java/org/alfresco/rest/api/Queries.java @@ -32,6 +32,7 @@ import org.alfresco.rest.api.model.Person; import org.alfresco.rest.api.model.Site; import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; import org.alfresco.rest.framework.resource.parameters.Parameters; +import org.alfresco.rest.framework.tools.RecognizedParamsExtractor; import org.alfresco.rest.framework.webscripts.ResourceWebScriptHelper; /** @@ -44,9 +45,9 @@ public interface Queries { // General static String PARAM_TERM = "term"; - static String PARAM_ORDERBY = ResourceWebScriptHelper.PARAM_ORDERBY; - static String PARAM_FIELDS = ResourceWebScriptHelper.PARAM_FILTER_FIELDS; - static String PARAM_INCLUDE = ResourceWebScriptHelper.PARAM_INCLUDE; + static String PARAM_ORDERBY = RecognizedParamsExtractor.PARAM_ORDERBY; + static String PARAM_FIELDS = RecognizedParamsExtractor.PARAM_FILTER_FIELDS; + static String PARAM_INCLUDE = RecognizedParamsExtractor.PARAM_INCLUDE; // Node query static String PARAM_ROOT_NODE_ID = "rootNodeId"; diff --git a/source/java/org/alfresco/rest/api/impl/QuickShareLinksImpl.java b/source/java/org/alfresco/rest/api/impl/QuickShareLinksImpl.java index c3ad3b964e..72bfa8e64d 100644 --- a/source/java/org/alfresco/rest/api/impl/QuickShareLinksImpl.java +++ b/source/java/org/alfresco/rest/api/impl/QuickShareLinksImpl.java @@ -57,7 +57,7 @@ import org.alfresco.rest.framework.resource.parameters.Parameters; import org.alfresco.rest.framework.resource.parameters.Params; import org.alfresco.rest.framework.resource.parameters.where.Query; import org.alfresco.rest.framework.resource.parameters.where.QueryHelper; -import org.alfresco.rest.framework.webscripts.ResourceWebScriptHelper; +import org.alfresco.rest.framework.tools.RecognizedParamsExtractor; import org.alfresco.rest.workflow.api.impl.MapBasedQueryWalker; import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.dictionary.DataTypeDefinition; @@ -107,7 +107,7 @@ import java.util.Set; * * @since publicapi1.0 */ -public class QuickShareLinksImpl implements QuickShareLinks, InitializingBean +public class QuickShareLinksImpl implements QuickShareLinks, RecognizedParamsExtractor, InitializingBean { private static final Log logger = LogFactory.getLog(QuickShareLinksImpl.class); @@ -404,7 +404,7 @@ public class QuickShareLinksImpl implements QuickShareLinks, InitializingBean // hmm ... can we simplify ? String filterStatusCreated = "(" + Renditions.PARAM_STATUS + "='" + Rendition.RenditionStatus.CREATED + "')"; - Query whereQuery = ResourceWebScriptHelper.getWhereClause(filterStatusCreated); + Query whereQuery = getWhereClause(filterStatusCreated); Params.RecognizedParams recParams = new Params.RecognizedParams(null, null, null, null, null, null, whereQuery, null, false); Parameters params = Params.valueOf(recParams, null, null, null); diff --git a/source/java/org/alfresco/rest/framework/jacksonextensions/SerializerOfCollectionWithPaging.java b/source/java/org/alfresco/rest/framework/jacksonextensions/SerializerOfCollectionWithPaging.java index faae2545c6..440ce789b7 100644 --- a/source/java/org/alfresco/rest/framework/jacksonextensions/SerializerOfCollectionWithPaging.java +++ b/source/java/org/alfresco/rest/framework/jacksonextensions/SerializerOfCollectionWithPaging.java @@ -29,6 +29,7 @@ import java.io.IOException; import org.alfresco.rest.framework.resource.SerializablePagedCollection; import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; +import org.alfresco.rest.framework.tools.RecognizedParamsExtractor; import org.alfresco.rest.framework.webscripts.ResourceWebScriptHelper; import org.codehaus.jackson.JsonGenerationException; import org.codehaus.jackson.JsonGenerator; @@ -90,8 +91,8 @@ public class SerializerOfCollectionWithPaging extends SerializerBase defaultResolver = new DefaultExceptionResolver(); private ExceptionResolver webScriptExceptionResolver; private ExceptionResolver resolver; private JacksonHelper jsonHelper; + /** + * Determines the api being used from the templateVars + * @param templateVars + * @return Api + */ public static Api determineApi(Map templateVars) { String apiScope = templateVars.get("apiScope"); @@ -92,6 +74,11 @@ public class ApiAssistant { return Api.valueOf(apiName,apiScope,apiVersion); } + /** + * Resolves an exception as a json error. + * @param exception + * @return ErrorResponse + */ public ErrorResponse resolveException(Exception ex) { ErrorResponse error = null; @@ -110,99 +97,6 @@ public class ApiAssistant { return error; } - /** - * Sets the response headers with any information we know about the content - * @param res WebScriptResponse - * @param contentInfo Content Information - */ - public void setContentInfoOnResponse(WebScriptResponse res, ContentInfo contentInfo) - { - if (contentInfo != null) - { - //Set content info on the response - res.setContentType(contentInfo.getMimeType()); - res.setContentEncoding(contentInfo.getEncoding()); - - if (res instanceof WrappingWebScriptResponse) - { - WrappingWebScriptResponse wrappedRes = ((WrappingWebScriptResponse) res); - res = wrappedRes.getNext(); - } - - if (res instanceof WebScriptServletResponse) - { - WebScriptServletResponse servletResponse = (WebScriptServletResponse) res; - if (contentInfo.getLength() > 0) - { - if (contentInfo.getLength() > 0 && contentInfo.getLength() < Integer.MAX_VALUE) - { - servletResponse.getHttpServletResponse().setContentLength((int) contentInfo.getLength()); - } - } - if (contentInfo.getLocale() != null) - { - servletResponse.getHttpServletResponse().setLocale(contentInfo.getLocale()); - } - } - } - } - - /** - * Renders an exception to the output stream as Json. - * @param exception - * @param response - * @throws IOException - */ - public void renderException(Exception exception, final WebScriptResponse response) throws IOException { - renderErrorResponse(resolveException(exception), response); - } - - /** - * Renders a JSON error response - * @param errorResponse The error - * @param res web script response - * @throws IOException - */ - public void renderErrorResponse(ErrorResponse errorResponse, final WebScriptResponse res) throws IOException { - - String logId = ""; - - if (Status.STATUS_INTERNAL_SERVER_ERROR == errorResponse.getStatusCode() || logger.isDebugEnabled()) - { - logId = org.alfresco.util.GUID.generate(); - logger.error(logId+" : "+errorResponse.getStackTrace()); - } - - String stackMessage = I18NUtil.getMessage(DefaultExceptionResolver.STACK_MESSAGE_ID); - - final ErrorResponse errorToWrite = new ErrorResponse(errorResponse.getErrorKey(), - errorResponse.getStatusCode(), - errorResponse.getBriefSummary(), - stackMessage, - logId, - errorResponse.getAdditionalState(), - DefaultExceptionResolver.ERROR_URL); - - setContentInfoOnResponse(res, DEFAULT_JSON_CONTENT); - - // Status must be set before the response is written by Jackson (which will by default close and commit the response). - // In a r/w txn, web script buffered responses ensure that it doesn't really matter but for r/o txns this is important. - res.setStatus(errorToWrite.getStatusCode()); - - jsonHelper.withWriter(res.getOutputStream(), new JacksonHelper.Writer() - { - @SuppressWarnings("unchecked") - @Override - public void writeContents(JsonGenerator generator, ObjectMapper objectMapper) - throws JsonGenerationException, JsonMappingException, IOException - { - JSONObject obj = new JSONObject(); - obj.put("error", errorToWrite); - objectMapper.writeValue(generator, obj); - } - }); - } - public JacksonHelper getJsonHelper() { return jsonHelper; } diff --git a/source/java/org/alfresco/rest/framework/tools/RecognizedParamsExtractor.java b/source/java/org/alfresco/rest/framework/tools/RecognizedParamsExtractor.java new file mode 100644 index 0000000000..73c416d01a --- /dev/null +++ b/source/java/org/alfresco/rest/framework/tools/RecognizedParamsExtractor.java @@ -0,0 +1,451 @@ +/* + * #%L + * Alfresco Remote API + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ + +package org.alfresco.rest.framework.tools; + +import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException; +import org.alfresco.rest.framework.jacksonextensions.BeanPropertiesFilter; +import org.alfresco.rest.framework.resource.parameters.InvalidSelectException; +import org.alfresco.rest.framework.resource.parameters.Paging; +import org.alfresco.rest.framework.resource.parameters.Params; +import org.alfresco.rest.framework.resource.parameters.SortColumn; +import org.alfresco.rest.framework.resource.parameters.where.InvalidQueryException; +import org.alfresco.rest.framework.resource.parameters.where.Query; +import org.alfresco.rest.framework.resource.parameters.where.QueryImpl; +import org.alfresco.rest.framework.resource.parameters.where.WhereCompiler; +import org.antlr.runtime.RecognitionException; +import org.antlr.runtime.tree.CommonErrorNode; +import org.antlr.runtime.tree.CommonTree; +import org.antlr.runtime.tree.RewriteCardinalityException; +import org.antlr.runtime.tree.Tree; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.extensions.webscripts.WebScriptRequest; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.StringTokenizer; + +/* + * Extracts recognized parameters from the HTTP request. + * + * @author Gethin James + */ +public interface RecognizedParamsExtractor +{ + public static final String PARAM_RELATIONS = "relations"; + public static final String PARAM_FILTER_FIELDS = "fields"; + + @Deprecated + public static final String PARAM_FILTER_PROPERTIES = "properties"; + + public static final String PARAM_PAGING_SKIP = "skipCount"; + public static final String PARAM_PAGING_MAX = "maxItems"; + public static final String PARAM_ORDERBY = "orderBy"; + public static final String PARAM_WHERE = "where"; + public static final String PARAM_SELECT = "select"; + public static final String PARAM_INCLUDE = "include"; + public static final String PARAM_INCLUDE_SOURCE_ENTITY = "includeSource"; + public static final List KNOWN_PARAMS = Arrays.asList( + PARAM_RELATIONS, PARAM_FILTER_PROPERTIES, PARAM_FILTER_FIELDS,PARAM_PAGING_SKIP,PARAM_PAGING_MAX, + PARAM_ORDERBY, PARAM_WHERE, PARAM_SELECT, PARAM_INCLUDE_SOURCE_ENTITY); + + default Log rpeLogger() { + return LogFactory.getLog(this.getClass()); + } + + /** + * Finds the formal set of params that any rest service could potentially have passed in as request params + * @param req WebScriptRequest + * @return RecognizedParams a POJO containing the params for use with the Params objects + */ + default Params.RecognizedParams getRecognizedParams(WebScriptRequest req) + { + Paging paging = findPaging(req); + List sorting = getSort(req.getParameter(PARAM_ORDERBY)); + Map relationFilter = getRelationFilter(req.getParameter(PARAM_RELATIONS)); + Query whereQuery = getWhereClause(req.getParameter(PARAM_WHERE)); + Map requestParams = getRequestParameters(req); + boolean includeSource = Boolean.valueOf(req.getParameter(PARAM_INCLUDE_SOURCE_ENTITY)); + + List includedFields = getIncludeClause(req.getParameter(PARAM_INCLUDE)); + List selectFields = getSelectClause(req.getParameter(PARAM_SELECT)); + + String fields = req.getParameter(PARAM_FILTER_FIELDS); + String properties = req.getParameter(PARAM_FILTER_PROPERTIES); + + if ((fields != null) && (properties != null)) + { + if (rpeLogger().isWarnEnabled()) + { + rpeLogger().warn("Taking 'fields' param [" + fields + "] and ignoring deprecated 'properties' param [" + properties + "]"); + } + } + + BeanPropertiesFilter filter = getFilter((fields != null ? fields : properties), includedFields); + + return new Params.RecognizedParams(requestParams, paging, filter, relationFilter, includedFields, selectFields, whereQuery, sorting, includeSource); + } + + + /** + * Takes the web request and looks for a "fields" parameter (otherwise deprecated "properties" parameter). + * + * Parses the parameter and produces a list of bean properties to use as a filter A + * SimpleBeanPropertyFilter it returned that uses the bean properties. If no + * filter param is set then a default BeanFilter is returned that will never + * filter fields (ie. Returns all bean properties). + * + * If selectList is provided then it will take precedence (ie. be included) over the fields/properties filter + * for top-level entries (bean properties). + * + * For example, this will return entries from both select & properties, eg. + * + * select=abc,def&properties=id,name,ghi + * + * Note: it should be noted that API-generic "fields" clause does not currently work for sub-entries. + * + * Hence, even if the API-specific "select" clause allows selection of a sub-entries this cannot be used + * with "fields" filtering. For example, an API-specific method may implement and return "abc/blah", eg. + * + * select=abc/blah + * + * However the following will not return "abc/blah" if used with fields filtering, eg. + * + * select=abc/blah&fields=id,name,ghi + * + * If fields filtering is desired then it would require "abc" to be selected and returned as a whole, eg. + * + * select=abc&fields=id,name,ghi + * + * @param filterParams + * @param selectList + * @return + */ + default BeanPropertiesFilter getFilter(String filterParams, List selectList) + { + if (filterParams != null) + { + StringTokenizer st = new StringTokenizer(filterParams, ","); + Set filteredProperties = new HashSet(st.countTokens()); + while (st.hasMoreTokens()) + { + filteredProperties.add(st.nextToken()); + } + + // if supplied, the select takes precedence over the filter (fields/properties) for top-level bean properties + if (selectList != null) + { + for (String select : selectList) + { + String[] split = select.split("/"); + filteredProperties.add(split[0]); + } + } + + rpeLogger().debug("Filtering using the following properties: " + filteredProperties); + BeanPropertiesFilter filter = new BeanPropertiesFilter(filteredProperties); + return filter; + } + return BeanPropertiesFilter.ALLOW_ALL; + } + + + /** + * Takes the "select" parameter and turns it into a List property names + * @param selectParam String + * @return bean property names potentially using JSON Pointer syntax + */ + @SuppressWarnings("unchecked") + @Deprecated + default List getSelectClause(String selectParam) throws InvalidArgumentException + { + return getClause(selectParam, "SELECT"); + } + + /** + * Takes the "include" parameter and turns it into a List property names + * @param includeParam String + * @return bean property names potentially using JSON Pointer syntax + */ + @SuppressWarnings("unchecked") + default List getIncludeClause(String includeParam) throws InvalidArgumentException + { + return getClause(includeParam, "INCLUDE"); + } + + /** + * Gets the clause specificed in paramName + * @param param + * @param paramName + * @return bean property names potentially using JSON Pointer syntax + */ + default List getClause(String param, String paramName) + { + if (param == null) return Collections.emptyList(); + + try { + CommonTree selectedPropsTree = WhereCompiler.compileSelectClause(param); + if (selectedPropsTree instanceof CommonErrorNode) + { + rpeLogger().debug("Error parsing the "+paramName+" clause "+selectedPropsTree); + throw new InvalidSelectException(paramName, selectedPropsTree); + } + if (selectedPropsTree.getChildCount() == 0 && !selectedPropsTree.getText().isEmpty()) + { + return Arrays.asList(selectedPropsTree.getText()); + } + List children = (List) selectedPropsTree.getChildren(); + if (children!= null && !children.isEmpty()) + { + List properties = new ArrayList(children.size()); + for (Tree child : children) { + properties.add(child.getText()); + } + return properties; + } + } + catch (RewriteCardinalityException re) + { + //Catch any error so it doesn't get thrown up the stack + rpeLogger().debug("Unhandled Error parsing the "+paramName+" clause: "+re); + } + catch (RecognitionException e) + { + rpeLogger().debug("Error parsing the \"+paramName+\" clause: "+param); + } + catch (InvalidQueryException iqe) + { + throw new InvalidSelectException(paramName, iqe.getQueryParam()); + } + //Default to throw out an invalid query + throw new InvalidSelectException(paramName, param); + } + + /** + * Takes the "where" parameter and turns it into a Java Object that can be used for querying + * @param whereParam String + * @return Query a parsed version of the where clause, represented in Java + */ + default Query getWhereClause(String whereParam) throws InvalidQueryException + { + if (whereParam == null) return QueryImpl.EMPTY; + + try { + CommonTree whereTree = WhereCompiler.compileWhereClause(whereParam); + if (whereTree instanceof CommonErrorNode) + { + rpeLogger().debug("Error parsing the WHERE clause "+whereTree); + throw new InvalidQueryException(whereTree); + } + return new QueryImpl(whereTree); + } catch (RewriteCardinalityException re) { //Catch any error so it doesn't get thrown up the stack + rpeLogger().info("Unhandled Error parsing the WHERE clause: "+re); + } catch (RecognitionException e) { + whereParam += ", "+WhereCompiler.resolveMessage(e); + rpeLogger().info("Error parsing the WHERE clause: "+whereParam); + } + //Default to throw out an invalid query + throw new InvalidQueryException(whereParam); + } + + /** + * Takes the Sort parameter as a String and parses it into a List of SortColumn objects. + * The format is a comma seperated list of "columnName sortDirection", + * e.g. "name DESC, age ASC". It is not case sensitive and the sort direction is optional + * It default to sort ASCENDING. + * @param sortParams - String passed in on the request + * @return - the sort columns or an empty list if the params were invalid. + */ + default List getSort(String sortParams) + { + if (sortParams != null) + { + StringTokenizer st = new StringTokenizer(sortParams, ","); + List sortedColumns = new ArrayList(st.countTokens()); + while (st.hasMoreTokens()) + { + String token = st.nextToken(); + StringTokenizer columnDesc = new StringTokenizer(token, " "); + if (columnDesc.countTokens() <= 2) + { + String columnName = columnDesc.nextToken(); + String sortOrder = SortColumn.ASCENDING; + if (columnDesc.hasMoreTokens()) + { + String sortDef = columnDesc.nextToken().toUpperCase(); + if (SortColumn.ASCENDING.equals(sortDef) || SortColumn.DESCENDING.equals(sortDef)) + { + sortOrder = sortDef; + } + else + { + rpeLogger().debug("Invalid sort order definition ("+sortDef+"). Valid values are "+SortColumn.ASCENDING+" or "+SortColumn.DESCENDING+"."); + } + } + sortedColumns.add(new SortColumn(columnName, SortColumn.ASCENDING.equals(sortOrder))); + } + // filteredProperties.add(); + } +// logger.debug("Filtering using the following properties: " + filteredProperties); +// BeanPropertiesFilter filter = new BeanPropertiesFilter(filteredProperties); + return sortedColumns; + } + return Collections.emptyList(); + } + + /** + * Find paging setings based on the request parameters. + * + * @param req + * @return Paging + */ + default Paging findPaging(WebScriptRequest req) + { + int skipped = Paging.DEFAULT_SKIP_COUNT; + int max = Paging.DEFAULT_MAX_ITEMS; + String skip = req.getParameter(PARAM_PAGING_SKIP); + String maxItems = req.getParameter(PARAM_PAGING_MAX); + + try + { + if (skip != null) { skipped = Integer.parseInt(skip);} + if (maxItems != null) { max = Integer.parseInt(maxItems); } + if (max < 0 || skipped < 0) + { + throw new InvalidArgumentException("Negative values not supported."); + } + } + catch (NumberFormatException error) + { + if (rpeLogger().isDebugEnabled()) + { + rpeLogger().debug("Invalid paging params skip: " + skip + ",maxItems:" + maxItems); + } + throw new InvalidArgumentException(); + } + + return Paging.valueOf(skipped, max); + } + + + /** + * Takes the web request and looks for a "fields" parameter (otherwise deprecated "properties" parameter). + * + * Parses the parameter and produces a list of bean properties to use as a filter A + * SimpleBeanPropertyFilter it returned that uses the bean properties. If no + * filter param is set then a default BeanFilter is returned that will never + * filter fields (ie. Returns all bean properties). + * + * @param filterParams String + * @return BeanPropertyFilter - if no parameter then returns a new + * ReturnAllBeanProperties class + */ + default BeanPropertiesFilter getFilter(String filterParams) + { + return getFilter(filterParams, null); + } + + /** + * Takes the web request and looks for a "relations" parameter Parses the + * parameter and produces a list of bean properties to use as a filter A + * SimpleBeanPropertiesFilter it returned that uses the properties If no + * filter param is set then a default BeanFilter is returned that will never + * filter properties (ie. Returns all bean properties). + * + * @param filterParams String + * @return BeanPropertiesFilter - if no parameter then returns a new + * ReturnAllBeanProperties class + */ + default Map getRelationFilter(String filterParams) + { + if (filterParams != null) + { + // Split by a comma when not in a bracket + String[] relations = filterParams.split(",(?![^()]*+\\))"); + Map filterMap = new HashMap(relations.length); + + for (String relation : relations) + { + int bracketLocation = relation.indexOf("("); + if (bracketLocation != -1) + { + // We have properties + String relationKey = relation.substring(0, bracketLocation); + String props = relation.substring(bracketLocation + 1, relation.length() - 1); + filterMap.put(relationKey, getFilter(props)); + } + else + { + // no properties so just get the String + filterMap.put(relation, getFilter(null)); + } + } + return filterMap; + } + return Collections.emptyMap(); + } + + + /** + * Finds all request parameters that aren't already know about (eg. not paging or filter params) + * and returns them for use. + * + * @param req - the WebScriptRequest object + * @return the request parameters + */ + default Map getRequestParameters(WebScriptRequest req) + { + if (req!= null) + { + String[] paramNames = req.getParameterNames(); + if (paramNames!= null) + { + Map requestParameteters = new HashMap(paramNames.length); + + for (int i = 0; i < paramNames.length; i++) + { + String paramName = paramNames[i]; + if (!KNOWN_PARAMS.contains(paramName)) + { + String[] vals = req.getParameterValues(paramName); + requestParameteters.put(paramName, vals); + } + } + return requestParameteters; + } + } + + return Collections.emptyMap(); + } + +} diff --git a/source/java/org/alfresco/rest/framework/tools/RequestReader.java b/source/java/org/alfresco/rest/framework/tools/RequestReader.java new file mode 100644 index 0000000000..d0ba26f032 --- /dev/null +++ b/source/java/org/alfresco/rest/framework/tools/RequestReader.java @@ -0,0 +1,103 @@ +/* + * #%L + * Alfresco Remote API + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ + +package org.alfresco.rest.framework.tools; + +import org.alfresco.rest.framework.core.exceptions.ApiException; +import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException; +import org.alfresco.rest.framework.jacksonextensions.JacksonHelper; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.codehaus.jackson.map.JsonMappingException; +import org.springframework.extensions.webscripts.WebScriptRequest; + +import java.io.IOException; +import java.io.Reader; +import java.util.List; + +/* + * Reads information from the request + * + * @author Gethin James + */ +public interface RequestReader +{ + /** + * Extracts the body contents from the request + * + * @param req the request + * @param jsonHelper Jackson Helper + * @param requiredType the type to return + * @return the Object in the required type + */ + default T extractJsonContent(WebScriptRequest req, JacksonHelper jsonHelper, Class requiredType) + { + Reader reader; + try + { + reader = req.getContent().getReader(); + return jsonHelper.construct(reader, requiredType); + } + catch (JsonMappingException e) + { + rrLogger().warn("Could not read content from HTTP request body.", e); + throw new InvalidArgumentException("Could not read content from HTTP request body."); + } + catch (IOException e) + { + throw new ApiException("Could not read content from HTTP request body.", e.getCause()); + } + } + + /** + * Extracts the body contents from the request as a List, the JSON can be an array or just a single value without the [] symbols + * + * @param req the request + * @param jsonHelper Jackson Helper + * @param requiredType the type to return (without the List param) + * @return A List of "Object" as the required type + */ + default List extractJsonContentAsList(WebScriptRequest req, JacksonHelper jsonHelper, Class requiredType) + { + Reader reader; + try + { + reader = req.getContent().getReader(); + return jsonHelper.constructList(reader, requiredType); + } + catch (IOException e) + { + throw new ApiException("Could not read content from HTTP request body.", e.getCause()); + } + } + + default Log rrLogger() { + return LogFactory.getLog(this.getClass()); + } + + + +} diff --git a/source/java/org/alfresco/rest/framework/tools/ResponseWriter.java b/source/java/org/alfresco/rest/framework/tools/ResponseWriter.java new file mode 100644 index 0000000000..cbc15bcaeb --- /dev/null +++ b/source/java/org/alfresco/rest/framework/tools/ResponseWriter.java @@ -0,0 +1,258 @@ +/* + * #%L + * Alfresco Remote API + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.rest.framework.tools; + +import org.alfresco.rest.framework.Api; +import org.alfresco.rest.framework.core.exceptions.DefaultExceptionResolver; +import org.alfresco.rest.framework.core.exceptions.ErrorResponse; +import org.alfresco.rest.framework.core.exceptions.UnsupportedResourceOperationException; +import org.alfresco.rest.framework.jacksonextensions.BeanPropertiesFilter; +import org.alfresco.rest.framework.jacksonextensions.ExecutionResult; +import org.alfresco.rest.framework.jacksonextensions.JacksonHelper; +import org.alfresco.rest.framework.resource.SerializablePagedCollection; +import org.alfresco.rest.framework.resource.content.BinaryResource; +import org.alfresco.rest.framework.resource.content.ContentInfo; +import org.alfresco.rest.framework.resource.content.ContentInfoImpl; +import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; +import org.alfresco.rest.framework.resource.parameters.Params; +import org.alfresco.rest.framework.webscripts.WithResponse; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.map.JsonMappingException; +import org.codehaus.jackson.map.ObjectMapper; +import org.json.simple.JSONObject; +import org.springframework.beans.BeanUtils; +import org.springframework.extensions.surf.util.I18NUtil; +import org.springframework.extensions.webscripts.*; +import org.springframework.extensions.webscripts.servlet.WebScriptServletResponse; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +/* + * Writes to the response + * + * @author Gethin James + */ +public interface ResponseWriter +{ + + String UTF8 = "UTF-8"; + ContentInfo DEFAULT_JSON_CONTENT = new ContentInfoImpl(Format.JSON.mimetype(),UTF8, 0, null); + Cache CACHE_NEVER = new Cache(new Description.RequiredCache() + { + @Override + public boolean getNeverCache() + { + return true; + } + + @Override + public boolean getIsPublic() + { + return false; + } + + @Override + public boolean getMustRevalidate() + { + return true; + } + }); + + default Log resWriterLogger() { + return LogFactory.getLog(this.getClass()); + } + + /** + * Sets the response headers with any information we know about the content + * @param res WebScriptResponse + * @param contentInfo Content Information + */ + default void setContentInfoOnResponse(WebScriptResponse res, ContentInfo contentInfo) + { + if (contentInfo != null) + { + //Set content info on the response + res.setContentType(contentInfo.getMimeType()); + res.setContentEncoding(contentInfo.getEncoding()); + + if (res instanceof WrappingWebScriptResponse) + { + WrappingWebScriptResponse wrappedRes = ((WrappingWebScriptResponse) res); + res = wrappedRes.getNext(); + } + + if (res instanceof WebScriptServletResponse) + { + WebScriptServletResponse servletResponse = (WebScriptServletResponse) res; + if (contentInfo.getLength() > 0) + { + if (contentInfo.getLength() > 0 && contentInfo.getLength() < Integer.MAX_VALUE) + { + servletResponse.getHttpServletResponse().setContentLength((int) contentInfo.getLength()); + } + } + if (contentInfo.getLocale() != null) + { + servletResponse.getHttpServletResponse().setLocale(contentInfo.getLocale()); + } + } + } + } + + /** + * The response status must be set before the response is written by Jackson (which will by default close and commit the response). + * In a r/w txn, web script buffered responses ensure that it doesn't really matter but for r/o txns this is important. + * + * If you set content information via the contentInfo object and ALSO the headers then "headers" will win because they are + * set last. + * + * @param res + * @param status + * @param cache + * @param contentInfo + * @param headers + */ + default void setResponse(final WebScriptResponse res, int status, Cache cache, ContentInfo contentInfo, Map> headers) + { + res.setStatus(status); + if (cache != null) res.setCache(cache); + setContentInfoOnResponse(res,contentInfo); + if (headers != null && !headers.isEmpty()) + { + for (Map.Entry> header:headers.entrySet()) + { + for (int i=0; i < header.getValue().size(); i++) { + if (i==0) + { + //If its the first one then set the header overwriting. + res.setHeader(header.getKey(), header.getValue().get(i)); + } + else + { + //If its not the first one than update the header + res.addHeader(header.getKey(), header.getValue().get(i)); + } + } + } + } + } + + /** + * Sets the response using the WithResponse object + * @param res + * @param withResponse + */ + default void setResponse(final WebScriptResponse res, WithResponse withResponse) + { + setResponse(res, withResponse.getStatus(), withResponse.getCache(), withResponse.getContentInfo(), withResponse.getHeaders()); + } + + /** + * Renders a JSON error response + * @param errorResponse The error + * @param res web script response + * @throws IOException + */ + default void renderErrorResponse(final ErrorResponse errorResponse, final WebScriptResponse res, final JacksonHelper jsonHelper) throws IOException { + + String logId = ""; + + if (Status.STATUS_INTERNAL_SERVER_ERROR == errorResponse.getStatusCode() || resWriterLogger().isDebugEnabled()) + { + logId = org.alfresco.util.GUID.generate(); + resWriterLogger().error(logId+" : "+errorResponse.getStackTrace()); + } + + String stackMessage = I18NUtil.getMessage(DefaultExceptionResolver.STACK_MESSAGE_ID); + + final ErrorResponse errorToWrite = new ErrorResponse(errorResponse.getErrorKey(), + errorResponse.getStatusCode(), + errorResponse.getBriefSummary(), + stackMessage, + logId, + errorResponse.getAdditionalState(), + DefaultExceptionResolver.ERROR_URL); + + setContentInfoOnResponse(res, DEFAULT_JSON_CONTENT); + + // Status must be set before the response is written by Jackson (which will by default close and commit the response). + // In a r/w txn, web script buffered responses ensure that it doesn't really matter but for r/o txns this is important. + res.setStatus(errorToWrite.getStatusCode()); + + jsonHelper.withWriter(res.getOutputStream(), new JacksonHelper.Writer() + { + @SuppressWarnings("unchecked") + @Override + public void writeContents(JsonGenerator generator, ObjectMapper objectMapper) + throws JsonGenerationException, JsonMappingException, IOException + { + JSONObject obj = new JSONObject(); + obj.put("error", errorToWrite); + objectMapper.writeValue(generator, obj); + } + }); + } + + + /** + * Renders an exception to the output stream as Json. + * @param exception + * @param response + * @throws IOException + */ + default void renderException(final Exception exception, final WebScriptResponse response, final ApiAssistant assistant) throws IOException { + renderErrorResponse(assistant.resolveException(exception), response, assistant.getJsonHelper()); + } + + /** + * Renders the result of an execution. + * + * @param res WebScriptResponse + * @param toSerialize result of an execution + * @throws IOException + */ + default void renderJsonResponse(final WebScriptResponse res, final Object toSerialize, final JacksonHelper jsonHelper) + throws IOException + { + jsonHelper.withWriter(res.getOutputStream(), new JacksonHelper.Writer() + { + @Override + public void writeContents(JsonGenerator generator, ObjectMapper objectMapper) + throws JsonGenerationException, JsonMappingException, IOException + { + objectMapper.writeValue(generator, toSerialize); + } + }); + } + +} diff --git a/source/java/org/alfresco/rest/framework/webscripts/AbstractResourceWebScript.java b/source/java/org/alfresco/rest/framework/webscripts/AbstractResourceWebScript.java index 5b3cc08316..b690cd63d5 100644 --- a/source/java/org/alfresco/rest/framework/webscripts/AbstractResourceWebScript.java +++ b/source/java/org/alfresco/rest/framework/webscripts/AbstractResourceWebScript.java @@ -53,6 +53,7 @@ import org.alfresco.rest.framework.resource.content.FileBinaryResource; import org.alfresco.rest.framework.resource.content.NodeBinaryResource; import org.alfresco.rest.framework.resource.parameters.Params; import org.alfresco.rest.framework.tools.ApiAssistant; +import org.alfresco.rest.framework.tools.ResponseWriter; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -80,7 +81,7 @@ import org.springframework.http.HttpMethod; */ // TODO for requests that pass in input streams e.g. binary content for workflow, this is going to need a way to re-read the input stream a la // code in RepositoryContainer due to retrying transaction logic -public abstract class AbstractResourceWebScript extends ApiWebScript implements HttpMethodSupport, ActionExecutor +public abstract class AbstractResourceWebScript extends ApiWebScript implements HttpMethodSupport, ActionExecutor, ResponseWriter { private static Log logger = LogFactory.getLog(AbstractResourceWebScript.class); @@ -146,18 +147,18 @@ public abstract class AbstractResourceWebScript extends ApiWebScript implements } else { - renderJsonResponse(res, toSerialize); + renderJsonResponse(res, toSerialize, assistant.getJsonHelper()); } } } catch (AlfrescoRuntimeException | ApiException | WebScriptException xception ) { - assistant.renderException(xception, res); + renderException(xception, res, assistant); } catch (RuntimeException runtimeException) { - assistant.renderException(runtimeException, res); + renderException(runtimeException, res, assistant); } } @@ -165,7 +166,7 @@ public abstract class AbstractResourceWebScript extends ApiWebScript implements { final String entityCollectionName = ResourceInspector.findEntityCollectionNameName(resource.getMetaData()); final ResourceOperation operation = resource.getMetaData().getOperation(getHttpMethod()); - final WithResponse callBack = new WithResponse(operation.getSuccessStatus(), ApiAssistant.DEFAULT_JSON_CONTENT,ApiAssistant.CACHE_NEVER); + final WithResponse callBack = new WithResponse(operation.getSuccessStatus(), DEFAULT_JSON_CONTENT,CACHE_NEVER); Object toReturn = transactionService.getRetryingTransactionHelper().doInTransaction( new RetryingTransactionHelper.RetryingTransactionCallback() { @@ -199,7 +200,7 @@ public abstract class AbstractResourceWebScript extends ApiWebScript implements { NodeBinaryResource nodeResource = (NodeBinaryResource) resource; ContentInfo contentInfo = nodeResource.getContentInfo(); - assistant.setContentInfoOnResponse(res, contentInfo); + setContentInfoOnResponse(res, contentInfo); // if requested, set attachment boolean attach = StringUtils.isNotEmpty(nodeResource.getAttachFileName()); Map model = getModelForCacheDirective(nodeResource.getCacheDirective()); @@ -217,70 +218,6 @@ public abstract class AbstractResourceWebScript extends ApiWebScript implements return null; } - /** - * The response status must be set before the response is written by Jackson (which will by default close and commit the response). - * In a r/w txn, web script buffered responses ensure that it doesn't really matter but for r/o txns this is important. - * - * If you set content information via the contentInfo object and ALSO the headers then "headers" will win because they are - * set last. - * - * @param res - * @param status - * @param cache - * @param contentInfo - * @param headers - */ - public void setResponse(final WebScriptResponse res, int status, Cache cache, ContentInfo contentInfo, Map> headers) - { - res.setStatus(status); - if (cache != null) res.setCache(cache); - assistant.setContentInfoOnResponse(res,contentInfo); - if (headers != null && !headers.isEmpty()) - { - for (Map.Entry> header:headers.entrySet()) - { - for (int i=0; i < header.getValue().size(); i++) { - if (i==0) - { - //If its the first one then set the header overwriting. - res.setHeader(header.getKey(), header.getValue().get(i)); - } - else - { - //If its not the first one than update the header - res.addHeader(header.getKey(), header.getValue().get(i)); - } - } - } - } - } - - protected void setResponse(final WebScriptResponse res, WithResponse withResponse) - { - setResponse(res, withResponse.getStatus(), withResponse.getCache(), withResponse.getContentInfo(), withResponse.getHeaders()); - } - - /** - * Renders the result of an execution. - * - * @param res WebScriptResponse - * @param toSerialize result of an execution - * @throws IOException - */ - protected void renderJsonResponse(final WebScriptResponse res, final Object toSerialize) - throws IOException - { - assistant.getJsonHelper().withWriter(res.getOutputStream(), new JacksonHelper.Writer() - { - @Override - public void writeContents(JsonGenerator generator, ObjectMapper objectMapper) - throws JsonGenerationException, JsonMappingException, IOException - { - objectMapper.writeValue(generator, toSerialize); - } - }); - } - public void setLocator(ResourceLocator locator) { this.locator = locator; diff --git a/source/java/org/alfresco/rest/framework/webscripts/ResourceWebScriptDelete.java b/source/java/org/alfresco/rest/framework/webscripts/ResourceWebScriptDelete.java index d3dd34b1cc..819d3b8bdd 100644 --- a/source/java/org/alfresco/rest/framework/webscripts/ResourceWebScriptDelete.java +++ b/source/java/org/alfresco/rest/framework/webscripts/ResourceWebScriptDelete.java @@ -38,6 +38,7 @@ import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResou import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceBinaryAction; import org.alfresco.rest.framework.resource.parameters.Params; import org.alfresco.rest.framework.tools.ApiAssistant; +import org.alfresco.rest.framework.tools.RecognizedParamsExtractor; import org.apache.commons.lang.StringUtils; import org.springframework.extensions.webscripts.WebScriptRequest; import org.springframework.extensions.webscripts.WebScriptResponse; @@ -48,7 +49,7 @@ import org.springframework.http.HttpMethod; * * @author Gethin James */ -public class ResourceWebScriptDelete extends AbstractResourceWebScript implements ParamsExtractor +public class ResourceWebScriptDelete extends AbstractResourceWebScript implements ParamsExtractor, RecognizedParamsExtractor { public ResourceWebScriptDelete() @@ -63,7 +64,7 @@ public class ResourceWebScriptDelete extends AbstractResourceWebScript implement { String entityId = req.getServiceMatch().getTemplateVars().get(ResourceLocator.ENTITY_ID); String relationshipId = req.getServiceMatch().getTemplateVars().get(ResourceLocator.RELATIONSHIP_ID); - final Params.RecognizedParams params = ResourceWebScriptHelper.getRecognizedParams(req); + final Params.RecognizedParams params = getRecognizedParams(req); switch (resourceMeta.getType()) { @@ -215,7 +216,7 @@ public class ResourceWebScriptDelete extends AbstractResourceWebScript implement public Void execute(final ResourceWithMetadata resource, final Params params, final WebScriptResponse res, boolean isReadOnly) { final ResourceOperation operation = resource.getMetaData().getOperation(HttpMethod.DELETE); - final WithResponse callBack = new WithResponse(operation.getSuccessStatus(), ApiAssistant.DEFAULT_JSON_CONTENT,ApiAssistant.CACHE_NEVER); + final WithResponse callBack = new WithResponse(operation.getSuccessStatus(), DEFAULT_JSON_CONTENT,CACHE_NEVER); transactionService.getRetryingTransactionHelper().doInTransaction( new RetryingTransactionCallback() { diff --git a/source/java/org/alfresco/rest/framework/webscripts/ResourceWebScriptGet.java b/source/java/org/alfresco/rest/framework/webscripts/ResourceWebScriptGet.java index d85b487064..5ad762dd7e 100644 --- a/source/java/org/alfresco/rest/framework/webscripts/ResourceWebScriptGet.java +++ b/source/java/org/alfresco/rest/framework/webscripts/ResourceWebScriptGet.java @@ -40,6 +40,7 @@ import org.alfresco.rest.framework.resource.content.BinaryResource; import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; import org.alfresco.rest.framework.resource.parameters.Params; import org.alfresco.rest.framework.resource.parameters.Params.RecognizedParams; +import org.alfresco.rest.framework.tools.RecognizedParamsExtractor; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -51,7 +52,7 @@ import org.springframework.http.HttpMethod; * * @author Gethin James */ -public class ResourceWebScriptGet extends AbstractResourceWebScript implements ParamsExtractor +public class ResourceWebScriptGet extends AbstractResourceWebScript implements ParamsExtractor, RecognizedParamsExtractor { private static Log logger = LogFactory.getLog(ResourceWebScriptGet.class); @@ -67,7 +68,7 @@ public class ResourceWebScriptGet extends AbstractResourceWebScript implements P { final String entityId = req.getServiceMatch().getTemplateVars().get(ResourceLocator.ENTITY_ID); final String relationshipId = req.getServiceMatch().getTemplateVars().get(ResourceLocator.RELATIONSHIP_ID); - final RecognizedParams params = ResourceWebScriptHelper.getRecognizedParams(req); + final RecognizedParams params = getRecognizedParams(req); switch (resourceMeta.getType()) { diff --git a/source/java/org/alfresco/rest/framework/webscripts/ResourceWebScriptHelper.java b/source/java/org/alfresco/rest/framework/webscripts/ResourceWebScriptHelper.java index 3836efcc65..a627f1f7e7 100644 --- a/source/java/org/alfresco/rest/framework/webscripts/ResourceWebScriptHelper.java +++ b/source/java/org/alfresco/rest/framework/webscripts/ResourceWebScriptHelper.java @@ -67,6 +67,7 @@ import org.alfresco.rest.framework.resource.parameters.where.Query; import org.alfresco.rest.framework.resource.parameters.where.QueryImpl; import org.alfresco.rest.framework.resource.parameters.where.WhereCompiler; import org.alfresco.rest.framework.tools.ApiAssistant; +import org.alfresco.rest.framework.tools.ResponseWriter; import org.alfresco.util.Pair; import org.alfresco.util.PropertyCheck; import org.antlr.runtime.RecognitionException; @@ -92,336 +93,10 @@ import org.springframework.http.HttpMethod; public class ResourceWebScriptHelper { private static Log logger = LogFactory.getLog(ResourceWebScriptHelper.class); - public static final String PARAM_RELATIONS = "relations"; - - public static final String PARAM_FILTER_FIELDS = "fields"; - - @Deprecated - public static final String PARAM_FILTER_PROPERTIES = "properties"; - - public static final String PARAM_PAGING_SKIP = "skipCount"; - public static final String PARAM_PAGING_MAX = "maxItems"; - public static final String PARAM_ORDERBY = "orderBy"; - public static final String PARAM_WHERE = "where"; - - public static final String PARAM_SELECT = "select"; - - public static final String PARAM_INCLUDE = "include"; - public static final String PARAM_INCLUDE_SOURCE_ENTITY = "includeSource"; - - public static final List KNOWN_PARAMS = Arrays.asList( - PARAM_RELATIONS, PARAM_FILTER_PROPERTIES, PARAM_FILTER_FIELDS,PARAM_PAGING_SKIP,PARAM_PAGING_MAX, - PARAM_ORDERBY, PARAM_WHERE, PARAM_SELECT, PARAM_INCLUDE_SOURCE_ENTITY); - private ResourceLocator locator; private ActionExecutor executor; - /** - * Takes the web request and looks for a "fields" parameter (otherwise deprecated "properties" parameter). - * - * Parses the parameter and produces a list of bean properties to use as a filter A - * SimpleBeanPropertyFilter it returned that uses the bean properties. If no - * filter param is set then a default BeanFilter is returned that will never - * filter fields (ie. Returns all bean properties). - * - * @param filterParams String - * @return BeanPropertyFilter - if no parameter then returns a new - * ReturnAllBeanProperties class - */ - public static BeanPropertiesFilter getFilter(String filterParams) - { - return getFilter(filterParams, null); - } - - /** - * Takes the web request and looks for a "fields" parameter (otherwise deprecated "properties" parameter). - * - * Parses the parameter and produces a list of bean properties to use as a filter A - * SimpleBeanPropertyFilter it returned that uses the bean properties. If no - * filter param is set then a default BeanFilter is returned that will never - * filter fields (ie. Returns all bean properties). - * - * If selectList is provided then it will take precedence (ie. be included) over the fields/properties filter - * for top-level entries (bean properties). - * - * For example, this will return entries from both select & properties, eg. - * - * select=abc,def&properties=id,name,ghi - * - * Note: it should be noted that API-generic "fields" clause does not currently work for sub-entries. - * - * Hence, even if the API-specific "select" clause allows selection of a sub-entries this cannot be used - * with "fields" filtering. For example, an API-specific method may implement and return "abc/blah", eg. - * - * select=abc/blah - * - * However the following will not return "abc/blah" if used with fields filtering, eg. - * - * select=abc/blah&fields=id,name,ghi - * - * If fields filtering is desired then it would require "abc" to be selected and returned as a whole, eg. - * - * select=abc&fields=id,name,ghi - * - * @param filterParams - * @param selectList - * @return - */ - public static BeanPropertiesFilter getFilter(String filterParams, List selectList) - { - if (filterParams != null) - { - StringTokenizer st = new StringTokenizer(filterParams, ","); - Set filteredProperties = new HashSet(st.countTokens()); - while (st.hasMoreTokens()) - { - filteredProperties.add(st.nextToken()); - } - - // if supplied, the select takes precedence over the filter (fields/properties) for top-level bean properties - if (selectList != null) - { - for (String select : selectList) - { - String[] split = select.split("/"); - filteredProperties.add(split[0]); - } - } - - logger.debug("Filtering using the following properties: " + filteredProperties); - BeanPropertiesFilter filter = new BeanPropertiesFilter(filteredProperties); - return filter; - } - return BeanPropertiesFilter.ALLOW_ALL; - } - - /** - * Takes the web request and looks for a "relations" parameter Parses the - * parameter and produces a list of bean properties to use as a filter A - * SimpleBeanPropertiesFilter it returned that uses the properties If no - * filter param is set then a default BeanFilter is returned that will never - * filter properties (ie. Returns all bean properties). - * - * @param filterParams String - * @return BeanPropertiesFilter - if no parameter then returns a new - * ReturnAllBeanProperties class - */ - public static Map getRelationFilter(String filterParams) - { - if (filterParams != null) - { - // Split by a comma when not in a bracket - String[] relations = filterParams.split(",(?![^()]*+\\))"); - Map filterMap = new HashMap(relations.length); - - for (String relation : relations) - { - int bracketLocation = relation.indexOf("("); - if (bracketLocation != -1) - { - // We have properties - String relationKey = relation.substring(0, bracketLocation); - String props = relation.substring(bracketLocation + 1, relation.length() - 1); - filterMap.put(relationKey, getFilter(props)); - } - else - { - // no properties so just get the String - filterMap.put(relation, getFilter(null)); - } - } - return filterMap; - } - return Collections.emptyMap(); - } - - /** - * Takes the "select" parameter and turns it into a List property names - * @param selectParam String - * @return bean property names potentially using JSON Pointer syntax - */ - @SuppressWarnings("unchecked") - @Deprecated - public static List getSelectClause(String selectParam) throws InvalidArgumentException - { - return getClause(selectParam, "SELECT"); - } - - /** - * Takes the "include" parameter and turns it into a List property names - * @param includeParam String - * @return bean property names potentially using JSON Pointer syntax - */ - @SuppressWarnings("unchecked") - public static List getIncludeClause(String includeParam) throws InvalidArgumentException - { - return getClause(includeParam, "INCLUDE"); - } - - private static List getClause(String param, String paramName) - { - if (param == null) return Collections.emptyList(); - - try { - CommonTree selectedPropsTree = WhereCompiler.compileSelectClause(param); - if (selectedPropsTree instanceof CommonErrorNode) - { - logger.debug("Error parsing the "+paramName+" clause "+selectedPropsTree); - throw new InvalidSelectException(paramName, selectedPropsTree); - } - if (selectedPropsTree.getChildCount() == 0 && !selectedPropsTree.getText().isEmpty()) - { - return Arrays.asList(selectedPropsTree.getText()); - } - List children = (List) selectedPropsTree.getChildren(); - if (children!= null && !children.isEmpty()) - { - List properties = new ArrayList(children.size()); - for (Tree child : children) { - properties.add(child.getText()); - } - return properties; - } - } - catch (RewriteCardinalityException re) - { - //Catch any error so it doesn't get thrown up the stack - logger.debug("Unhandled Error parsing the "+paramName+" clause: "+re); - } - catch (RecognitionException e) - { - logger.debug("Error parsing the \"+paramName+\" clause: "+param); - } - catch (InvalidQueryException iqe) - { - throw new InvalidSelectException(paramName, iqe.getQueryParam()); - } - //Default to throw out an invalid query - throw new InvalidSelectException(paramName, param); - } - - /** - * Takes the "where" parameter and turns it into a Java Object that can be used for querying - * @param whereParam String - * @return Query a parsed version of the where clause, represented in Java - */ - public static Query getWhereClause(String whereParam) throws InvalidQueryException - { - if (whereParam == null) return QueryImpl.EMPTY; - - try { - CommonTree whereTree = WhereCompiler.compileWhereClause(whereParam); - if (whereTree instanceof CommonErrorNode) - { - logger.debug("Error parsing the WHERE clause "+whereTree); - throw new InvalidQueryException(whereTree); - } - return new QueryImpl(whereTree); - } catch (RewriteCardinalityException re) { //Catch any error so it doesn't get thrown up the stack - logger.info("Unhandled Error parsing the WHERE clause: "+re); - } catch (RecognitionException e) { - whereParam += ", "+WhereCompiler.resolveMessage(e); - logger.info("Error parsing the WHERE clause: "+whereParam); - } - //Default to throw out an invalid query - throw new InvalidQueryException(whereParam); - } - - /** - * Takes the Sort parameter as a String and parses it into a List of SortColumn objects. - * The format is a comma seperated list of "columnName sortDirection", - * e.g. "name DESC, age ASC". It is not case sensitive and the sort direction is optional - * It default to sort ASCENDING. - * @param sortParams - String passed in on the request - * @return - the sort columns or an empty list if the params were invalid. - */ - public static List getSort(String sortParams) - { - if (sortParams != null) - { - StringTokenizer st = new StringTokenizer(sortParams, ","); - List sortedColumns = new ArrayList(st.countTokens()); - while (st.hasMoreTokens()) - { - String token = st.nextToken(); - StringTokenizer columnDesc = new StringTokenizer(token, " "); - if (columnDesc.countTokens() <= 2) - { - String columnName = columnDesc.nextToken(); - String sortOrder = SortColumn.ASCENDING; - if (columnDesc.hasMoreTokens()) - { - String sortDef = columnDesc.nextToken().toUpperCase(); - if (SortColumn.ASCENDING.equals(sortDef) || SortColumn.DESCENDING.equals(sortDef)) - { - sortOrder = sortDef; - } - else - { - logger.debug("Invalid sort order definition ("+sortDef+"). Valid values are "+SortColumn.ASCENDING+" or "+SortColumn.DESCENDING+"."); - } - } - sortedColumns.add(new SortColumn(columnName, SortColumn.ASCENDING.equals(sortOrder))); - } - // filteredProperties.add(); - } -// logger.debug("Filtering using the following properties: " + filteredProperties); -// BeanPropertiesFilter filter = new BeanPropertiesFilter(filteredProperties); - return sortedColumns; - } - return Collections.emptyList(); - } - - /** - * Extracts the body contents from the request - * - * @param req the request - * @param jsonHelper Jackson Helper - * @param requiredType the type to return - * @return the Object in the required type - */ - public static T extractJsonContent(WebScriptRequest req, JacksonHelper jsonHelper, Class requiredType) - { - Reader reader; - try - { - reader = req.getContent().getReader(); - return jsonHelper.construct(reader, requiredType); - } - catch (JsonMappingException e) - { - logger.warn("Could not read content from HTTP request body.", e); - throw new InvalidArgumentException("Could not read content from HTTP request body."); - } - catch (IOException e) - { - throw new ApiException("Could not read content from HTTP request body.", e.getCause()); - } - } - - /** - * Extracts the body contents from the request as a List, the JSON can be an array or just a single value without the [] symbols - * - * @param req the request - * @param jsonHelper Jackson Helper - * @param requiredType the type to return (without the List param) - * @return A List of "Object" as the required type - */ - public static List extractJsonContentAsList(WebScriptRequest req, JacksonHelper jsonHelper, Class requiredType) - { - Reader reader; - try - { - reader = req.getContent().getReader(); - return jsonHelper.constructList(reader, requiredType); - } - catch (IOException e) - { - throw new ApiException("Could not read content from HTTP request body.", e.getCause()); - } - } - /** * Set the id of theObj to the uniqueId. Attempts to find a set method and * invoke it. If it fails it just swallows the exceptions and doesn't throw @@ -471,41 +146,6 @@ public class ResourceWebScriptHelper } } -// /** -// * Renders the response result -// * -// * @param response -// * @param result -// */ -// public static void renderResponseDep(Map response, Object result) -// { -// -// if (result == null) { return; } -// -// if (result instanceof Collection) -// { -// response.put("list", result); -// } -// else if (result instanceof CollectionWithPagingInfo) -// { -// CollectionWithPagingInfo col = (CollectionWithPagingInfo) result; -// if (col.getCollection() !=null && !col.getCollection().isEmpty()) -// { -// response.put("list", col); -// } -// } -// else if (result instanceof Pair) -// { -// Pair aPair = (Pair) result; -// response.put("entry", aPair.getFirst()); -// response.put("relations", aPair.getSecond()); -// } -// else -// { -// response.put("entry", result); -// } -// } - /** * Looks at the object passed in and recursively expands any @EmbeddedEntityResource annotations or related relationship. * {@link org.alfresco.rest.framework.resource.EmbeddedEntityResource EmbeddedEntityResource} is expanded by calling the ReadById method for this entity. @@ -677,7 +317,7 @@ public class ResourceWebScriptHelper paramFilter = filters.get(resourceKey); } final Params executionParams = Params.valueOf(paramFilter, uniqueEntityId, params.getRequest()); - final WithResponse callBack = new WithResponse(Status.STATUS_OK, ApiAssistant.DEFAULT_JSON_CONTENT,ApiAssistant.CACHE_NEVER); + final WithResponse callBack = new WithResponse(Status.STATUS_OK, ResponseWriter.DEFAULT_JSON_CONTENT,ResponseWriter.CACHE_NEVER); //Read only because this only occurs for GET requests Object result = executor.executeAction(resource, executionParams, callBack); return processAdditionsToTheResponse(null, api, null, executionParams, result); @@ -705,118 +345,6 @@ public class ResourceWebScriptHelper return null; //default } - /** - * Finds all request parameters that aren't already known about (eg. not paging or filter params) - * and returns them for use. - * - * @param req - the WebScriptRequest object - * @return the request parameters - */ - public static Map getRequestParameters(WebScriptRequest req) - { - if (req!= null) - { - String[] paramNames = req.getParameterNames(); - if (paramNames!= null) - { - Map requestParameteters = new HashMap(paramNames.length); - - for (int i = 0; i < paramNames.length; i++) - { - String paramName = paramNames[i]; - if (!KNOWN_PARAMS.contains(paramName)) - { - String[] vals = req.getParameterValues(paramName); - requestParameteters.put(paramName, vals); - } - } - return requestParameteters; - } - } - - return Collections.emptyMap(); - } - - /** - * Finds the formal set of params that any rest service could potentially have passed in as request params - * @param req WebScriptRequest - * @return RecognizedParams a POJO containing the params for use with the Params objects - */ - public static RecognizedParams getRecognizedParams(WebScriptRequest req) - { - Paging paging = findPaging(req); - List sorting = getSort(req.getParameter(ResourceWebScriptHelper.PARAM_ORDERBY)); - Map relationFilter = getRelationFilter(req.getParameter(ResourceWebScriptHelper.PARAM_RELATIONS)); - Query whereQuery = getWhereClause(req.getParameter(ResourceWebScriptHelper.PARAM_WHERE)); - Map requestParams = getRequestParameters(req); - boolean includeSource = Boolean.valueOf(req.getParameter(ResourceWebScriptHelper.PARAM_INCLUDE_SOURCE_ENTITY)); - - List includedFields = getIncludeClause(req.getParameter(ResourceWebScriptHelper.PARAM_INCLUDE)); - List selectFields = getSelectClause(req.getParameter(ResourceWebScriptHelper.PARAM_SELECT)); - - String fields = req.getParameter(ResourceWebScriptHelper.PARAM_FILTER_FIELDS); - String properties = req.getParameter(ResourceWebScriptHelper.PARAM_FILTER_PROPERTIES); - - if ((fields != null) && (properties != null)) - { - if (logger.isWarnEnabled()) - { - logger.warn("Taking 'fields' param [" + fields + "] and ignoring deprecated 'properties' param [" + properties + "]"); - } - } - - BeanPropertiesFilter filter = getFilter((fields != null ? fields : properties), includedFields); - - return new RecognizedParams(requestParams, paging, filter, relationFilter, includedFields, selectFields, whereQuery, sorting, includeSource); - } - - /** - * Find paging setings based on the request parameters. - * - * @param req - * @return Paging - */ - public static Paging findPaging(WebScriptRequest req) - { - int skipped = Paging.DEFAULT_SKIP_COUNT; - int max = Paging.DEFAULT_MAX_ITEMS; - String skip = req.getParameter(PARAM_PAGING_SKIP); - String maxItems = req.getParameter(PARAM_PAGING_MAX); - - try - { - if (skip != null) { skipped = Integer.parseInt(skip);} - if (maxItems != null) { max = Integer.parseInt(maxItems); } - if (skipped < 0) - { - throw new InvalidArgumentException("Negative values not supported for skipCount."); - } - if (max < 1) - { - throw new InvalidArgumentException("Only positive values supported for maxItems."); - } - } - catch (NumberFormatException error) - { - String errorMsg = "Invalid paging parameters skipCount: " + skip + ", maxItems:" + maxItems; - if (logger.isDebugEnabled()) - { - logger.debug(errorMsg); - } - if (skip == null) - { - errorMsg = "Invalid paging parameter maxItems:" + maxItems; - } - if (maxItems == null) - { - errorMsg = "Invalid paging parameter skipCount:" + skip; - } - throw new InvalidArgumentException(errorMsg); - } - - return Paging.valueOf(skipped, max); - } - public void setLocator(ResourceLocator locator) { this.locator = locator; diff --git a/source/java/org/alfresco/rest/framework/webscripts/ResourceWebScriptPost.java b/source/java/org/alfresco/rest/framework/webscripts/ResourceWebScriptPost.java index 792c9fbf0d..9671af65eb 100644 --- a/source/java/org/alfresco/rest/framework/webscripts/ResourceWebScriptPost.java +++ b/source/java/org/alfresco/rest/framework/webscripts/ResourceWebScriptPost.java @@ -45,6 +45,8 @@ import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResou import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; import org.alfresco.rest.framework.resource.parameters.Params; import org.alfresco.rest.framework.resource.parameters.Params.RecognizedParams; +import org.alfresco.rest.framework.tools.RecognizedParamsExtractor; +import org.alfresco.rest.framework.tools.RequestReader; import org.apache.commons.lang.StringUtils; import org.springframework.extensions.webscripts.WebScriptRequest; import org.springframework.extensions.webscripts.WebScriptRequestImpl; @@ -56,7 +58,8 @@ import org.springframework.http.HttpMethod; * * @author Gethin James */ -public class ResourceWebScriptPost extends AbstractResourceWebScript implements ParamsExtractor +public class ResourceWebScriptPost extends AbstractResourceWebScript implements ParamsExtractor, + RecognizedParamsExtractor, RequestReader { public ResourceWebScriptPost() @@ -69,7 +72,7 @@ public class ResourceWebScriptPost extends AbstractResourceWebScript implements @Override public Params extractParams(ResourceMetadata resourceMeta, WebScriptRequest req) { - final RecognizedParams params = ResourceWebScriptHelper.getRecognizedParams(req); + final RecognizedParams params = getRecognizedParams(req); final String entityId = req.getServiceMatch().getTemplateVars().get(ResourceLocator.ENTITY_ID); final String relationshipId = req.getServiceMatch().getTemplateVars().get(ResourceLocator.RELATIONSHIP_ID); final ResourceOperation operation = resourceMeta.getOperation(HttpMethod.POST); @@ -168,7 +171,7 @@ public class ResourceWebScriptPost extends AbstractResourceWebScript implements Object jsonContent = null; if (objType != null) { - jsonContent = ResourceWebScriptHelper.extractJsonContent(req, assistant.getJsonHelper(), objType); + jsonContent = extractJsonContent(req, assistant.getJsonHelper(), objType); } if (isTypeOperation) @@ -203,11 +206,11 @@ public class ResourceWebScriptPost extends AbstractResourceWebScript implements if (isTypeOperation) { // Operations don't support a List as json body - return ResourceWebScriptHelper.extractJsonContent(req, assistant.getJsonHelper(), objType); + return extractJsonContent(req, assistant.getJsonHelper(), objType); } else { - return ResourceWebScriptHelper.extractJsonContentAsList(req, assistant.getJsonHelper(), objType); + return extractJsonContentAsList(req, assistant.getJsonHelper(), objType); } } diff --git a/source/java/org/alfresco/rest/framework/webscripts/ResourceWebScriptPut.java b/source/java/org/alfresco/rest/framework/webscripts/ResourceWebScriptPut.java index 7538ad054d..328239a6ea 100644 --- a/source/java/org/alfresco/rest/framework/webscripts/ResourceWebScriptPut.java +++ b/source/java/org/alfresco/rest/framework/webscripts/ResourceWebScriptPut.java @@ -44,6 +44,8 @@ import org.alfresco.rest.framework.resource.content.BasicContentInfo; import org.alfresco.rest.framework.resource.content.ContentInfoImpl; import org.alfresco.rest.framework.resource.parameters.Params; import org.alfresco.rest.framework.resource.parameters.Params.RecognizedParams; +import org.alfresco.rest.framework.tools.RecognizedParamsExtractor; +import org.alfresco.rest.framework.tools.RequestReader; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -57,7 +59,8 @@ import org.springframework.http.MediaType; * * @author Gethin James */ -public class ResourceWebScriptPut extends AbstractResourceWebScript implements ParamsExtractor +public class ResourceWebScriptPut extends AbstractResourceWebScript implements ParamsExtractor, + RecognizedParamsExtractor, RequestReader { private static Log logger = LogFactory.getLog(ResourceWebScriptPut.class); @@ -75,7 +78,7 @@ public class ResourceWebScriptPut extends AbstractResourceWebScript implements P final String relationshipId = req.getServiceMatch().getTemplateVars().get(ResourceLocator.RELATIONSHIP_ID); final String entityId = req.getServiceMatch().getTemplateVars().get(ResourceLocator.ENTITY_ID); - final RecognizedParams params = ResourceWebScriptHelper.getRecognizedParams(req); + final RecognizedParams params = getRecognizedParams(req); final ResourceOperation operation = resourceMeta.getOperation(HttpMethod.PUT); switch (resourceMeta.getType()) @@ -87,7 +90,7 @@ public class ResourceWebScriptPut extends AbstractResourceWebScript implements P } else { - Object putEnt = ResourceWebScriptHelper.extractJsonContent(req, assistant.getJsonHelper(), resourceMeta.getObjectType(operation)); + Object putEnt = extractJsonContent(req, assistant.getJsonHelper(), resourceMeta.getObjectType(operation)); return Params.valueOf(entityId,params,putEnt, req); } case RELATIONSHIP: @@ -96,7 +99,7 @@ public class ResourceWebScriptPut extends AbstractResourceWebScript implements P throw new UnsupportedResourceOperationException("PUT is executed against the instance URL"); } else { - Object putRel = ResourceWebScriptHelper.extractJsonContent(req, assistant.getJsonHelper(), resourceMeta.getObjectType(operation)); + Object putRel = extractJsonContent(req, assistant.getJsonHelper(), resourceMeta.getObjectType(operation)); ResourceWebScriptHelper.setUniqueId(putRel,relationshipId); return Params.valueOf(entityId, params, putRel, req); } diff --git a/source/test-java/org/alfresco/rest/framework/tests/core/AbstractContextTest.java b/source/test-java/org/alfresco/rest/framework/tests/core/AbstractContextTest.java index 47aef6b318..28d927da27 100644 --- a/source/test-java/org/alfresco/rest/framework/tests/core/AbstractContextTest.java +++ b/source/test-java/org/alfresco/rest/framework/tests/core/AbstractContextTest.java @@ -39,6 +39,7 @@ import org.alfresco.rest.framework.resource.EntityResource; import org.alfresco.rest.framework.resource.RelationshipResource; import org.alfresco.rest.framework.resource.parameters.Params; import org.alfresco.rest.framework.tools.ApiAssistant; +import org.alfresco.rest.framework.tools.ResponseWriter; import org.alfresco.rest.framework.webscripts.AbstractResourceWebScript; import org.alfresco.rest.framework.webscripts.ApiWebScript; import org.alfresco.rest.framework.webscripts.ResourceWebScriptHelper; @@ -81,7 +82,7 @@ public abstract class AbstractContextTest static Params NOT_USED = Params.valueOf("notUsed", null, mock(WebScriptRequest.class)); static final Params.RecognizedParams NULL_PARAMS = new Params.RecognizedParams(null, null, null, null, null, null, null, null, false); - static final WithResponse callBack = new WithResponse(Status.STATUS_OK, ApiAssistant.DEFAULT_JSON_CONTENT,ApiAssistant.CACHE_NEVER); + static final WithResponse callBack = new WithResponse(Status.STATUS_OK, ResponseWriter.DEFAULT_JSON_CONTENT,ResponseWriter.CACHE_NEVER); static Api api = Api.valueOf("alfrescomock", "private", "1"); @SuppressWarnings("unchecked") diff --git a/source/test-java/org/alfresco/rest/framework/tests/core/AllRestFrameworkTest.java b/source/test-java/org/alfresco/rest/framework/tests/core/AllRestFrameworkTest.java index 9d01bf71a0..d4972f4d8e 100644 --- a/source/test-java/org/alfresco/rest/framework/tests/core/AllRestFrameworkTest.java +++ b/source/test-java/org/alfresco/rest/framework/tests/core/AllRestFrameworkTest.java @@ -23,22 +23,23 @@ * along with Alfresco. If not, see . * #L% */ -package org.alfresco.rest.framework.tests.core; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.junit.runners.Suite.SuiteClasses; - -/** - * Runs all the tests for the Public Rest Framework - * @author Gethin James - */ -@RunWith(Suite.class) -@SuiteClasses({ InspectorTests.class, JsonJacksonTests.class, ParamsExtractorTests.class, - ResourceLocatorTests.class, ResourceWebScriptHelperTests.class, SerializeTests.class, - WhereTests.class, ExecutionTests.class, WithResponseTest.class, - ExceptionResolverTests.class }) -public class AllRestFrameworkTest -{ - -} +package org.alfresco.rest.framework.tests.core; + +import org.alfresco.rest.framework.tools.RecognizedParamsExtractorTest; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +/** + * Runs all the tests for the Public Rest Framework + * @author Gethin James + */ +@RunWith(Suite.class) +@SuiteClasses({ InspectorTests.class, JsonJacksonTests.class, ParamsExtractorTests.class, + ResourceLocatorTests.class, ResourceWebScriptHelperTests.class, SerializeTests.class, + WhereTests.class, ExecutionTests.class, WithResponseTest.class, + ExceptionResolverTests.class, RecognizedParamsExtractorTest.class}) +public class AllRestFrameworkTest +{ + +} diff --git a/source/test-java/org/alfresco/rest/framework/tests/core/ExecutionTests.java b/source/test-java/org/alfresco/rest/framework/tests/core/ExecutionTests.java index e1884001a4..4d11f8f881 100644 --- a/source/test-java/org/alfresco/rest/framework/tests/core/ExecutionTests.java +++ b/source/test-java/org/alfresco/rest/framework/tests/core/ExecutionTests.java @@ -51,6 +51,7 @@ import org.alfresco.rest.framework.tests.api.mocks.Grass; import org.alfresco.rest.framework.tests.api.mocks.Sheep; import org.alfresco.rest.framework.tests.api.mocks3.FlockEntityResource; import org.alfresco.rest.framework.tools.ApiAssistant; +import org.alfresco.rest.framework.tools.ResponseWriter; import org.alfresco.rest.framework.webscripts.AbstractResourceWebScript; import org.alfresco.rest.framework.webscripts.ApiWebScript; import org.junit.Test; @@ -80,7 +81,7 @@ import java.util.Map; * Tests the execution of resources */ -public class ExecutionTests extends AbstractContextTest +public class ExecutionTests extends AbstractContextTest implements ResponseWriter { static final Api api3 = Api.valueOf("alfrescomock", "private", "3"); @@ -99,7 +100,7 @@ public class ExecutionTests extends AbstractContextTest entityResource = locator.locateEntityResource(api,"cow", HttpMethod.GET); result = executor.execute(entityResource, Params.valueOf((String)null, null, mock(WebScriptRequest.class)), response, true); assertNotNull(result); - verify(response, times(1)).setCache((Cache) ApiAssistant.CACHE_NEVER); + verify(response, times(1)).setCache((Cache) ResponseWriter.CACHE_NEVER); response = mock(WebScriptResponse.class); result = executor.execute(entityResource, Params.valueOf("543", null, mock(WebScriptRequest.class)), response, true); @@ -305,7 +306,7 @@ public class ExecutionTests extends AbstractContextTest ErrorResponse defaultError = new DefaultExceptionResolver().resolveException(new NullPointerException()); ByteArrayOutputStream out = new ByteArrayOutputStream(); - apiAssistant.renderErrorResponse(defaultError, mockResponse(out)); + renderErrorResponse(defaultError, mockResponse(out), apiAssistant.getJsonHelper()); String errorMessage = out.toString(); // System.out.println(errorMessage); assertTrue(errorMessage.contains("\"errorKey\":\"framework.exception.ApiDefault\"")); @@ -316,7 +317,7 @@ public class ExecutionTests extends AbstractContextTest ErrorResponse anError = simpleMappingExceptionResolver.resolveException(new ApiException("nothing")); out = new ByteArrayOutputStream(); - apiAssistant.renderErrorResponse(anError, mockResponse(out)); + renderErrorResponse(anError, mockResponse(out),apiAssistant.getJsonHelper()); errorMessage = out.toString(); // System.out.println(errorMessage); assertTrue(errorMessage.contains("\"errorKey\":\"nothing\"")); @@ -326,7 +327,7 @@ public class ExecutionTests extends AbstractContextTest anError = simpleMappingExceptionResolver.resolveException(new EntityNotFoundException("2")); out = new ByteArrayOutputStream(); - apiAssistant.renderErrorResponse(anError, mockResponse(out)); + renderErrorResponse(anError, mockResponse(out),apiAssistant.getJsonHelper()); errorMessage = out.toString(); System.out.println(errorMessage); assertTrue(errorMessage.contains("\"errorKey\":\"framework.exception.EntityNotFound\"")); diff --git a/source/test-java/org/alfresco/rest/framework/tests/core/InspectorTests.java b/source/test-java/org/alfresco/rest/framework/tests/core/InspectorTests.java index 8108377b76..70da787514 100644 --- a/source/test-java/org/alfresco/rest/framework/tests/core/InspectorTests.java +++ b/source/test-java/org/alfresco/rest/framework/tests/core/InspectorTests.java @@ -77,6 +77,7 @@ import org.alfresco.rest.framework.tests.api.mocks3.SheepBlackSheepResourceIsNoM import org.alfresco.rest.framework.tests.api.mocks3.SheepEntityResourceWithDeletedMethods; import org.alfresco.rest.framework.tests.api.mocks3.SlimGoat; import org.alfresco.rest.framework.tools.ApiAssistant; +import org.alfresco.rest.framework.tools.ResponseWriter; import org.alfresco.rest.framework.webscripts.ApiWebScript; import org.alfresco.rest.framework.webscripts.WithResponse; import org.alfresco.util.Pair; @@ -466,7 +467,7 @@ public class InspectorTests OperationResourceMetaData operationResourceMetaData = (OperationResourceMetaData) resourceMetadata; Method actionMethod = operationResourceMetaData.getOperationMethod(); String result = null; - final WithResponse wr = new WithResponse(Status.STATUS_OK, ApiAssistant.DEFAULT_JSON_CONTENT, ApiAssistant.CACHE_NEVER); + final WithResponse wr = new WithResponse(Status.STATUS_OK, ResponseWriter.DEFAULT_JSON_CONTENT, ResponseWriter.CACHE_NEVER); switch (resourceMetadata.getUniqueId()) { diff --git a/source/test-java/org/alfresco/rest/framework/tests/core/ResourceWebScriptHelperTests.java b/source/test-java/org/alfresco/rest/framework/tests/core/ResourceWebScriptHelperTests.java index 437bbce807..e0b89ecdc4 100644 --- a/source/test-java/org/alfresco/rest/framework/tests/core/ResourceWebScriptHelperTests.java +++ b/source/test-java/org/alfresco/rest/framework/tests/core/ResourceWebScriptHelperTests.java @@ -49,6 +49,7 @@ import org.alfresco.rest.framework.tests.api.mocks.Farmer; import org.alfresco.rest.framework.tests.api.mocks.Goat; import org.alfresco.rest.framework.tests.api.mocks.Grass; import org.alfresco.rest.framework.tests.api.mocks.UniqueIdMethodButNoSetter; +import org.alfresco.rest.framework.tools.RecognizedParamsExtractor; import org.alfresco.rest.framework.webscripts.ResourceWebScriptHelper; import org.junit.Test; import org.mockito.invocation.InvocationOnMock; @@ -63,329 +64,6 @@ import org.springframework.extensions.webscripts.WebScriptRequest; public class ResourceWebScriptHelperTests { - - @Test - public void getFilterTest() - { - BeanPropertiesFilter theFilter = ResourceWebScriptHelper.getFilter(null); - assertNotNull(theFilter); - assertTrue("Null passed in so must return the default BeanPropertiesFilter.ALLOW_ALL class", BeanPropertiesFilter.AllProperties.class.equals(theFilter.getClass())); - - theFilter = ResourceWebScriptHelper.getFilter("bob"); - assertNotNull(theFilter); - assertTrue("Must return the BeanPropertiesFilter class", theFilter instanceof BeanPropertiesFilter); - - theFilter = ResourceWebScriptHelper.getFilter("50,fred,b.z"); - assertNotNull(theFilter); - assertTrue("Must return the BeanPropertiesFilter class", theFilter instanceof BeanPropertiesFilter); - - theFilter = ResourceWebScriptHelper.getFilter("50,fred,"); - assertNotNull(theFilter); - assertTrue("Must return the BeanPropertiesFilter class", theFilter instanceof BeanPropertiesFilter); - } - - - @Test - public void getSortingTest() - { - List theSort = ResourceWebScriptHelper.getSort(null); - assertNotNull(theSort); - assertTrue("Null passed in so empty sort list should be returned.", theSort.isEmpty()); - - theSort = ResourceWebScriptHelper.getSort("name ASC"); - assertNotNull(theSort); - assertTrue("Must have a value for column: NAME", !theSort.isEmpty()); - assertTrue(theSort.size() == 1); - assertEquals("name", theSort.get(0).column); - assertTrue(theSort.get(0).asc); - - theSort = ResourceWebScriptHelper.getSort("name "); - assertNotNull(theSort); - assertTrue("Must have a value for column: NAME", !theSort.isEmpty()); - assertTrue(theSort.size() == 1); - assertEquals("name", theSort.get(0).column); - assertTrue(theSort.get(0).asc); - - theSort = ResourceWebScriptHelper.getSort("name DESC"); - assertNotNull(theSort); - assertTrue("Must have a value for column: NAME", !theSort.isEmpty()); - assertTrue(theSort.size() == 1); - assertEquals("name", theSort.get(0).column); - assertTrue(!theSort.get(0).asc); //desc - - theSort = ResourceWebScriptHelper.getSort("name desc"); - assertNotNull(theSort); - assertTrue("Must have a value for column: NAME", !theSort.isEmpty()); - assertTrue(theSort.size() == 1); - assertEquals("name", theSort.get(0).column); - assertTrue(!theSort.get(0).asc); //desc - - theSort = ResourceWebScriptHelper.getSort("name,age desc"); - assertNotNull(theSort); - assertTrue("Must have a value for column: NAME", !theSort.isEmpty()); - assertTrue(theSort.size() == 2); - assertEquals("name", theSort.get(0).column); - assertTrue(theSort.get(0).asc); - assertEquals("age", theSort.get(1).column); - assertTrue(!theSort.get(1).asc); //desc - - theSort = ResourceWebScriptHelper.getSort(" name, age desc"); - assertNotNull(theSort); - assertTrue("Must have a value for column: NAME", !theSort.isEmpty()); - assertTrue(theSort.size() == 2); - assertEquals("name", theSort.get(0).column); - assertTrue(theSort.get(0).asc); - assertEquals("age", theSort.get(1).column); - assertTrue(!theSort.get(1).asc); //desc - - theSort = ResourceWebScriptHelper.getSort("name DESC, age desc"); - assertNotNull(theSort); - assertTrue("Must have a value for column: NAME", !theSort.isEmpty()); - assertTrue(theSort.size() == 2); - assertEquals("name", theSort.get(0).column); - assertTrue(!theSort.get(0).asc); //desc - assertEquals("age", theSort.get(1).column); - assertTrue(!theSort.get(1).asc); //desc - - theSort = ResourceWebScriptHelper.getSort("age Desc, name Asc"); - assertNotNull(theSort); - assertTrue("Must have a value for column: NAME", !theSort.isEmpty()); - assertTrue(theSort.size() == 2); - assertEquals("age", theSort.get(0).column); - assertTrue(!theSort.get(0).asc); //desc - assertEquals("name", theSort.get(1).column); - assertTrue(theSort.get(1).asc); - - theSort = ResourceWebScriptHelper.getSort("name des"); //invalid, should be desc - assertNotNull(theSort); - assertTrue("Must have a value for column: NAME", !theSort.isEmpty()); - assertTrue(theSort.size() == 1); - assertEquals("name", theSort.get(0).column); - assertTrue(theSort.get(0).asc); //Defaults to ascending because the sort order was invalid - - theSort = ResourceWebScriptHelper.getSort("name asc,"); //invalid, should be desc - assertNotNull(theSort); - assertTrue("Must have a value for column: NAME", !theSort.isEmpty()); - assertTrue(theSort.size() == 1); - assertEquals("name", theSort.get(0).column); - assertTrue(theSort.get(0).asc); - } - - @Test - public void getIncludeClauseTest() - { - getClauseTest("include"); - } - - @Test - public void getSelectClauseTest() - { - getClauseTest("select"); - } - - // at the moment select and include are parsed the same way, hence common/shared test - private void getClauseTest(String paramName) - { - List theClause = getClause(paramName, null); - assertNotNull(theClause); - assertFalse("Null passed in so nothing in the "+paramName, theClause.size() > 0); - - try - { - theClause = getClause(paramName, ",,,"); - fail("Should throw an InvalidSelectException"); - } - catch (InvalidSelectException error) - { - //this is correct - } - - try - { - theClause = getClause(paramName, "(,,,"); - fail("Should throw an InvalidSelectException"); - } - catch (InvalidSelectException error) - { - //this is correct - } - - try - { - theClause = getClause(paramName, "(,,,)"); - fail("Should throw an InvalidSelectException"); - } - catch (InvalidSelectException error) - { - //this is correct - } - - try - { - theClause = getClause(paramName, "x/,z"); - fail("Should throw an InvalidSelectException"); - } - catch (InvalidSelectException error) - { - //this is correct - } - - try - { - theClause = getClause(paramName, "/x'n,/z"); - fail("Should throw an InvalidSelectException"); - } - catch (InvalidSelectException error) - { - //this is correct - } - - try - { - theClause = getClause(paramName, "/foo/0"); - fail("Should throw an InvalidSelectException. Legal identifiers must start with a letter not zero"); - } - catch (InvalidSelectException error) - { - //this is correct - } - - try - { - theClause = getClause(paramName, "/"); - fail("Should throw an InvalidSelectException. No identifier specified."); - } - catch (InvalidSelectException error) - { - //this is correct - } - - try - { - theClause = getClause(paramName, "path, isLink"); - fail("Should throw an InvalidSelectException. No identifier specified."); - } - catch (InvalidSelectException error) - { - //this is correct - } - - theClause = getClause(paramName, "king/kong"); - assertTrue("has a valid "+paramName, theClause.size() == 1); - assertEquals("king/kong",theClause.get(0)); - - theClause = getClause(paramName, "x,y"); - assertTrue("has a valid "+paramName, theClause.size() == 2); - assertEquals("x",theClause.get(0)); - assertEquals("y",theClause.get(1)); - - theClause = getClause(paramName, "x,/z"); - assertTrue("has a valid "+paramName, theClause.size() == 2); - assertEquals("x",theClause.get(0)); - assertEquals("/z",theClause.get(1)); - - theClause = getClause(paramName, "/b"); - assertTrue("has a valid "+paramName, theClause.size() == 1); - assertEquals("/b",theClause.get(0)); - - theClause = getClause(paramName, "/be,/he"); - assertTrue("has a valid "+paramName, theClause.size() == 2); - assertEquals("/be",theClause.get(0)); - assertEquals("/he",theClause.get(1)); - - theClause = getClause(paramName, "/king/kong"); - assertTrue("has a valid "+paramName, theClause.size() == 1); - assertEquals("/king/kong",theClause.get(0)); - - theClause = getClause(paramName, "/name,/person/age"); - assertTrue("has a valid "+paramName, theClause.size() == 2); - assertEquals("/name",theClause.get(0)); - assertEquals("/person/age",theClause.get(1)); - - theClause = getClause(paramName, "/foo"); - assertTrue("has a valid select",theClause.size() == 1); - assertEquals("/foo",theClause.get(0)); - - theClause = getClause(paramName, "/foo/anArray/x"); - assertTrue("has a valid "+paramName, theClause.size() == 1); - assertEquals("/foo/anArray/x",theClause.get(0)); - - theClause = getClause(paramName, "/foo/anArray/x,/person/age,/eggs/bacon/sausage,/p"); - assertTrue("has a valid "+paramName, theClause.size() == 4); - assertEquals("/foo/anArray/x",theClause.get(0)); - assertEquals("/person/age",theClause.get(1)); - assertEquals("/eggs/bacon/sausage",theClause.get(2)); - assertEquals("/p",theClause.get(3)); - - theClause = getClause(paramName, "/foo/_bar "); - assertTrue("has a valid "+paramName, theClause.size() == 1); - assertEquals("/foo/_bar",theClause.get(0)); - } - - private List getClause(String paramName, String paramValue) - { - if (paramName.equalsIgnoreCase("include")) - { - return ResourceWebScriptHelper.getIncludeClause(paramValue); - } - else if (paramName.equalsIgnoreCase("select")) - { - return ResourceWebScriptHelper.getSelectClause(paramValue); - } - - fail("Unexpected clause: "+paramName); - return null; - } - - @Test - public void getRelationFilterTest() - { - Map theFilter = ResourceWebScriptHelper.getRelationFilter(null); - assertNotNull(theFilter); - assertTrue("Null passed in so nothing to filter.",theFilter.isEmpty()); - - theFilter = ResourceWebScriptHelper.getRelationFilter("bob"); - assertNotNull(theFilter); - assertTrue("Must be a single relationship", theFilter.size() == 1); - assertTrue("Must be a single relationship called bob", theFilter.containsKey("bob")); - BeanPropertiesFilter aFilter = theFilter.get("bob"); - assertTrue("No bean properties specified so need a BeanPropertiesFilter.ALLOW_ALL class", BeanPropertiesFilter.AllProperties.class.equals(aFilter.getClass())); - - theFilter = ResourceWebScriptHelper.getRelationFilter("bob,hope"); - assertNotNull(theFilter); - assertTrue("Must be a two relationships", theFilter.size() == 2); - assertTrue("Must have hope.", theFilter.containsKey("hope")); - aFilter = theFilter.get("hope"); - assertTrue("No bean properties specified so need a BeanPropertiesFilter.ALLOW_ALL class", BeanPropertiesFilter.AllProperties.class.equals(aFilter.getClass())); - - theFilter = ResourceWebScriptHelper.getRelationFilter("bob(name),hope"); - assertNotNull(theFilter); - assertTrue("Must be a two relationships", theFilter.size() == 2); - assertTrue("Must have bob.", theFilter.containsKey("bob")); - aFilter = theFilter.get("bob"); - assertTrue("Bean properties specified so must be an BeanPropertiesFilter class", BeanPropertiesFilter.class.equals(aFilter.getClass())); - - theFilter = ResourceWebScriptHelper.getRelationFilter("bob,hope(age,name)"); - assertNotNull(theFilter); - assertTrue("Must be a two relationships", theFilter.size() == 2); - aFilter = theFilter.get("bob"); - assertTrue("No bean properties specified so need a BeanPropertiesFilter.ALLOW_ALL class", BeanPropertiesFilter.AllProperties.class.equals(aFilter.getClass())); - aFilter = theFilter.get("hope"); - assertTrue("Bean properties specified so must be an BeanPropertiesFilter class", BeanPropertiesFilter.class.equals(aFilter.getClass())); - - - theFilter = ResourceWebScriptHelper.getRelationFilter("bob(name,age),nohope,hope(height,width)"); - assertNotNull(theFilter); - assertTrue("Must be a three relationships", theFilter.size() == 3); - aFilter = theFilter.get("bob"); - assertTrue("Bean properties specified so must be an BeanPropertiesFilter class", BeanPropertiesFilter.class.equals(aFilter.getClass())); - aFilter = theFilter.get("nohope"); - assertTrue("No bean properties specified so need a ReturnAllBeanProperties class", BeanPropertiesFilter.AllProperties.class.equals(aFilter.getClass())); - aFilter = theFilter.get("hope"); - assertTrue("Bean properties specified so must be an BeanPropertiesFilter class", BeanPropertiesFilter.class.equals(aFilter.getClass())); - - } - @Test public void setUniqueIdTest() { @@ -405,162 +83,5 @@ public class ResourceWebScriptHelperTests ResourceWebScriptHelper.setUniqueId(invalidbj, "error"); assertNotNull("There should not be an error, errors should be swallowed up.",invalidbj); } - - @Test - public void findPagingTest() - { - WebScriptRequest request = mock(WebScriptRequest.class); - when(request.getParameter("skipCount")).thenReturn("34"); - when(request.getParameter("maxItems")).thenReturn("50"); - - Paging pagin = ResourceWebScriptHelper.findPaging(request); - assertNotNull(pagin); - assertTrue(pagin.getSkipCount() == 34); - assertTrue(pagin.getMaxItems() == 50); - - request = mock(WebScriptRequest.class); - when(request.getParameter("skipCount")).thenReturn(null); - when(request.getParameter("maxItems")).thenReturn(null); - pagin = ResourceWebScriptHelper.findPaging(request); - assertNotNull(pagin); - assertTrue(pagin.getSkipCount() == Paging.DEFAULT_SKIP_COUNT); - assertTrue(pagin.getMaxItems() == Paging.DEFAULT_MAX_ITEMS); - - request = mock(WebScriptRequest.class); - when(request.getParameter("skipCount")).thenReturn("55"); - pagin = ResourceWebScriptHelper.findPaging(request); - assertNotNull(pagin); - assertTrue(pagin.getSkipCount() == 55); - assertTrue(pagin.getMaxItems() == Paging.DEFAULT_MAX_ITEMS); - - request = mock(WebScriptRequest.class); - when(request.getParameter("skipCount")).thenReturn(null); - when(request.getParameter("maxItems")).thenReturn("45"); - pagin = ResourceWebScriptHelper.findPaging(request); - assertNotNull(pagin); - assertTrue(pagin.getMaxItems() == 45); - assertTrue(pagin.getSkipCount() == Paging.DEFAULT_SKIP_COUNT); - - request = mock(WebScriptRequest.class); - when(request.getParameter("skipCount")).thenReturn("apple"); - when(request.getParameter("maxItems")).thenReturn("pear"); - try - { - pagin = ResourceWebScriptHelper.findPaging(request); - fail("Should not get here."); - } - catch (InvalidArgumentException iae) - { - assertNotNull(iae); // Must throw this exceptions - } - - request = mock(WebScriptRequest.class); - when(request.getParameter("skipCount")).thenReturn("0"); - when(request.getParameter("maxItems")).thenReturn("0"); - try - { - pagin = ResourceWebScriptHelper.findPaging(request); - fail("Should not get here."); - } - catch (InvalidArgumentException iae) - { - assertNotNull(iae); // Must throw this exceptions - } - - //Test Case cloud-2198 - request = mock(WebScriptRequest.class); - when(request.getParameter("skipCount")).thenReturn("0"); - when(request.getParameter("maxItems")).thenReturn("a"); - try - { - pagin = ResourceWebScriptHelper.findPaging(request); - fail("Should not get here."); - } - catch (InvalidArgumentException iae) - { - assertNotNull(iae); // Must throw this exceptions - } - - request = mock(WebScriptRequest.class); - when(request.getParameter("skipCount")).thenReturn("s"); - when(request.getParameter("maxItems")).thenReturn("5"); - try - { - pagin = ResourceWebScriptHelper.findPaging(request); - fail("Should not get here."); - } - catch (InvalidArgumentException iae) - { - assertNotNull(iae); // Must throw this exceptions - } - - request = mock(WebScriptRequest.class); - when(request.getParameter("skipCount")).thenReturn("0"); - when(request.getParameter("maxItems")).thenReturn("-2"); - try - { - pagin = ResourceWebScriptHelper.findPaging(request); - fail("Should not get here."); - } - catch (InvalidArgumentException iae) - { - assertNotNull(iae); // Must throw this exceptions - } - - request = mock(WebScriptRequest.class); - when(request.getParameter("skipCount")).thenReturn("-3"); - when(request.getParameter("maxItems")).thenReturn("5"); - try - { - pagin = ResourceWebScriptHelper.findPaging(request); - fail("Should not get here."); - } - catch (InvalidArgumentException iae) - { - assertNotNull(iae); // Must throw this exceptions - } - - request = mock(WebScriptRequest.class); - when(request.getParameter("maxItems")).thenReturn("5"); - pagin = ResourceWebScriptHelper.findPaging(request); - assertNotNull(pagin); - assertTrue("skip count defaults to 0", pagin.getSkipCount() == Paging.DEFAULT_SKIP_COUNT); - //End of Test Case cloud-2198 - } - - @Test - public void paramsTest() - { - Map> mockParams = new HashMap>(); - mockParams.put("age", Arrays.asList("23","45")); - mockParams.put("name", Arrays.asList("fred")); - WebScriptRequest request = mockRequest(mockParams); - Map params = ResourceWebScriptHelper.getRequestParameters(request); - assertNotNull(params); - Params paramObj = ParamsExtender.valueOf(params); - assertNotNull(paramObj); - String aValue = paramObj.getParameter("age"); - assertEquals("23", aValue); - - aValue = paramObj.getParameter("name"); - assertEquals("fred", aValue); - - } - - private WebScriptRequest mockRequest(final Map> params) - { - final String[] paramNames = params.keySet().toArray(new String[]{}); - WebScriptRequest request = mock(WebScriptRequest.class); - when(request.getParameterNames()).thenReturn(paramNames); - when(request.getParameterValues(anyString())).thenAnswer(new Answer() { - @Override - public String[] answer(InvocationOnMock invocation) throws Throwable { - Object[] args = invocation.getArguments(); - return params.get((String) args[0]).toArray(new String[]{}); - } - }); - return request; - } - } diff --git a/source/test-java/org/alfresco/rest/framework/tests/core/SerializeTests.java b/source/test-java/org/alfresco/rest/framework/tests/core/SerializeTests.java index a8801bfd63..b937c6d3c2 100644 --- a/source/test-java/org/alfresco/rest/framework/tests/core/SerializeTests.java +++ b/source/test-java/org/alfresco/rest/framework/tests/core/SerializeTests.java @@ -57,6 +57,7 @@ import org.alfresco.rest.framework.tests.api.mocks.Grass; import org.alfresco.rest.framework.tests.api.mocks.Sheep; import org.alfresco.rest.framework.tests.api.mocks3.Flock; import org.alfresco.rest.framework.tests.api.mocks3.SlimGoat; +import org.alfresco.rest.framework.tools.RecognizedParamsExtractor; import org.alfresco.rest.framework.webscripts.AbstractResourceWebScript; import org.alfresco.rest.framework.webscripts.ResourceWebScriptHelper; import org.alfresco.service.cmr.repository.NodeRef; @@ -91,7 +92,7 @@ import java.util.Locale; import java.util.Map; import java.util.Set; -public class SerializeTests extends AbstractContextTest +public class SerializeTests extends AbstractContextTest implements RecognizedParamsExtractor { @Test @@ -197,7 +198,7 @@ public class SerializeTests extends AbstractContextTest public void testExpandRelations() throws IOException { assertNotNull(helper); - Map rFilter = ResourceWebScriptHelper.getRelationFilter("blacksheep,baaahh"); + Map rFilter = getRelationFilter("blacksheep,baaahh"); ExecutionResult res = (ExecutionResult) helper.processAdditionsToTheResponse(mock(WebScriptResponse.class), api,"sheep",ParamsExtender.valueOf(rFilter,"1"),new Farmer("180")); assertNotNull(res); String out = writeResponse(res); @@ -239,7 +240,7 @@ public class SerializeTests extends AbstractContextTest public void testExpandRecursiveRelations() throws IOException { ExecutionResult exec1 = new ExecutionResult(new Farmer("180"),null); - ExecutionResult exec2 = new ExecutionResult(new Farmer("456"),ResourceWebScriptHelper.getFilter("age")); + ExecutionResult exec2 = new ExecutionResult(new Farmer("456"),getFilter("age")); CollectionWithPagingInfo coll = CollectionWithPagingInfo.asPaged(null, Arrays.asList(exec1, exec2)); ExecutionResult execResult = new ExecutionResult(new Sheep("ssheep"),null); Map related = new HashMap(); @@ -436,12 +437,12 @@ public class SerializeTests extends AbstractContextTest public void testFilter() throws IOException, JSONException { assertNotNull(helper); - BeanPropertiesFilter theFilter = ResourceWebScriptHelper.getFilter("age"); + BeanPropertiesFilter theFilter = getFilter("age"); Object res = new ExecutionResult(new Sheep("bob"),theFilter); String out = writeResponse(res); assertTrue("Filter must only return the age.", StringUtils.contains(out, "{\"age\":3}")); - theFilter = ResourceWebScriptHelper.getFilter("age,name"); + theFilter = getFilter("age,name"); res = new ExecutionResult(new Sheep("bob"),theFilter); out = writeResponse(res); JSONObject jsonRsp = new JSONObject(new JSONTokener(out)); @@ -452,8 +453,8 @@ public class SerializeTests extends AbstractContextTest assertTrue("The age should be 3", entry.getInt("age") == 3); // unit test filter with "include" taking precendence over "fields" filter - List theInclude = ResourceWebScriptHelper.getIncludeClause("name"); - theFilter = ResourceWebScriptHelper.getFilter("age", theInclude); + List theInclude = getIncludeClause("name"); + theFilter = getFilter("age", theInclude); res = new ExecutionResult(new Sheep("bob"),theFilter); out = writeResponse(res); jsonRsp = new JSONObject(new JSONTokener(out)); @@ -464,7 +465,7 @@ public class SerializeTests extends AbstractContextTest assertTrue("The age should be 3", entry.getInt("age") == 3); Api v3 = Api.valueOf(api.getName(), api.getScope().toString(), "3"); - Map relFiler = ResourceWebScriptHelper.getRelationFilter("herd"); + Map relFiler = getRelationFilter("herd"); res = helper.processAdditionsToTheResponse(mock(WebScriptResponse.class), v3,"goat",ParamsExtender.valueOf(relFiler, "notUsed"),new SlimGoat()); out = writeResponse(res); jsonRsp = new JSONObject(new JSONTokener(out)); @@ -476,7 +477,7 @@ public class SerializeTests extends AbstractContextTest assertEquals("The name should be 'bigun'", "bigun", entry.getString("name")); assertTrue("The quantity should be 56", entry.getInt("quantity") == 56); - relFiler = ResourceWebScriptHelper.getRelationFilter("herd(name)"); + relFiler = getRelationFilter("herd(name)"); res = helper.processAdditionsToTheResponse(mock(WebScriptResponse.class), v3,"goat",ParamsExtender.valueOf(relFiler, "notUsed"),new SlimGoat()); out = writeResponse(res); assertTrue("Must return only the herd name.", StringUtils.contains(out, "{\"name\":\"bigun\"}")); diff --git a/source/test-java/org/alfresco/rest/framework/tests/core/WhereTests.java b/source/test-java/org/alfresco/rest/framework/tests/core/WhereTests.java index b28708e9e1..878cba9992 100644 --- a/source/test-java/org/alfresco/rest/framework/tests/core/WhereTests.java +++ b/source/test-java/org/alfresco/rest/framework/tests/core/WhereTests.java @@ -37,16 +37,17 @@ import org.alfresco.rest.framework.resource.parameters.where.InvalidQueryExcepti import org.alfresco.rest.framework.resource.parameters.where.Query; import org.alfresco.rest.framework.resource.parameters.where.QueryHelper; import org.alfresco.rest.framework.resource.parameters.where.QueryHelper.WalkerCallbackAdapter; -import org.alfresco.rest.framework.webscripts.ResourceWebScriptHelper; +import org.alfresco.rest.framework.tools.RecognizedParamsExtractor; import org.antlr.runtime.tree.CommonTree; import org.junit.Test; -public class WhereTests { +public class WhereTests implements RecognizedParamsExtractor +{ @Test public void basicTest() throws IOException { - Query theQuery = ResourceWebScriptHelper.getWhereClause(" ( fred > g ) "); + Query theQuery = getWhereClause(" ( fred > g ) "); CommonTree ast = theQuery.getTree(); //check AST structure assertEquals(WhereClauseParser.GREATERTHAN, ast.getType()); @@ -57,13 +58,13 @@ public class WhereTests { @Test public void existClauseTest() { - Query theQuery = ResourceWebScriptHelper.getWhereClause(null); + Query theQuery = getWhereClause(null); assertNotNull(theQuery); assertTrue("Null passed in so nothing to theQuery.", theQuery.getTree() == null); try { - theQuery = ResourceWebScriptHelper.getWhereClause("fred"); + theQuery = getWhereClause("fred"); fail("Should throw an InvalidQueryException"); } catch (InvalidQueryException error) @@ -73,7 +74,7 @@ public class WhereTests { try { - theQuery = ResourceWebScriptHelper.getWhereClause("(noClosingBracket"); + theQuery = getWhereClause("(noClosingBracket"); fail("Should throw an InvalidQueryException"); } catch (InvalidQueryException error) @@ -83,7 +84,7 @@ public class WhereTests { try { - theQuery = ResourceWebScriptHelper.getWhereClause("noOpeningBracket)"); + theQuery = getWhereClause("noOpeningBracket)"); fail("Should throw an InvalidQueryException"); } catch (InvalidQueryException error) @@ -94,7 +95,7 @@ public class WhereTests { try { - theQuery = ResourceWebScriptHelper.getWhereClause("(EXISTS(target.file))"); + theQuery = getWhereClause("(EXISTS(target.file))"); fail("Should throw an InvalidQueryException"); } catch (InvalidQueryException error) @@ -102,34 +103,34 @@ public class WhereTests { //this is correct } - theQuery = ResourceWebScriptHelper.getWhereClause("(exists(/target/file))"); + theQuery = getWhereClause("(exists(/target/file))"); assertExistsPropertyEquals("/target/file", theQuery, false); - theQuery = ResourceWebScriptHelper.getWhereClause("(EXISTS(b))"); + theQuery = getWhereClause("(EXISTS(b))"); assertExistsPropertyEquals("b", theQuery, false); - theQuery = ResourceWebScriptHelper.getWhereClause(" ( EXISTS ( whitespace ) ) "); + theQuery = getWhereClause(" ( EXISTS ( whitespace ) ) "); assertExistsPropertyEquals("whitespace", theQuery, false); - theQuery = ResourceWebScriptHelper.getWhereClause("(exists ( folder ))"); + theQuery = getWhereClause("(exists ( folder ))"); assertExistsPropertyEquals("folder", theQuery, false); - theQuery = ResourceWebScriptHelper.getWhereClause("(NOT EXISTS(b))"); + theQuery = getWhereClause("(NOT EXISTS(b))"); assertExistsPropertyEquals("b", theQuery, true); - theQuery = ResourceWebScriptHelper.getWhereClause(" (NOT EXISTS(b))"); + theQuery = getWhereClause(" (NOT EXISTS(b))"); assertExistsPropertyEquals("b", theQuery, true); - theQuery = ResourceWebScriptHelper.getWhereClause("( NOT EXISTS(b))"); + theQuery = getWhereClause("( NOT EXISTS(b))"); assertExistsPropertyEquals("b", theQuery, true); - theQuery = ResourceWebScriptHelper.getWhereClause(" ( NOT EXISTS(b))"); + theQuery = getWhereClause(" ( NOT EXISTS(b))"); assertExistsPropertyEquals("b", theQuery, true); try { - theQuery = ResourceWebScriptHelper.getWhereClause("(exists folder)"); + theQuery = getWhereClause("(exists folder)"); fail("Should throw an InvalidQueryException, 'folder' should have a bracket around it"); } catch (InvalidQueryException error) @@ -137,7 +138,7 @@ public class WhereTests { //this is correct } - theQuery = ResourceWebScriptHelper.getWhereClause("(EXISTS(/target/folder) AND NOT EXISTS(/target/site))"); + theQuery = getWhereClause("(EXISTS(/target/folder) AND NOT EXISTS(/target/site))"); assertNotNull(theQuery); CommonTree tree = theQuery.getTree(); assertNotNull(tree); @@ -166,7 +167,7 @@ public class WhereTests { try { - theQuery = ResourceWebScriptHelper.getWhereClause("(EXISTS(/target/folder)OR EXISTS(/target/site))"); + theQuery = getWhereClause("(EXISTS(/target/folder)OR EXISTS(/target/site))"); fail("Should throw an InvalidQueryException, the OR should have a space before it."); } catch (InvalidQueryException error) @@ -174,7 +175,7 @@ public class WhereTests { //this is correct } - theQuery = ResourceWebScriptHelper.getWhereClause("(NOT EXISTS(/target/folder) OR EXISTS(/target/site))"); + theQuery = getWhereClause("(NOT EXISTS(/target/folder) OR EXISTS(/target/site))"); QueryHelper.walk(theQuery, new WalkerCallbackAdapter(){ @Override public void exists(String propertyName, boolean negated) { @@ -196,7 +197,7 @@ public class WhereTests { }); - theQuery = ResourceWebScriptHelper.getWhereClause("(EXISTS ( /target/folder ) OR EXISTS( /target/site ) )"); + theQuery = getWhereClause("(EXISTS ( /target/folder ) OR EXISTS( /target/site ) )"); QueryHelper.walk(theQuery, new WalkerCallbackAdapter(){ int i=0; @Override @@ -220,7 +221,7 @@ public class WhereTests { }); - theQuery = ResourceWebScriptHelper.getWhereClause("(EXISTS(target/file) AND EXISTS(target/folder) AND EXISTS(target/site))"); + theQuery = getWhereClause("(EXISTS(target/file) AND EXISTS(target/folder) AND EXISTS(target/site))"); QueryHelper.walk(theQuery, new WalkerCallbackAdapter(){ int i=0; @Override @@ -254,25 +255,25 @@ public class WhereTests { @Test public void inClauseTest() { - Query theQuery = ResourceWebScriptHelper.getWhereClause("( dueAt in (5,8) )"); + Query theQuery = getWhereClause("( dueAt in (5,8) )"); inChecks(theQuery, "dueAt", "5", "8"); - theQuery = ResourceWebScriptHelper.getWhereClause("( fred/bloggs in (head,elbow) )"); + theQuery = getWhereClause("( fred/bloggs in (head,elbow) )"); inChecks(theQuery, "fred/bloggs", "head", "elbow"); - theQuery = ResourceWebScriptHelper.getWhereClause("( nextOne in (5,8,4) )"); + theQuery = getWhereClause("( nextOne in (5,8,4) )"); inChecks(theQuery, "nextOne", "5", "8", "4"); - theQuery = ResourceWebScriptHelper.getWhereClause("( nextOne in (5,56,fred) )"); + theQuery = getWhereClause("( nextOne in (5,56,fred) )"); inChecks(theQuery, "nextOne", "5", "56", "fred"); - theQuery = ResourceWebScriptHelper.getWhereClause("( nextOne in (5,56,'fred&') )"); + theQuery = getWhereClause("( nextOne in (5,56,'fred&') )"); inChecks(theQuery, "nextOne", "5", "56", "fred&"); - theQuery = ResourceWebScriptHelper.getWhereClause("( nextOne in ('me , you',56,egg) )"); + theQuery = getWhereClause("( nextOne in ('me , you',56,egg) )"); inChecks(theQuery, "nextOne", "me , you", "56", "egg"); - theQuery = ResourceWebScriptHelper.getWhereClause("( NOT nextOne in (5,56,fred, king, kong, 'fred\\'^') )"); + theQuery = getWhereClause("( NOT nextOne in (5,56,fred, king, kong, 'fred\\'^') )"); CommonTree tree = theQuery.getTree(); assertNotNull(tree); QueryHelper.walk(theQuery, new WalkerCallbackAdapter(){ @@ -293,15 +294,15 @@ public class WhereTests { @Test public void betweenClauseTest() { - Query theQuery = ResourceWebScriptHelper.getWhereClause("( dueAt between (5,8) )"); + Query theQuery = getWhereClause("( dueAt between (5,8) )"); betweenChecks(theQuery, "dueAt", "5", "8"); - theQuery = ResourceWebScriptHelper.getWhereClause("( fred/bloggs between (head,elbow) )"); + theQuery = getWhereClause("( fred/bloggs between (head,elbow) )"); betweenChecks(theQuery, "fred/bloggs", "head", "elbow"); try { - theQuery = ResourceWebScriptHelper.getWhereClause("( nextOne between (5,8,4) )"); + theQuery = getWhereClause("( nextOne between (5,8,4) )"); fail("Should throw an InvalidQueryException, between can have only two values."); } catch (InvalidQueryException error) @@ -311,7 +312,7 @@ public class WhereTests { try { - theQuery = ResourceWebScriptHelper.getWhereClause("( nextOne between 5,8 )"); + theQuery = getWhereClause("( nextOne between 5,8 )"); fail("Should throw an InvalidQueryException, Need brackets."); } catch (InvalidQueryException error) @@ -319,7 +320,7 @@ public class WhereTests { //this is correct } - theQuery = ResourceWebScriptHelper.getWhereClause("(NOT dueAt between (5,8) AND nextOne between (green,blue))"); + theQuery = getWhereClause("(NOT dueAt between (5,8) AND nextOne between (green,blue))"); QueryHelper.walk(theQuery, new WalkerCallbackAdapter(){ @Override public void between(String property, String firstVal, String secondVal, boolean negated) { @@ -349,18 +350,18 @@ public class WhereTests { @Test public void matchesClauseTest() { - Query theQuery = ResourceWebScriptHelper.getWhereClause("(fred matches(bob))"); + Query theQuery = getWhereClause("(fred matches(bob))"); matchesChecks(theQuery, "fred", "bob"); - theQuery = ResourceWebScriptHelper.getWhereClause("( king/kong/hair/shoulders/knees/toes matches ('fred%') )"); + theQuery = getWhereClause("( king/kong/hair/shoulders/knees/toes matches ('fred%') )"); matchesChecks(theQuery, "king/kong/hair/shoulders/knees/toes", "fred%"); - theQuery = ResourceWebScriptHelper.getWhereClause("( niceone matches (bob) )"); + theQuery = getWhereClause("( niceone matches (bob) )"); matchesChecks(theQuery, "niceone", "bob"); try { - theQuery = ResourceWebScriptHelper.getWhereClause("( fred matches bob )"); + theQuery = getWhereClause("( fred matches bob )"); fail("Should throw an InvalidQueryException, Need brackets."); } catch (InvalidQueryException error) @@ -373,25 +374,25 @@ public class WhereTests { @Test public void comparisonClauseTest() { - Query theQuery = ResourceWebScriptHelper.getWhereClause("( dueAt > '12.04.345' )"); + Query theQuery = getWhereClause("( dueAt > '12.04.345' )"); int comparisonOperator = WhereClauseParser.GREATERTHAN; comparisonChecks(theQuery, comparisonOperator, "dueAt", "12.04.345"); - theQuery = ResourceWebScriptHelper.getWhereClause("( dueAt >= '12.04.345' )"); + theQuery = getWhereClause("( dueAt >= '12.04.345' )"); comparisonOperator = WhereClauseParser.GREATERTHANOREQUALS; comparisonChecks(theQuery, comparisonOperator, "dueAt", "12.04.345"); - theQuery = ResourceWebScriptHelper.getWhereClause("( dueAt < '12.04.345' )"); + theQuery = getWhereClause("( dueAt < '12.04.345' )"); comparisonOperator = WhereClauseParser.LESSTHAN; comparisonChecks(theQuery, comparisonOperator, "dueAt", "12.04.345"); - theQuery = ResourceWebScriptHelper.getWhereClause("( dueAt <= '12.04.345' )"); + theQuery = getWhereClause("( dueAt <= '12.04.345' )"); comparisonOperator = WhereClauseParser.LESSTHANOREQUALS; comparisonChecks(theQuery, comparisonOperator, "dueAt", "12.04.345"); try { - theQuery = ResourceWebScriptHelper.getWhereClause("( Fred/Bloggs = %$NICE&* )"); + theQuery = getWhereClause("( Fred/Bloggs = %$NICE&* )"); fail("Should throw an InvalidQueryException, needs single quotes"); } catch (InvalidQueryException error) @@ -399,13 +400,13 @@ public class WhereTests { //this is correct } - theQuery = ResourceWebScriptHelper.getWhereClause("( Fred/Bloggs = '%$NICE&*' )"); + theQuery = getWhereClause("( Fred/Bloggs = '%$NICE&*' )"); comparisonOperator = WhereClauseParser.EQUALS; comparisonChecks(theQuery, comparisonOperator, "Fred/Bloggs", "%$NICE&*"); try { - theQuery = ResourceWebScriptHelper.getWhereClause("( Ken = (456) )"); + theQuery = getWhereClause("( Ken = (456) )"); fail("Should throw an InvalidQueryException, needs single quotes no brackets"); } catch (InvalidQueryException error) @@ -413,15 +414,15 @@ public class WhereTests { //this is correct } - theQuery = ResourceWebScriptHelper.getWhereClause("( Ken = '456' )"); + theQuery = getWhereClause("( Ken = '456' )"); comparisonOperator = WhereClauseParser.EQUALS; comparisonChecks(theQuery, comparisonOperator, "Ken", "456"); - theQuery = ResourceWebScriptHelper.getWhereClause("( DogHouse = 'Cat\\\'s House' )"); + theQuery = getWhereClause("( DogHouse = 'Cat\\\'s House' )"); comparisonOperator = WhereClauseParser.EQUALS; comparisonChecks(theQuery, comparisonOperator, "DogHouse", "Cat\\\'s House"); - theQuery = ResourceWebScriptHelper.getWhereClause("( KING_KONG >= 'Mighty Mouse' )"); + theQuery = getWhereClause("( KING_KONG >= 'Mighty Mouse' )"); comparisonOperator = WhereClauseParser.GREATERTHANOREQUALS; comparisonChecks(theQuery, comparisonOperator, "KING_KONG", "Mighty Mouse"); @@ -442,25 +443,25 @@ public class WhereTests { @Test public void getChildrenTests() { - Query theQuery = ResourceWebScriptHelper.getWhereClause("(fred matches(bob))"); + Query theQuery = getWhereClause("(fred matches(bob))"); assertNotNull(theQuery); CommonTree tree = theQuery.getTree(); assertNotNull(tree); assertTrue(2 == QueryHelper.getChildren(tree).size()); - theQuery = ResourceWebScriptHelper.getWhereClause("( dueAt between (5,8) )"); + theQuery = getWhereClause("( dueAt between (5,8) )"); assertNotNull(theQuery); tree = theQuery.getTree(); assertNotNull(tree); assertTrue(3 == QueryHelper.getChildren(tree).size()); - theQuery = ResourceWebScriptHelper.getWhereClause("(NOT EXISTS(b))"); + theQuery = getWhereClause("(NOT EXISTS(b))"); assertNotNull(theQuery); tree = theQuery.getTree(); assertNotNull(tree); assertTrue(1 == QueryHelper.getChildren(tree).size()); - theQuery = ResourceWebScriptHelper.getWhereClause("(EXISTS(/target/folder) AND EXISTS(/target/site))"); + theQuery = getWhereClause("(EXISTS(/target/folder) AND EXISTS(/target/site))"); assertNotNull(theQuery); tree = theQuery.getTree(); assertNotNull(tree); diff --git a/source/test-java/org/alfresco/rest/framework/tests/core/WithResponseTest.java b/source/test-java/org/alfresco/rest/framework/tests/core/WithResponseTest.java index 23901abdd7..239ac2e3a7 100644 --- a/source/test-java/org/alfresco/rest/framework/tests/core/WithResponseTest.java +++ b/source/test-java/org/alfresco/rest/framework/tests/core/WithResponseTest.java @@ -39,6 +39,7 @@ import static org.mockito.Mockito.when; import org.alfresco.rest.framework.resource.content.ContentInfo; import org.alfresco.rest.framework.resource.content.ContentInfoImpl; import org.alfresco.rest.framework.tools.ApiAssistant; +import org.alfresco.rest.framework.tools.ResponseWriter; import org.alfresco.rest.framework.webscripts.AbstractResourceWebScript; import org.alfresco.rest.framework.webscripts.ApiWebScript; import org.alfresco.rest.framework.webscripts.ResourceWebScriptDelete; @@ -70,17 +71,17 @@ public class WithResponseTest @Test public void testDefaults() throws Exception { - WithResponse callBack = new WithResponse(Status.STATUS_OK,ApiAssistant.DEFAULT_JSON_CONTENT, ApiAssistant.CACHE_NEVER); + WithResponse callBack = new WithResponse(Status.STATUS_OK, ResponseWriter.DEFAULT_JSON_CONTENT, ResponseWriter.CACHE_NEVER); assertEquals(Status.STATUS_OK, callBack.getStatus()); - assertEquals(ApiAssistant.DEFAULT_JSON_CONTENT, callBack.getContentInfo()); - assertEquals(ApiAssistant.CACHE_NEVER, callBack.getCache()); + assertEquals(ResponseWriter.DEFAULT_JSON_CONTENT, callBack.getContentInfo()); + assertEquals(ResponseWriter.CACHE_NEVER, callBack.getCache()); assertTrue(callBack.getHeaders().isEmpty()); } @Test public void testSetHeader() throws Exception { - WithResponse callBack = new WithResponse(Status.STATUS_OK,ApiAssistant.DEFAULT_JSON_CONTENT, ApiAssistant.CACHE_NEVER); + WithResponse callBack = new WithResponse(Status.STATUS_OK,ResponseWriter.DEFAULT_JSON_CONTENT, ResponseWriter.CACHE_NEVER); callBack.setHeader("king", "can"); callBack.setHeader("king", "kong"); assertTrue(callBack.getHeaders().size() == 1); @@ -92,7 +93,7 @@ public class WithResponseTest @Test public void testAddHeader() throws Exception { - WithResponse callBack = new WithResponse(Status.STATUS_OK,ApiAssistant.DEFAULT_JSON_CONTENT, ApiAssistant.CACHE_NEVER); + WithResponse callBack = new WithResponse(Status.STATUS_OK,ResponseWriter.DEFAULT_JSON_CONTENT, ResponseWriter.CACHE_NEVER); callBack.addHeader("king", "can"); callBack.addHeader("king", "kong"); assertTrue(callBack.getHeaders().size() == 1); @@ -105,7 +106,7 @@ public class WithResponseTest @Test public void testSetters() throws Exception { - WithResponse callBack = new WithResponse(Status.STATUS_OK, ApiAssistant.DEFAULT_JSON_CONTENT, ApiAssistant.CACHE_NEVER); + WithResponse callBack = new WithResponse(Status.STATUS_OK, ResponseWriter.DEFAULT_JSON_CONTENT, ResponseWriter.CACHE_NEVER); callBack.setStatus(Status.STATUS_GONE); Cache myCache = new Cache(new Description.RequiredCache() { @@ -142,7 +143,7 @@ public class WithResponseTest { AbstractResourceWebScript responseWriter = new ResourceWebScriptDelete(); responseWriter.setAssistant(new ApiAssistant()); - WithResponse wr = new WithResponse(Status.STATUS_OK, ApiAssistant.DEFAULT_JSON_CONTENT, ApiAssistant.CACHE_NEVER); + WithResponse wr = new WithResponse(Status.STATUS_OK, ResponseWriter.DEFAULT_JSON_CONTENT, ResponseWriter.CACHE_NEVER); WebScriptResponse response = mock(WebScriptResponse.class); diff --git a/source/test-java/org/alfresco/rest/framework/tools/RecognizedParamsExtractorTest.java b/source/test-java/org/alfresco/rest/framework/tools/RecognizedParamsExtractorTest.java new file mode 100644 index 0000000000..04b4ffca7e --- /dev/null +++ b/source/test-java/org/alfresco/rest/framework/tools/RecognizedParamsExtractorTest.java @@ -0,0 +1,539 @@ +/* + * #%L + * Alfresco Remote API + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.rest.framework.tools; + +import static org.junit.Assert.*; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException; +import org.alfresco.rest.framework.jacksonextensions.BeanPropertiesFilter; +import org.alfresco.rest.framework.resource.parameters.InvalidSelectException; +import org.alfresco.rest.framework.resource.parameters.Paging; +import org.alfresco.rest.framework.resource.parameters.Params; +import org.alfresco.rest.framework.resource.parameters.SortColumn; +import org.alfresco.rest.framework.tests.core.ParamsExtender; +import org.junit.Test; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; +import org.springframework.extensions.webscripts.WebScriptRequest; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Test the RecognizedParamsExtractor + * + * @author Gethin James + */ +public class RecognizedParamsExtractorTest implements RecognizedParamsExtractor +{ + + + @Test + public void getFilterTest() + { + BeanPropertiesFilter theFilter = getFilter(null); + assertNotNull(theFilter); + assertTrue("Null passed in so must return the default BeanPropertiesFilter.ALLOW_ALL class", BeanPropertiesFilter.AllProperties.class.equals(theFilter.getClass())); + + theFilter = getFilter("bob"); + assertNotNull(theFilter); + assertTrue("Must return the BeanPropertiesFilter class", theFilter instanceof BeanPropertiesFilter); + + theFilter = getFilter("50,fred,b.z"); + assertNotNull(theFilter); + assertTrue("Must return the BeanPropertiesFilter class", theFilter instanceof BeanPropertiesFilter); + + theFilter = getFilter("50,fred,"); + assertNotNull(theFilter); + assertTrue("Must return the BeanPropertiesFilter class", theFilter instanceof BeanPropertiesFilter); + } + + + @Test + public void getSortingTest() + { + List theSort = getSort(null); + assertNotNull(theSort); + assertTrue("Null passed in so empty sort list should be returned.", theSort.isEmpty()); + + theSort = getSort("name ASC"); + assertNotNull(theSort); + assertTrue("Must have a value for column: NAME", !theSort.isEmpty()); + assertTrue(theSort.size() == 1); + assertEquals("name", theSort.get(0).column); + assertTrue(theSort.get(0).asc); + + theSort = getSort("name "); + assertNotNull(theSort); + assertTrue("Must have a value for column: NAME", !theSort.isEmpty()); + assertTrue(theSort.size() == 1); + assertEquals("name", theSort.get(0).column); + assertTrue(theSort.get(0).asc); + + theSort = getSort("name DESC"); + assertNotNull(theSort); + assertTrue("Must have a value for column: NAME", !theSort.isEmpty()); + assertTrue(theSort.size() == 1); + assertEquals("name", theSort.get(0).column); + assertTrue(!theSort.get(0).asc); //desc + + theSort = getSort("name desc"); + assertNotNull(theSort); + assertTrue("Must have a value for column: NAME", !theSort.isEmpty()); + assertTrue(theSort.size() == 1); + assertEquals("name", theSort.get(0).column); + assertTrue(!theSort.get(0).asc); //desc + + theSort = getSort("name,age desc"); + assertNotNull(theSort); + assertTrue("Must have a value for column: NAME", !theSort.isEmpty()); + assertTrue(theSort.size() == 2); + assertEquals("name", theSort.get(0).column); + assertTrue(theSort.get(0).asc); + assertEquals("age", theSort.get(1).column); + assertTrue(!theSort.get(1).asc); //desc + + theSort = getSort(" name, age desc"); + assertNotNull(theSort); + assertTrue("Must have a value for column: NAME", !theSort.isEmpty()); + assertTrue(theSort.size() == 2); + assertEquals("name", theSort.get(0).column); + assertTrue(theSort.get(0).asc); + assertEquals("age", theSort.get(1).column); + assertTrue(!theSort.get(1).asc); //desc + + theSort = getSort("name DESC, age desc"); + assertNotNull(theSort); + assertTrue("Must have a value for column: NAME", !theSort.isEmpty()); + assertTrue(theSort.size() == 2); + assertEquals("name", theSort.get(0).column); + assertTrue(!theSort.get(0).asc); //desc + assertEquals("age", theSort.get(1).column); + assertTrue(!theSort.get(1).asc); //desc + + theSort = getSort("age Desc, name Asc"); + assertNotNull(theSort); + assertTrue("Must have a value for column: NAME", !theSort.isEmpty()); + assertTrue(theSort.size() == 2); + assertEquals("age", theSort.get(0).column); + assertTrue(!theSort.get(0).asc); //desc + assertEquals("name", theSort.get(1).column); + assertTrue(theSort.get(1).asc); + + theSort = getSort("name des"); //invalid, should be desc + assertNotNull(theSort); + assertTrue("Must have a value for column: NAME", !theSort.isEmpty()); + assertTrue(theSort.size() == 1); + assertEquals("name", theSort.get(0).column); + assertTrue(theSort.get(0).asc); //Defaults to ascending because the sort order was invalid + + theSort = getSort("name asc,"); //invalid, should be desc + assertNotNull(theSort); + assertTrue("Must have a value for column: NAME", !theSort.isEmpty()); + assertTrue(theSort.size() == 1); + assertEquals("name", theSort.get(0).column); + assertTrue(theSort.get(0).asc); + } + + @Test + public void getIncludeClauseTest() + { + getClauseTest("include"); + } + + @Test + public void getSelectClauseTest() + { + getClauseTest("select"); + } + + // at the moment select and include are parsed the same way, hence common/shared test + private void getClauseTest(String paramName) + { + List theClause = getCorrectClause(paramName, null); + assertNotNull(theClause); + assertFalse("Null passed in so nothing in the "+paramName, theClause.size() > 0); + + try + { + theClause = getCorrectClause(paramName, ",,,"); + fail("Should throw an InvalidSelectException"); + } + catch (InvalidSelectException error) + { + //this is correct + } + + try + { + theClause = getCorrectClause(paramName, "(,,,"); + fail("Should throw an InvalidSelectException"); + } + catch (InvalidSelectException error) + { + //this is correct + } + + try + { + theClause = getCorrectClause(paramName, "(,,,)"); + fail("Should throw an InvalidSelectException"); + } + catch (InvalidSelectException error) + { + //this is correct + } + + try + { + theClause = getCorrectClause(paramName, "x/,z"); + fail("Should throw an InvalidSelectException"); + } + catch (InvalidSelectException error) + { + //this is correct + } + + try + { + theClause = getCorrectClause(paramName, "/x'n,/z"); + fail("Should throw an InvalidSelectException"); + } + catch (InvalidSelectException error) + { + //this is correct + } + + try + { + theClause = getCorrectClause(paramName, "/foo/0"); + fail("Should throw an InvalidSelectException. Legal identifiers must start with a letter not zero"); + } + catch (InvalidSelectException error) + { + //this is correct + } + + try + { + theClause = getCorrectClause(paramName, "/"); + fail("Should throw an InvalidSelectException. No identifier specified."); + } + catch (InvalidSelectException error) + { + //this is correct + } + + try + { + theClause = getCorrectClause(paramName, "path, isLink"); + fail("Should throw an InvalidSelectException. No identifier specified."); + } + catch (InvalidSelectException error) + { + //this is correct + } + + theClause = getCorrectClause(paramName, "king/kong"); + assertTrue("has a valid "+paramName, theClause.size() == 1); + assertEquals("king/kong",theClause.get(0)); + + theClause = getCorrectClause(paramName, "x,y"); + assertTrue("has a valid "+paramName, theClause.size() == 2); + assertEquals("x",theClause.get(0)); + assertEquals("y",theClause.get(1)); + + theClause = getCorrectClause(paramName, "x,/z"); + assertTrue("has a valid "+paramName, theClause.size() == 2); + assertEquals("x",theClause.get(0)); + assertEquals("/z",theClause.get(1)); + + theClause = getCorrectClause(paramName, "/b"); + assertTrue("has a valid "+paramName, theClause.size() == 1); + assertEquals("/b",theClause.get(0)); + + theClause = getCorrectClause(paramName, "/be,/he"); + assertTrue("has a valid "+paramName, theClause.size() == 2); + assertEquals("/be",theClause.get(0)); + assertEquals("/he",theClause.get(1)); + + theClause = getCorrectClause(paramName, "/king/kong"); + assertTrue("has a valid "+paramName, theClause.size() == 1); + assertEquals("/king/kong",theClause.get(0)); + + theClause = getCorrectClause(paramName, "/name,/person/age"); + assertTrue("has a valid "+paramName, theClause.size() == 2); + assertEquals("/name",theClause.get(0)); + assertEquals("/person/age",theClause.get(1)); + + theClause = getCorrectClause(paramName, "/foo"); + assertTrue("has a valid select",theClause.size() == 1); + assertEquals("/foo",theClause.get(0)); + + theClause = getCorrectClause(paramName, "/foo/anArray/x"); + assertTrue("has a valid "+paramName, theClause.size() == 1); + assertEquals("/foo/anArray/x",theClause.get(0)); + + theClause = getCorrectClause(paramName, "/foo/anArray/x,/person/age,/eggs/bacon/sausage,/p"); + assertTrue("has a valid "+paramName, theClause.size() == 4); + assertEquals("/foo/anArray/x",theClause.get(0)); + assertEquals("/person/age",theClause.get(1)); + assertEquals("/eggs/bacon/sausage",theClause.get(2)); + assertEquals("/p",theClause.get(3)); + + theClause = getCorrectClause(paramName, "/foo/_bar "); + assertTrue("has a valid "+paramName, theClause.size() == 1); + assertEquals("/foo/_bar",theClause.get(0)); + } + + private List getCorrectClause(String paramName, String paramValue) + { + if (paramName.equalsIgnoreCase("include")) + { + return getIncludeClause(paramValue); + } + else if (paramName.equalsIgnoreCase("select")) + { + return getSelectClause(paramValue); + } + + fail("Unexpected clause: "+paramName); + return null; + } + + @Test + public void getRelationFilterTest() + { + Map theFilter = getRelationFilter(null); + assertNotNull(theFilter); + assertTrue("Null passed in so nothing to filter.",theFilter.isEmpty()); + + theFilter = getRelationFilter("bob"); + assertNotNull(theFilter); + assertTrue("Must be a single relationship", theFilter.size() == 1); + assertTrue("Must be a single relationship called bob", theFilter.containsKey("bob")); + BeanPropertiesFilter aFilter = theFilter.get("bob"); + assertTrue("No bean properties specified so need a BeanPropertiesFilter.ALLOW_ALL class", BeanPropertiesFilter.AllProperties.class.equals(aFilter.getClass())); + + theFilter = getRelationFilter("bob,hope"); + assertNotNull(theFilter); + assertTrue("Must be a two relationships", theFilter.size() == 2); + assertTrue("Must have hope.", theFilter.containsKey("hope")); + aFilter = theFilter.get("hope"); + assertTrue("No bean properties specified so need a BeanPropertiesFilter.ALLOW_ALL class", BeanPropertiesFilter.AllProperties.class.equals(aFilter.getClass())); + + theFilter = getRelationFilter("bob(name),hope"); + assertNotNull(theFilter); + assertTrue("Must be a two relationships", theFilter.size() == 2); + assertTrue("Must have bob.", theFilter.containsKey("bob")); + aFilter = theFilter.get("bob"); + assertTrue("Bean properties specified so must be an BeanPropertiesFilter class", BeanPropertiesFilter.class.equals(aFilter.getClass())); + + theFilter = getRelationFilter("bob,hope(age,name)"); + assertNotNull(theFilter); + assertTrue("Must be a two relationships", theFilter.size() == 2); + aFilter = theFilter.get("bob"); + assertTrue("No bean properties specified so need a BeanPropertiesFilter.ALLOW_ALL class", BeanPropertiesFilter.AllProperties.class.equals(aFilter.getClass())); + aFilter = theFilter.get("hope"); + assertTrue("Bean properties specified so must be an BeanPropertiesFilter class", BeanPropertiesFilter.class.equals(aFilter.getClass())); + + + theFilter = getRelationFilter("bob(name,age),nohope,hope(height,width)"); + assertNotNull(theFilter); + assertTrue("Must be a three relationships", theFilter.size() == 3); + aFilter = theFilter.get("bob"); + assertTrue("Bean properties specified so must be an BeanPropertiesFilter class", BeanPropertiesFilter.class.equals(aFilter.getClass())); + aFilter = theFilter.get("nohope"); + assertTrue("No bean properties specified so need a ReturnAllBeanProperties class", BeanPropertiesFilter.AllProperties.class.equals(aFilter.getClass())); + aFilter = theFilter.get("hope"); + assertTrue("Bean properties specified so must be an BeanPropertiesFilter class", BeanPropertiesFilter.class.equals(aFilter.getClass())); + + } + + + @Test + public void findPagingTest() + { + WebScriptRequest request = mock(WebScriptRequest.class); + when(request.getParameter("skipCount")).thenReturn("34"); + when(request.getParameter("maxItems")).thenReturn("50"); + + Paging pagin = findPaging(request); + assertNotNull(pagin); + assertTrue(pagin.getSkipCount() == 34); + assertTrue(pagin.getMaxItems() == 50); + + request = mock(WebScriptRequest.class); + when(request.getParameter("skipCount")).thenReturn(null); + when(request.getParameter("maxItems")).thenReturn(null); + pagin = findPaging(request); + assertNotNull(pagin); + assertTrue(pagin.getSkipCount() == Paging.DEFAULT_SKIP_COUNT); + assertTrue(pagin.getMaxItems() == Paging.DEFAULT_MAX_ITEMS); + + request = mock(WebScriptRequest.class); + when(request.getParameter("skipCount")).thenReturn("55"); + pagin = findPaging(request); + assertNotNull(pagin); + assertTrue(pagin.getSkipCount() == 55); + assertTrue(pagin.getMaxItems() == Paging.DEFAULT_MAX_ITEMS); + + request = mock(WebScriptRequest.class); + when(request.getParameter("skipCount")).thenReturn(null); + when(request.getParameter("maxItems")).thenReturn("45"); + pagin = findPaging(request); + assertNotNull(pagin); + assertTrue(pagin.getMaxItems() == 45); + assertTrue(pagin.getSkipCount() == Paging.DEFAULT_SKIP_COUNT); + + request = mock(WebScriptRequest.class); + when(request.getParameter("skipCount")).thenReturn("apple"); + when(request.getParameter("maxItems")).thenReturn("pear"); + try + { + pagin = findPaging(request); + fail("Should not get here."); + } + catch (InvalidArgumentException iae) + { + assertNotNull(iae); // Must throw this exceptions + } + + request = mock(WebScriptRequest.class); + when(request.getParameter("skipCount")).thenReturn("0"); + when(request.getParameter("maxItems")).thenReturn("0"); + try + { + pagin = findPaging(request); + fail("Should not get here."); + } + catch (InvalidArgumentException iae) + { + assertNotNull(iae); // Must throw this exceptions + } + + //Test Case cloud-2198 + request = mock(WebScriptRequest.class); + when(request.getParameter("skipCount")).thenReturn("0"); + when(request.getParameter("maxItems")).thenReturn("a"); + try + { + pagin = findPaging(request); + fail("Should not get here."); + } + catch (InvalidArgumentException iae) + { + assertNotNull(iae); // Must throw this exceptions + } + + request = mock(WebScriptRequest.class); + when(request.getParameter("skipCount")).thenReturn("s"); + when(request.getParameter("maxItems")).thenReturn("5"); + try + { + pagin = findPaging(request); + fail("Should not get here."); + } + catch (InvalidArgumentException iae) + { + assertNotNull(iae); // Must throw this exceptions + } + + request = mock(WebScriptRequest.class); + when(request.getParameter("skipCount")).thenReturn("0"); + when(request.getParameter("maxItems")).thenReturn("-2"); + try + { + pagin = findPaging(request); + fail("Should not get here."); + } + catch (InvalidArgumentException iae) + { + assertNotNull(iae); // Must throw this exceptions + } + + request = mock(WebScriptRequest.class); + when(request.getParameter("skipCount")).thenReturn("-3"); + when(request.getParameter("maxItems")).thenReturn("5"); + try + { + pagin = findPaging(request); + fail("Should not get here."); + } + catch (InvalidArgumentException iae) + { + assertNotNull(iae); // Must throw this exceptions + } + + request = mock(WebScriptRequest.class); + when(request.getParameter("maxItems")).thenReturn("5"); + pagin = findPaging(request); + assertNotNull(pagin); + assertTrue("skip count defaults to 0", pagin.getSkipCount() == Paging.DEFAULT_SKIP_COUNT); + + //End of Test Case cloud-2198 + } + + @Test + public void paramsTest() + { + Map> mockParams = new HashMap>(); + mockParams.put("age", Arrays.asList("23","45")); + mockParams.put("name", Arrays.asList("fred")); + WebScriptRequest request = mockRequest(mockParams); + Map params = getRequestParameters(request); + assertNotNull(params); + Params paramObj = ParamsExtender.valueOf(params); + assertNotNull(paramObj); + String aValue = paramObj.getParameter("age"); + assertEquals("23", aValue); + + aValue = paramObj.getParameter("name"); + assertEquals("fred", aValue); + + } + + private WebScriptRequest mockRequest(final Map> params) + { + final String[] paramNames = params.keySet().toArray(new String[]{}); + WebScriptRequest request = mock(WebScriptRequest.class); + when(request.getParameterNames()).thenReturn(paramNames); + when(request.getParameterValues(anyString())).thenAnswer(new Answer() { + @Override + public String[] answer(InvocationOnMock invocation) throws Throwable { + Object[] args = invocation.getArguments(); + return params.get((String) args[0]).toArray(new String[]{}); + } + }); + return request; + } + +} \ No newline at end of file diff --git a/source/test-java/org/alfresco/rest/test/workflow/api/impl/ProcessesImplTest.java b/source/test-java/org/alfresco/rest/test/workflow/api/impl/ProcessesImplTest.java index 91b72b5cb5..297ad37109 100644 --- a/source/test-java/org/alfresco/rest/test/workflow/api/impl/ProcessesImplTest.java +++ b/source/test-java/org/alfresco/rest/test/workflow/api/impl/ProcessesImplTest.java @@ -43,7 +43,7 @@ import org.alfresco.rest.framework.resource.parameters.Parameters; import org.alfresco.rest.framework.resource.parameters.Params; import org.alfresco.rest.framework.resource.parameters.Params.RecognizedParams; import org.alfresco.rest.framework.resource.parameters.where.Query; -import org.alfresco.rest.framework.webscripts.ResourceWebScriptHelper; +import org.alfresco.rest.framework.tools.RecognizedParamsExtractor; import org.alfresco.rest.workflow.api.Processes; import org.alfresco.rest.workflow.api.impl.ProcessesImpl; import org.alfresco.rest.workflow.api.model.ProcessInfo; @@ -67,7 +67,7 @@ import junit.framework.TestCase; * * @author Dmitry Velichkevich */ -public class ProcessesImplTest extends TestCase +public class ProcessesImplTest extends TestCase implements RecognizedParamsExtractor { private static final String[] CONFIG_LOCATIONS = new String[ApplicationContextHelper.CONFIG_LOCATIONS.length + 2]; static @@ -224,7 +224,7 @@ public class ProcessesImplTest extends TestCase private CollectionWithPagingInfo queryMatchesProcesses(String matchesString) { - Query query = ResourceWebScriptHelper.getWhereClause(String.format(QUERY_WORKFLOWDESCRIPTION_MATCHES, matchesString)); + Query query = getWhereClause(String.format(QUERY_WORKFLOWDESCRIPTION_MATCHES, matchesString)); Parameters parameters = Params.valueOf(new RecognizedParams(null, Paging.valueOf(0, ACTIVE_WORKFLOWS_INITIAL_AMOUNT), null, null, null, null, query, null, false), null, null, null); return processes.getProcesses(parameters); @@ -232,7 +232,7 @@ public class ProcessesImplTest extends TestCase private CollectionWithPagingInfo queryActiveProcessesAndAssertResult(int skipCount, int maxItems) { - Query query = ResourceWebScriptHelper.getWhereClause(QUERY_STATUS_ACTIVE); + Query query = getWhereClause(QUERY_STATUS_ACTIVE); Parameters parameters = Params.valueOf(new RecognizedParams(null, Paging.valueOf(skipCount, maxItems), null, null, null, null, query, null, false), null, null, null); CollectionWithPagingInfo result = processes.getProcesses(parameters);