Package com.ponysdk.core

Source Code of com.ponysdk.core.AbstractApplicationManager

package com.ponysdk.core;

import java.util.List;

import javax.servlet.ServletException;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ponysdk.core.main.EntryPoint;
import com.ponysdk.core.servlet.Request;
import com.ponysdk.core.servlet.Response;
import com.ponysdk.core.servlet.Session;
import com.ponysdk.core.stm.Txn;
import com.ponysdk.core.stm.TxnContextHttp;
import com.ponysdk.ui.server.basic.PCookies;
import com.ponysdk.ui.terminal.Dictionnary.APPLICATION;
import com.ponysdk.ui.terminal.Dictionnary.HISTORY;
import com.ponysdk.ui.terminal.Dictionnary.PROPERTY;
import com.ponysdk.ui.terminal.exception.ServerException;

public abstract class AbstractApplicationManager {

    private static final Logger log = LoggerFactory.getLogger(AbstractApplicationManager.class);

    private final ApplicationManagerOption options;

    public AbstractApplicationManager() {
        this(new ApplicationManagerOption());
    }

    public AbstractApplicationManager(final ApplicationManagerOption options) {
        this.options = options;
        log.info("ApplicationManagerOption: " + options);
    }

    public void process(final Request request, final Response response) throws Exception {
        final JSONObject data = new JSONObject(new JSONTokener(request.getReader()));
        if (data.has(APPLICATION.KEY)) {
            startApplication(data, request, response);
        } else {
            fireInstructions(data, request, response);
        }
    }

    public void startApplication(final JSONObject data, final Request request, final Response response) throws Exception {

        final Session session = request.getSession();

        synchronized (session) {
            Long reloadedViewID = null;
            boolean isNewHttpSession = false;
            Application application = (Application) session.getAttribute(Application.class.getCanonicalName());
            if (application == null) {
                log.info("Creating a new application ... Session ID #" + session.getId() + " - " + request.getHeader("User-Agent") + " - " + request.getRemoteAddr());
                final String applicationID = System.getProperty(SystemProperty.APPLICATION_ID);
                final String applicationName = System.getProperty(SystemProperty.APPLICATION_NAME);
                application = new Application(applicationID, applicationName, session, options);
                session.setUserAgent(request.getHeader("User-Agent"));
                session.setAttribute(Application.class.getCanonicalName(), application);
                isNewHttpSession = true;
            } else {
                if (data.has(APPLICATION.VIEW_ID)) reloadedViewID = data.getLong(APPLICATION.VIEW_ID);
                log.info("Reloading application " + reloadedViewID + " on session #" + session.getId());
            }

            final UIContext uiContext = new UIContext(application);
            UIContext.setCurrent(uiContext);

            if (reloadedViewID != null) {
                final UIContext previousUIContext = application.getUIContext(reloadedViewID);
                if (previousUIContext != null) previousUIContext.destroy();
            }

            try {
                final Txn txn = Txn.get();
                txn.begin(new TxnContextHttp(true, request, response));
                try {

                    final long receivedSeqNum = data.getLong(APPLICATION.SEQ_NUM);
                    uiContext.updateIncomingSeqNum(receivedSeqNum);

                    final EntryPoint entryPoint = initializePonySession(uiContext);

                    final String historyToken = data.getString(HISTORY.TOKEN);
                    if (historyToken != null && !historyToken.isEmpty()) uiContext.getHistory().newItem(historyToken, false);

                    final PCookies pCookies = uiContext.getCookies();
                    final JSONArray cookies = data.getJSONArray(PROPERTY.COOKIES);
                    for (int i = 0; i < cookies.length(); i++) {
                        final JSONObject jsoObject = cookies.getJSONObject(i);
                        final String name = jsoObject.getString(PROPERTY.KEY);
                        final String value = jsoObject.getString(PROPERTY.VALUE);
                        pCookies.cacheCookie(name, value);
                    }

                    if (isNewHttpSession) {
                        entryPoint.start(uiContext);
                    } else {
                        entryPoint.restart(uiContext);
                    }
                    txn.commit();
                } catch (final Throwable e) {
                    log.error("Cannot send instructions to the browser, Session ID #" + session.getId(), e);
                    txn.rollback();
                }
            } finally {
                UIContext.remove();
            }
        }
    }

