public Object evaluate( final GraphObject entity, final String key, final Object data, final String defaultValue, final int depth) throws FrameworkException { Object value = constants.get(key); if (value == null) { // special HttpServletRequest handling if (data instanceof HttpServletRequest) { value = ((HttpServletRequest) data).getParameter(key); } // special handling of maps.. if (data instanceof Map) { value = ((Map) data).get(key); } if (data != null) { if (data instanceof GraphObject) { value = ((GraphObject) data).evaluate(securityContext, key, defaultValue); } else { switch (key) { case "size": if (data instanceof Collection) { return ((Collection) data).size(); } if (data.getClass().isArray()) { return ((Object[]) data).length; } break; } } } else { // "data-less" keywords to start the evaluation chain switch (key) { case "request": return securityContext.getRequest(); case "host": return securityContext.getRequest().getServerName(); case "port": return securityContext.getRequest().getServerPort(); case "pathInfo": case "path_info": return securityContext.getRequest().getPathInfo(); case "parameterMap": case "parameter_map": return securityContext.getRequest().getParameterMap(); case "remoteAddress": case "remote_address": final String remoteAddress = securityContext.getRequest().getHeader("X-FORWARDED-FOR"); if (remoteAddress == null) { return securityContext.getRequest().getRemoteAddr(); } return remoteAddress; case "response": if (securityContext != null) { final HttpServletResponse response = securityContext.getResponse(); if (response != null) { try { // return output stream of HTTP response for streaming return response.getOutputStream(); } catch (IOException ioex) { logger.warn("", ioex); } } } return null; case "now": return DatePropertyParser.format(new Date(), DateProperty.DEFAULT_FORMAT); case "me": return securityContext.getUser(false); case "element": logger.warn( "The \"element\" keyword is deprecated! Please use \"this\" instead. Used in {}", entity.getProperty(GraphObject.id)); case "this": return entity; case "locale": return locale != null ? locale.toString() : null; } } } if (value == null && defaultValue != null) { return Function.numberOrString(defaultValue); } return value; }
@Override public List<GraphObject> getData( final SecurityContext securityContext, final RenderContext renderContext, final String restQuery) throws FrameworkException { Map<Pattern, Class<? extends Resource>> resourceMap = new LinkedHashMap<>(); ResourceProvider resourceProvider = renderContext == null ? null : renderContext.getResourceProvider(); if (resourceProvider == null) { try { resourceProvider = UiResourceProvider.class.newInstance(); } catch (Throwable t) { logger.log(Level.SEVERE, "Couldn't establish a resource provider", t); return Collections.EMPTY_LIST; } } // inject resources resourceMap.putAll(resourceProvider.getResources()); Value<String> propertyView = new ThreadLocalPropertyView(); propertyView.set(securityContext, PropertyView.Ui); // initialize variables // mimic HTTP request HttpServletRequest request = new HttpServletRequestWrapper( renderContext == null ? securityContext.getRequest() : renderContext.getRequest()) { @Override public Enumeration<String> getParameterNames() { return new IteratorEnumeration(getParameterMap().keySet().iterator()); } @Override public String getParameter(String key) { String[] p = getParameterMap().get(key); return p != null ? p[0] : null; } @Override public Map<String, String[]> getParameterMap() { String[] parts = StringUtils.split(getQueryString(), "&"); Map<String, String[]> parameterMap = new HashMap(); for (String p : parts) { String[] kv = StringUtils.split(p, "="); if (kv.length > 1) { parameterMap.put(kv[0], new String[] {kv[1]}); } } return parameterMap; } @Override public String getQueryString() { return StringUtils.substringAfter(restQuery, "?"); } @Override public String getPathInfo() { return StringUtils.substringBefore(restQuery, "?"); } @Override public StringBuffer getRequestURL() { return new StringBuffer(restQuery); } }; // update request in security context securityContext.setRequest(request); // HttpServletResponse response = renderContext.getResponse(); Resource resource = ResourceHelper.applyViewTransformation( request, securityContext, ResourceHelper.optimizeNestedResourceChain( ResourceHelper.parsePath( securityContext, request, resourceMap, propertyView, GraphObject.id), GraphObject.id), propertyView); // TODO: decide if we need to rest the REST request here // securityContext.checkResourceAccess(request, resource.getResourceSignature(), // resource.getGrant(request, response), PropertyView.Ui); // add sorting & paging String pageSizeParameter = request.getParameter(JsonRestServlet.REQUEST_PARAMETER_PAGE_SIZE); String pageParameter = request.getParameter(JsonRestServlet.REQUEST_PARAMETER_PAGE_NUMBER); String offsetId = request.getParameter(JsonRestServlet.REQUEST_PARAMETER_OFFSET_ID); String sortOrder = request.getParameter(JsonRestServlet.REQUEST_PARAMETER_SORT_ORDER); String sortKeyName = request.getParameter(JsonRestServlet.REQUEST_PARAMETER_SORT_KEY); boolean sortDescending = (sortOrder != null && "desc".equals(sortOrder.toLowerCase())); int pageSize = parseInt(pageSizeParameter, NodeFactory.DEFAULT_PAGE_SIZE); int page = parseInt(pageParameter, NodeFactory.DEFAULT_PAGE); PropertyKey sortKey = null; // set sort key if (sortKeyName != null) { Class<? extends GraphObject> type = resource.getEntityClass(); if (type == null) { // fallback to default implementation // if no type can be determined type = AbstractNode.class; } sortKey = StructrApp.getConfiguration().getPropertyKeyForDatabaseName(type, sortKeyName); } // do action Result result = resource.doGet(sortKey, sortDescending, pageSize, page, offsetId); result.setIsCollection(resource.isCollectionResource()); result.setIsPrimitiveArray(resource.isPrimitiveArray()); // Integer rawResultCount = (Integer) Services.getAttribute(NodeFactory.RAW_RESULT_COUNT + // Thread.currentThread().getId()); PagingHelper.addPagingParameter(result, pageSize, page); List<GraphObject> res = result.getResults(); if (renderContext != null) { renderContext.setResult(result); } return res != null ? res : Collections.EMPTY_LIST; }