Search in sources :

Example 1 with AbstractCommand

use of org.structr.websocket.command.AbstractCommand in project structr by structr.

the class StructrWebSocket method onWebSocketText.

@Override
public void onWebSocketText(final String data) {
    if (!Services.getInstance().isInitialized()) {
        // send 401 Authentication Required
        send(MessageBuilder.status().code(503).message("System is not initialized yet").build(), true);
    }
    final Services servicesInstance = Services.getInstance();
    // wait for service layer to be initialized
    while (!servicesInstance.isInitialized()) {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException iex) {
        }
    }
    if (data == null) {
        logger.warn("Empty text message received.");
        return;
    }
    logger.debug("############################################################ RECEIVED \n{}", data.substring(0, Math.min(data.length(), 1000)));
    // parse web socket data from JSON
    final WebSocketMessage webSocketData = gson.fromJson(data, WebSocketMessage.class);
    final App app = StructrApp.getInstance(securityContext);
    final String command = webSocketData.getCommand();
    final Class type = commandSet.get(command);
    final String sessionIdFromMessage = webSocketData.getSessionId();
    if (type != null) {
        try (final Tx tx = app.tx()) {
            if (sessionIdFromMessage != null) {
                // try to authenticated this connection by sessionId
                authenticate(SessionHelper.getShortSessionId(sessionIdFromMessage), command.equals("PING"));
            }
            // we only permit LOGIN commands if authentication based on sessionId was not successful
            if (!isAuthenticated() && !type.equals(LoginCommand.class)) {
                // send 401 Authentication Required
                send(MessageBuilder.status().code(401).message("").build(), true);
                tx.success();
                return;
            }
            tx.success();
        } catch (DatabaseServiceNotAvailableException dbsnae) {
            logger.warn(dbsnae.getMessage());
        } catch (FrameworkException t) {
            logger.warn("Unable to parse message.", t);
        }
        // process message
        try {
            AbstractCommand abstractCommand = (AbstractCommand) type.newInstance();
            abstractCommand.setWebSocket(this);
            abstractCommand.setSession(session);
            abstractCommand.setCallback(webSocketData.getCallback());
            if (!(abstractCommand instanceof PingCommand)) {
                if (securityContext != null) {
                    final HttpSession session = SessionHelper.getSessionBySessionId(securityContext.getSessionId());
                    if (session != null) {
                        session.setMaxInactiveInterval(Services.getGlobalSessionTimeout());
                        try {
                            // Workaround to update lastAccessedTime() in Jetty's session via reflection
                            final Method accessMethod = ((org.eclipse.jetty.server.session.Session) session).getClass().getDeclaredMethod("access", long.class);
                            accessMethod.setAccessible(true);
                            accessMethod.invoke((org.eclipse.jetty.server.session.Session) session, System.currentTimeMillis());
                        } catch (Exception ex) {
                            logger.error("Access to method Session.access() via reflection failed: ", ex);
                        }
                    }
                }
            }
            // transactions in case of bulk processing commands etc.
            if (abstractCommand.requiresEnclosingTransaction()) {
                try (final Tx tx = app.tx()) {
                    // store authenticated-Flag in webSocketData
                    // so the command can access it
                    webSocketData.setSessionValid(isAuthenticated());
                    abstractCommand.processMessage(webSocketData);
                    // commit transaction
                    tx.success();
                }
            } else {
                try (final Tx tx = app.tx()) {
                    // store authenticated-Flag in webSocketData
                    // so the command can access it
                    webSocketData.setSessionValid(isAuthenticated());
                    // commit transaction
                    tx.success();
                }
                // process message without transaction context!
                abstractCommand.processMessage(webSocketData);
            }
        } catch (FrameworkException | InstantiationException | IllegalAccessException t) {
            try (final Tx tx = app.tx()) {
                // send 400 Bad Request
                if (t instanceof FrameworkException) {
                    final FrameworkException fex = (FrameworkException) t;
                    send(MessageBuilder.status().code(fex.getStatus()).message(fex.toString()).jsonErrorObject(fex.toJSON()).callback(webSocketData.getCallback()).build(), true);
                } else {
                    send(MessageBuilder.status().code(400).message(t.toString()).build(), true);
                }
                // commit transaction
                tx.success();
            } catch (FrameworkException fex) {
                logger.warn("Unable to send websocket result: {}", fex.getMessage());
            }
            return;
        }
    } else {
        logger.warn("Unknown command {}", command);
        // send 400 Bad Request
        send(MessageBuilder.status().code(400).message("Unknown command").build(), true);
        return;
    }
}
Also used : StructrApp(org.structr.core.app.StructrApp) App(org.structr.core.app.App) Tx(org.structr.core.graph.Tx) FrameworkException(org.structr.common.error.FrameworkException) HttpSession(javax.servlet.http.HttpSession) AbstractCommand(org.structr.websocket.command.AbstractCommand) DatabaseServiceNotAvailableException(org.structr.common.error.DatabaseServiceNotAvailableException) Method(java.lang.reflect.Method) FrameworkException(org.structr.common.error.FrameworkException) DatabaseServiceNotAvailableException(org.structr.common.error.DatabaseServiceNotAvailableException) IOException(java.io.IOException) PingCommand(org.structr.websocket.command.PingCommand) Services(org.structr.core.Services) WebSocketMessage(org.structr.websocket.message.WebSocketMessage)

Example 2 with AbstractCommand

use of org.structr.websocket.command.AbstractCommand in project structr by structr.

the class StructrWebSocket method addCommand.

public static void addCommand(final Class command) {
    try {
        final AbstractCommand msg = (AbstractCommand) command.newInstance();
        commandSet.put(msg.getCommand(), command);
    } catch (Throwable t) {
        logger.error("Unable to add command {}", command.getName());
    }
}
Also used : AbstractCommand(org.structr.websocket.command.AbstractCommand)

Aggregations

AbstractCommand (org.structr.websocket.command.AbstractCommand)2 IOException (java.io.IOException)1 Method (java.lang.reflect.Method)1 HttpSession (javax.servlet.http.HttpSession)1 DatabaseServiceNotAvailableException (org.structr.common.error.DatabaseServiceNotAvailableException)1 FrameworkException (org.structr.common.error.FrameworkException)1 Services (org.structr.core.Services)1 App (org.structr.core.app.App)1 StructrApp (org.structr.core.app.StructrApp)1 Tx (org.structr.core.graph.Tx)1 PingCommand (org.structr.websocket.command.PingCommand)1 WebSocketMessage (org.structr.websocket.message.WebSocketMessage)1