All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.fujion.websocket.Session Maven / Gradle / Ivy

There is a newer version: 3.1.0
Show newest version
/*
 * #%L
 * fujion
 * %%
 * Copyright (C) 2008 - 2017 Regenstrief Institute, Inc.
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * #L%
 */
package org.fujion.websocket;

import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;

import javax.servlet.ServletContext;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.fujion.client.ClientInvocation;
import org.fujion.client.ClientRequest;
import org.fujion.client.Synchronizer;
import org.fujion.component.Page;
import org.fujion.page.PageRegistry;
import org.springframework.web.socket.WebSocketSession;

/**
 * Container for core resources for a single client session (i.e., web socket connection).
 */
public class Session {
    
    private static final Log log = LogFactory.getLog(Session.class);
    
    public static final String ATTR_SESSION = "fujion_session";
    
    private enum EventType {
        DESTROY, REQUEST, INVOCATION
    }
    
    private final ServletContext servletContext;
    
    private final WebSocketSession socket;
    
    private final Synchronizer synchronizer;
    
    private Set sessionListeners;

    private final long creationTime;
    
    private long lastActivity;
    
    private Page page;
    
    /**
     * Create a session, with references to its servlet context and web socket.
     *
     * @param servletContext The servlet context.
     * @param socket The web socket.
     */
    protected Session(ServletContext servletContext, WebSocketSession socket) {
        this.servletContext = servletContext;
        this.socket = socket;
        socket.getAttributes().put(ATTR_SESSION, this);
        this.synchronizer = new Synchronizer(socket);
        creationTime = System.currentTimeMillis();
        lastActivity = creationTime;
    }
    
    /**
     * Destroy the session. This destroys the associated page.
     */
    protected void destroy() {
        if (page != null) {
            try {
                synchronizer.startQueueing();
                page.destroy();
                socket.getAttributes().remove(ATTR_SESSION);
            } finally {
                page = null;
            }
        }
        
        notifySessionListeners(EventType.DESTROY, null);
    }
    
    /**
     * Returns the session's id, which is the same as the underlying web socket id.
     *
     * @return The session's id.
     */
    public String getId() {
        return socket.getId();
    }
    
    /**
     * Returns the session's time of creation.
     *
     * @return The session's time of creation.
     */
    public long getCreationTime() {
        return creationTime;
    }
    
    /**
     * Returns the time of last activity for the session.
     *
     * @return The time of last activity.
     */
    public long getLastActivity() {
        return lastActivity;
    }
    
    /**
     * Updates the session's last activity.
     */
    public void updateLastActivity() {
        this.lastActivity = System.currentTimeMillis();
    }
    
    /**
     * Returns the servlet context associated with the session.
     *
     * @return The servlet context.
     */
    public ServletContext getServletContext() {
        return servletContext;
    }
    
    /**
     * Returns the web socket associated with the session.
     *
     * @return The web socket.
     */
    public WebSocketSession getSocket() {
        return socket;
    }
    
    /**
     * Returns the synchronizer associated with the session.
     *
     * @return The synchronizer.
     */
    public Synchronizer getSynchronizer() {
        return synchronizer;
    }
    
    /**
     * Returns the page associated with the session.
     *
     * @return The page.
     */
    public Page getPage() {
        return page;
    }
    
    /**
     * Returns the attribute map associated with the session. This is a convenience method for
     * accessing the attribute map of the underlying web socket session.
     *
     * @return The attribute map.
     */
    public Map getAttributes() {
        return socket.getAttributes();
    }
    
    /**
     * Register a session listener.
     *
     * @param listener Session listener to register.
     * @return True if the operation was successful.
     */
    public boolean addSessionListener(ISessionListener listener) {
        if (sessionListeners == null) {
            sessionListeners = new LinkedHashSet<>();
        }

        return sessionListeners.add(listener);
    }

    /**
     * Unregister a session listener.
     *
     * @param listener Session listener to unregister.
     * @return True if the operation was successful.
     */
    public boolean removeSessionListener(ISessionListener listener) {
        return sessionListeners != null && sessionListeners.remove(listener);
    }

    /**
     * Notify all session listeners of a client request event.
     *
     * @param request The client request.
     */
    protected void notifySessionListeners(ClientRequest request) {
        notifySessionListeners(EventType.REQUEST, request);
    }
    
    /**
     * Notify all session listeners of a client invocation event.
     *
     * @param invocation The client invocation.
     */
    protected void notifySessionListeners(ClientInvocation invocation) {
        notifySessionListeners(EventType.INVOCATION, invocation);
    }
    
    /**
     * Notify all session listeners of an event.
     *
     * @param event The type of session event.
     * @param argument Event arguments (specific to event type).
     */
    private void notifySessionListeners(EventType event, Object argument) {
        if (sessionListeners != null) {
            for (ISessionListener sessionListener : sessionListeners) {
                try {
                    switch (event) {
                        case DESTROY:
                            sessionListener.onDestroy();
                            break;
                        
                        case REQUEST:
                            sessionListener.onClientRequest((ClientRequest) argument);
                            break;
                        
                        case INVOCATION:
                            sessionListener.onClientInvocation((ClientInvocation) argument);
                            break;
                    }
                } catch (Exception e) {
                    log.error("A session listener threw an exception", e);
                }
            }
        }
    }
    
    /**
     * Send a ping to the client.
     *
     * @param data Data to send with the ping.
     */
    public void ping(String data) {
        WebSocketHandler.send(socket, new ClientInvocation((String) null, "fujion.ws.ping", data));
    }
    
    /**
     * Initialize the session. If already initialized, this only validates that the page id matches
     * that of the associated page. Otherwise, it associates the session with the page specified by
     * the page id.
     *
     * @param pageId The page id.
     * @return True if initialization took place.
     */
    protected boolean _init(String pageId) {
        if (page != null) {
            if (!page.getId().equals(pageId)) {
                throw new RuntimeException("Page ids do not match");
            }
            
            return false;
        } else {
            page = PageRegistry.getPage(pageId);
            
            if (page == null) {
                throw new RuntimeException("Unknown page id");
            }
            
            return true;
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy