Search in sources :

Example 1 with StreamingJsonWriter

use of org.structr.rest.serialization.StreamingJsonWriter in project structr by structr.

the class JsonRestServlet method doGetOrHead.

private void doGetOrHead(final HttpServletRequest request, final HttpServletResponse response, final boolean returnContent) throws ServletException, IOException {
    SecurityContext securityContext = null;
    Authenticator authenticator = null;
    Result result = null;
    Resource resource = null;
    try {
        // first thing to do!
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
        // isolate request authentication in a transaction
        try (final Tx tx = StructrApp.getInstance().tx()) {
            authenticator = config.getAuthenticator();
            securityContext = authenticator.initializeAndExamineRequest(request, response);
            tx.success();
        }
        final App app = StructrApp.getInstance(securityContext);
        // set default value for property view
        propertyView.set(securityContext, config.getDefaultPropertyView());
        // evaluate constraints and measure query time
        double queryTimeStart = System.nanoTime();
        // isolate resource authentication
        try (final Tx tx = app.tx()) {
            resource = ResourceHelper.applyViewTransformation(request, securityContext, ResourceHelper.optimizeNestedResourceChain(securityContext, request, resourceMap, propertyView), propertyView);
            authenticator.checkResourceAccess(securityContext, request, resource.getResourceSignature(), propertyView.get(securityContext));
            tx.success();
        }
        // add sorting & paging
        String pageSizeParameter = request.getParameter(REQUEST_PARAMETER_PAGE_SIZE);
        String pageParameter = request.getParameter(REQUEST_PARAMETER_PAGE_NUMBER);
        String sortOrder = request.getParameter(REQUEST_PARAMETER_SORT_ORDER);
        String sortKeyName = request.getParameter(REQUEST_PARAMETER_SORT_KEY);
        String outputDepth = request.getParameter(REQUEST_PARAMTER_OUTPUT_DEPTH);
        boolean sortDescending = (sortOrder != null && "desc".equals(sortOrder.toLowerCase()));
        int pageSize = Services.parseInt(pageSizeParameter, NodeFactory.DEFAULT_PAGE_SIZE);
        int page = Services.parseInt(pageParameter, NodeFactory.DEFAULT_PAGE);
        int depth = Services.parseInt(outputDepth, config.getOutputNestingDepth());
        String baseUrl = request.getRequestURI();
        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, false);
        }
        // isolate doGet
        boolean retry = true;
        while (retry) {
            try (final Tx tx = app.tx()) {
                result = resource.doGet(sortKey, sortDescending, pageSize, page);
                tx.success();
                retry = false;
            } catch (RetryException ddex) {
                retry = true;
            }
        }
        if (result == null) {
            throw new FrameworkException(HttpServletResponse.SC_SERVICE_UNAVAILABLE, "Unable to retrieve result, check database connection");
        }
        if (returnContent) {
            if (!(resource instanceof StaticRelationshipResource) && !result.isPrimitiveArray() && !result.isEmpty()) {
                result.setIsCollection(resource.isCollectionResource());
                result.setIsPrimitiveArray(resource.isPrimitiveArray());
            }
            PagingHelper.addPagingParameter(result, pageSize, page);
            // timing..
            double queryTimeEnd = System.nanoTime();
            // store property view that will be used to render the results
            result.setPropertyView(propertyView.get(securityContext));
            // allow resource to modify result set
            resource.postProcessResultSet(result);
            DecimalFormat decimalFormat = new DecimalFormat("0.000000000", DecimalFormatSymbols.getInstance(Locale.ENGLISH));
            result.setQueryTime(decimalFormat.format((queryTimeEnd - queryTimeStart) / 1000000000.0));
            if (outputDepth != null) {
                result.setOutputNestingDepth(depth);
            }
            String accept = request.getHeader("Accept");
            if (accept != null && accept.contains("text/html")) {
                final StreamingHtmlWriter htmlStreamer = new StreamingHtmlWriter(this.propertyView, indentJson, depth);
                // isolate write output
                try (final Tx tx = app.tx()) {
                    // no trailing semicolon so we dont trip MimeTypes.getContentTypeWithoutCharset
                    response.setContentType("text/html; charset=utf-8");
                    final Writer writer = response.getWriter();
                    htmlStreamer.stream(securityContext, writer, result, baseUrl);
                    // useful newline
                    writer.append("\n");
                    tx.success();
                }
            } else {
                final StreamingJsonWriter jsonStreamer = new StreamingJsonWriter(this.propertyView, indentJson, depth);
                // isolate write output
                try (final Tx tx = app.tx()) {
                    // no trailing semicolon so we dont trip MimeTypes.getContentTypeWithoutCharset
                    response.setContentType("application/json; charset=utf-8");
                    final Writer writer = response.getWriter();
                    jsonStreamer.stream(securityContext, writer, result, baseUrl);
                    // useful newline
                    writer.append("\n");
                    tx.success();
                }
            }
        }
        response.setStatus(HttpServletResponse.SC_OK);
    } catch (FrameworkException frameworkException) {
        // set status & write JSON output
        response.setStatus(frameworkException.getStatus());
        gson.get().toJson(frameworkException, response.getWriter());
        response.getWriter().println();
    } catch (JsonSyntaxException jsex) {
        logger.warn("JsonSyntaxException in GET", jsex);
        int code = HttpServletResponse.SC_BAD_REQUEST;
        response.setStatus(code);
        response.getWriter().append(RestMethodResult.jsonError(code, "Json syntax exception in GET: " + jsex.getMessage()));
    } catch (JsonParseException jpex) {
        logger.warn("JsonParseException in GET", jpex);
        int code = HttpServletResponse.SC_BAD_REQUEST;
        response.setStatus(code);
        response.getWriter().append(RestMethodResult.jsonError(code, "Parser exception in GET: " + jpex.getMessage()));
    } catch (Throwable t) {
        logger.warn("Exception in GET (URI: {})", securityContext != null ? securityContext.getCompoundRequestURI() : "(null SecurityContext)");
        logger.warn(" => Error thrown: ", t);
        int code = HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
        response.setStatus(code);
        response.getWriter().append(RestMethodResult.jsonError(code, "Exception in GET: " + t.getMessage()));
    } finally {
        try {
            // response.getWriter().flush();
            response.getWriter().close();
        } catch (Throwable t) {
            logger.warn("Unable to flush and close response: {}", t.getMessage());
        }
    }
}
Also used : App(org.structr.core.app.App) StructrApp(org.structr.core.app.StructrApp) Tx(org.structr.core.graph.Tx) FrameworkException(org.structr.common.error.FrameworkException) DecimalFormat(java.text.DecimalFormat) Resource(org.structr.rest.resource.Resource) StaticRelationshipResource(org.structr.rest.resource.StaticRelationshipResource) StaticRelationshipResource(org.structr.rest.resource.StaticRelationshipResource) StreamingHtmlWriter(org.structr.rest.serialization.StreamingHtmlWriter) RetryException(org.structr.api.RetryException) JsonParseException(com.google.gson.JsonParseException) Result(org.structr.core.Result) RestMethodResult(org.structr.rest.RestMethodResult) JsonSyntaxException(com.google.gson.JsonSyntaxException) StreamingJsonWriter(org.structr.rest.serialization.StreamingJsonWriter) SecurityContext(org.structr.common.SecurityContext) Authenticator(org.structr.core.auth.Authenticator) PropertyKey(org.structr.core.property.PropertyKey) Writer(java.io.Writer) StreamingHtmlWriter(org.structr.rest.serialization.StreamingHtmlWriter) StreamingJsonWriter(org.structr.rest.serialization.StreamingJsonWriter)

