org.fejoa.server.Portal.java Source code

Java tutorial

Introduction

Here is the source code for org.fejoa.server.Portal.java

Source

/*
 * Copyright 2015.
 * Distributed under the terms of the GPLv3 License.
 *
 * Authors:
 *      Clemens Zeidler <czei002@aucklanduni.ac.nz>
 */
package org.fejoa.server;

import org.apache.http.HttpEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.fejoa.library.remote.Errors;
import org.fejoa.library.remote.HTMLRequest;
import org.fejoa.library.remote.JsonRPCHandler;
import org.fejoa.library.support.StreamHelper;

import javax.servlet.MultipartConfigElement;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import java.io.*;
import java.util.ArrayList;
import java.util.List;

public class Portal extends AbstractHandler {
    public class ResponseHandler {
        final private HttpServletResponse response;
        private boolean handled = false;
        final private MultipartEntityBuilder builder = MultipartEntityBuilder.create();
        // TODO don't buffer the output data but send it directly!
        private ByteArrayOutputStream outputStream;

        public ResponseHandler(HttpServletResponse response) {
            this.response = response;
            builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
        }

        public boolean isHandled() {
            return handled;
        }

        public void setResponseHeader(String header) {
            handled = true;
            builder.addTextBody(HTMLRequest.MESSAGE_KEY, header, ContentType.DEFAULT_TEXT);
        }

        public OutputStream addData() {
            if (!handled)
                return null;
            if (outputStream == null)
                outputStream = new ByteArrayOutputStream();
            return outputStream;
        }

        public void finish() throws IOException {
            if (outputStream != null) {
                builder.addBinaryBody(HTMLRequest.DATA_KEY, new ByteArrayInputStream(outputStream.toByteArray()),
                        ContentType.DEFAULT_BINARY, HTMLRequest.DATA_FILE);
            }
            HttpEntity entity = builder.build();
            response.getOutputStream().write(entity.getContentType().toString().getBytes());
            response.getOutputStream().write('\n');
            entity.writeTo(response.getOutputStream());
        }
    }

    final private String baseDir;
    final private List<JsonRequestHandler> jsonHandlers = new ArrayList<>();

    private void addJsonHandler(JsonRequestHandler handler) {
        jsonHandlers.add(handler);
    }

    public Portal(String baseDir) {
        this.baseDir = baseDir;

        addJsonHandler(new JsonPingHandler());
        addJsonHandler(new WatchHandler());
        addJsonHandler(new ChunkStoreRequestHandler());
        addJsonHandler(new CreateAccountHandler());
        addJsonHandler(new LoginRequestHandler());
        addJsonHandler(new CommandHandler());
        addJsonHandler(new AccessRequestHandler());
        addJsonHandler(new StartMigrationHandler());
        addJsonHandler(new RemotePullHandler());
    }

    @Override
    public void handle(String s, Request request, HttpServletRequest httpServletRequest,
            HttpServletResponse response) throws IOException, ServletException {
        response.setContentType("text/plain;charset=utf-8");
        response.setStatus(HttpServletResponse.SC_OK);
        request.setHandled(true);

        final MultipartConfigElement MULTI_PART_CONFIG = new MultipartConfigElement(
                System.getProperty("java.io.tmpdir"));
        if (request.getContentType() != null && request.getContentType().startsWith("multipart/form-data")) {
            request.setAttribute(Request.__MULTIPART_CONFIG_ELEMENT, MULTI_PART_CONFIG);
        }

        Session session = new Session(baseDir, httpServletRequest.getSession());
        ResponseHandler responseHandler = new ResponseHandler(response);

        Part messagePart = request.getPart(HTMLRequest.MESSAGE_KEY);
        Part data = request.getPart(HTMLRequest.DATA_KEY);

        if (messagePart == null) {
            responseHandler.setResponseHeader("empty request!");
            responseHandler.finish();
            return;
        }

        StringWriter stringWriter = new StringWriter();
        StreamHelper.copy(messagePart.getInputStream(), stringWriter);

        String error = handleJson(responseHandler, stringWriter.toString(),
                (data != null) ? data.getInputStream() : null, session);

        if (!responseHandler.isHandled() || error != null)
            responseHandler.setResponseHeader(error);

        responseHandler.finish();
    }

    private String handleJson(ResponseHandler responseHandler, String message, InputStream data, Session session) {
        JsonRPCHandler jsonRPCHandler;
        try {
            jsonRPCHandler = new JsonRPCHandler(message);
        } catch (Exception e) {
            e.printStackTrace();
            return JsonRPCHandler.makeResult(-1, Errors.INVALID_JSON_REQUEST, "can't parse json");
        }

        String method = jsonRPCHandler.getMethod();
        for (JsonRequestHandler handler : jsonHandlers) {
            if (!handler.getMethod().equals(method))
                continue;

            try {
                handler.handle(responseHandler, jsonRPCHandler, data, session);
            } catch (Exception e) {
                e.printStackTrace();
                return jsonRPCHandler.makeResult(Errors.EXCEPTION, e.getMessage());
            }
            if (responseHandler.isHandled())
                return null;
        }

        return jsonRPCHandler.makeResult(Errors.NO_HANDLER_FOR_REQUEST, "can't handle request");
    }
}