    protected void fireInstructions(final JSONObject data, final Request request, final Response response) throws Exception {
        final long key = data.getLong(APPLICATION.VIEW_ID);
        final Session session = request.getSession();
        final Application applicationSession = (Application) session.getAttribute(Application.class.getCanonicalName());

        if (applicationSession == null) { throw new ServerException(ServerException.INVALID_SESSION, "Invalid session, please reload your application (viewID #" + key + ")."); }

        final UIContext uiContext = applicationSession.getUIContext(key);

        if (uiContext == null) { throw new ServerException(ServerException.INVALID_SESSION, "Invalid session (no UIContext found), please reload your application (viewID #" + key + ")."); }

        uiContext.acquire();
        UIContext.setCurrent(uiContext);
        try {
            final Txn txn = Txn.get();
            txn.begin(new TxnContextHttp(false, request, response));
            try {
                final Long receivedSeqNum = checkClientMessage(request.getSession(), data, uiContext);

                if (receivedSeqNum != null) {
                    process(uiContext, data);

                    final List<JSONObject> datas = uiContext.expungeIncomingMessageQueue(receivedSeqNum);
                    for (final JSONObject jsoObject : datas) {
                        process(uiContext, jsoObject);
                    }
                }

                txn.commit();
            } catch (final Throwable e) {
                log.error("Cannot process client instruction", e);
                txn.rollback();
            }
        } finally {
            UIContext.remove();
            uiContext.release();
        }
    }

    private Long checkClientMessage(final Session session, final JSONObject data, final UIContext uiContext) throws JSONException {
        printClientErrorMessage(data);

        final long receivedSeqNum = data.getLong(APPLICATION.SEQ_NUM);
        if (!uiContext.updateIncomingSeqNum(receivedSeqNum)) {
            final long key = data.getLong(APPLICATION.VIEW_ID);
            uiContext.stackIncomingMessage(receivedSeqNum, data);
            if (options.maxOutOfSyncDuration > 0 && uiContext.getLastSyncErrorTimestamp() > 0) {
                if (System.currentTimeMillis() - uiContext.getLastSyncErrorTimestamp() > options.maxOutOfSyncDuration) {
                    log.info("Unable to sync message for " + (System.currentTimeMillis() - uiContext.getLastSyncErrorTimestamp()) + " ms. Dropping connection (viewID #" + key + ").");
                    uiContext.destroy();
                    return null;
                }
            }
            log.info("Stacking incoming message #" + receivedSeqNum + ". Data #" + data + " (viewID #" + key + ")");
            return null;
        }
        return receivedSeqNum;

    }

    private void printClientErrorMessage(final JSONObject data) {
        try {
            final JSONArray errors = data.getJSONArray(APPLICATION.ERRORS);
            for (int i = 0; i < errors.length(); i++) {
                final JSONObject jsoObject = errors.getJSONObject(i);
                final String message = jsoObject.getString("message");
                final String details = jsoObject.getString("details");
                log.error("There was an unexpected error on the terminal. Message: " + message + ". Details: " + details);
            }
        } catch (final Throwable e) {
            log.error("Failed to display errors", e);
        }
    }

    private void process(final UIContext uiContext, final JSONObject jsoObject) throws JSONException {
        if (jsoObject.has(APPLICATION.INSTRUCTIONS)) {
            final JSONArray instructions = jsoObject.getJSONArray(APPLICATION.INSTRUCTIONS);
            for (int i = 0; i < instructions.length(); i++) {
                JSONObject jsonObject = null;
                try {
                    jsonObject = instructions.getJSONObject(i);
                    uiContext.fireClientData(jsonObject);
                } catch (final Throwable e) {
                    log.error("Failed to process instruction: " + jsonObject, e);
                }
            }
        }
    }

    protected abstract EntryPoint initializePonySession(final UIContext ponySession) throws ServletException;

}
TOP

Related Classes of com.ponysdk.core.AbstractApplicationManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.