Example 2 with StreamingJsonWriter

use of org.structr.rest.serialization.StreamingJsonWriter in project structr by structr.

the class ToJsonFunction method apply.

@Override
public Object apply(final ActionContext ctx, final Object caller, final Object[] sources) {
    if (sources != null && sources.length >= 1 && sources.length <= 3) {
        try {
            final SecurityContext securityContext = ctx.getSecurityContext();
            final Value<String> view = new StaticValue<>("public");
            if (sources.length > 1) {
                view.set(securityContext, sources[1].toString());
            }
            int outputDepth = 3;
            if (sources.length > 2 && sources[2] instanceof Number) {
                outputDepth = ((Number) sources[2]).intValue();
            }
            final StreamingJsonWriter jsonStreamer = new StreamingJsonWriter(view, true, outputDepth);
            final StringWriter writer = new StringWriter();
            if (sources[0] instanceof GraphObject) {
                jsonStreamer.streamSingle(securityContext, writer, (GraphObject) sources[0]);
            } else if (sources[0] instanceof List) {
                final List list = (List) sources[0];
                jsonStreamer.stream(securityContext, writer, new Result(list, list.size(), true, false), null);
            } else if (sources[0] instanceof Map) {
                final GraphObjectMap map = new GraphObjectMap();
                this.recursivelyConvertMapToGraphObjectMap(map, (Map) sources[0], outputDepth);
                jsonStreamer.stream(securityContext, writer, new Result(map, false), null);
            }
            return writer.getBuffer().toString();
        } catch (Throwable t) {
            logException(caller, t, sources);
        }
        return "";
    } else {
        logParameterError(caller, sources, ctx.isJavaScriptContext());
    }
    return usage(ctx.isJavaScriptContext());
}
Also used : StaticValue(org.structr.core.StaticValue) GraphObject(org.structr.core.GraphObject) Result(org.structr.core.Result) StringWriter(java.io.StringWriter) StreamingJsonWriter(org.structr.rest.serialization.StreamingJsonWriter) GraphObjectMap(org.structr.core.GraphObjectMap) SecurityContext(org.structr.common.SecurityContext) List(java.util.List) Map(java.util.Map) GraphObjectMap(org.structr.core.GraphObjectMap)

Aggregations

SecurityContext (org.structr.common.SecurityContext)2 Result (org.structr.core.Result)2 StreamingJsonWriter (org.structr.rest.serialization.StreamingJsonWriter)2 JsonParseException (com.google.gson.JsonParseException)1 JsonSyntaxException (com.google.gson.JsonSyntaxException)1 StringWriter (java.io.StringWriter)1 Writer (java.io.Writer)1 DecimalFormat (java.text.DecimalFormat)1 List (java.util.List)1 Map (java.util.Map)1 RetryException (org.structr.api.RetryException)1 FrameworkException (org.structr.common.error.FrameworkException)1 GraphObject (org.structr.core.GraphObject)1 GraphObjectMap (org.structr.core.GraphObjectMap)1 StaticValue (org.structr.core.StaticValue)1 App (org.structr.core.app.App)1 StructrApp (org.structr.core.app.StructrApp)1 Authenticator (org.structr.core.auth.Authenticator)1 Tx (org.structr.core.graph.Tx)1 PropertyKey (org.structr.core.property.PropertyKey)1