
pl.bristleback.server.bristle.BristlebackServerPlugin Maven / Gradle / Ivy
// Bristleback plugin - Copyright (c) 2010 bristleback.googlecode.com
// ---------------------------------------------------------------------------
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published by the
// Free Software Foundation; either version 3 of the License, or (at your
// option) any later version.
// This library is distributed in the hope that it will be useful,
// but without any warranty; without even the implied warranty of merchantability
// or fitness for a particular purpose.
// You should have received a copy of the GNU Lesser General Public License along
// with this program; if not, see .
// ---------------------------------------------------------------------------
package pl.bristleback.server.bristle;
import org.apache.log4j.Logger;
import org.jwebsocket.api.PluginConfiguration;
import org.jwebsocket.api.WebSocketConnector;
import org.jwebsocket.api.WebSocketEngine;
import org.jwebsocket.api.WebSocketServer;
import org.jwebsocket.kit.CloseReason;
import org.jwebsocket.kit.PlugInResponse;
import org.jwebsocket.plugins.TokenPlugIn;
import org.jwebsocket.token.Token;
import org.jwebsocket.token.TokenFactory;
import pl.bristleback.server.bristle.actions.ActionsDispatcher;
import pl.bristleback.server.bristle.actions.ActionsInitializer;
import pl.bristleback.server.bristle.actions.ReservedActionName;
import pl.bristleback.server.bristle.config.BristleConstants;
import pl.bristleback.server.bristle.config.ExceptionHandlersInitializer;
import pl.bristleback.server.bristle.messages.MessageController;
import pl.bristleback.server.bristle.rights.ConnectorRightsUtil;
import pl.bristleback.server.bristle.states.ServerStateInspector;
/**
* Bristleback Server plugin (also called Bristle plugin) is a helpful framework overlay,
* which simplifies process of creating applications using jWebsocket library.
* Bristleback plugin consists of five main elements:
*
* -
* Remote actions.
* Remote actions are used to declare response for user actions. They consists of name, required user rights and action response.
* Adding new action is very easy because of annotation usage.
* Actions are closely integrated with connector rights, which are described below.
* In addition, any exceptions while dispatching actions can be caught by implementing
* {@link pl.bristleback.server.bristle.exceptions.handlers.ExceptionHandler} interface.
*
* -
* Message senders and message dispatcher
* Senders and dispatchers provide way for sending messages to client in easy and thread safe way.
* Senders allow avoiding low level mechanisms of jwebsocket.
*
* -
* Connector rights
* After connector is connected, plugin creates empty rights set desired for that connector.
* Connector rights are used to determine whether connector can execute action.
* Rights using can be extended, eg. in sending messages.
*
* -
* Client side of Bristleback plugin
* Client side plugin provides the same action dispatching mechanism as on server side.
*
* -
* Spring Framework integration
* Spring Framework is used in thousands of projects. Bristle plugin provides a simple annotation,
* which can be used in action classes to inject dependencies. Furthermore,
* most classes loaded via configuration file, like message senders or server state listeners, may be Spring beans.
* Still, the target is to make available for every element to be a Spring bean.
* Check the documentation of Bristleback Plugin elements to see how can you make use of Spring beans.
*
*
*
* If you need to perform some operations before server is up or after server is down,
* you might be interested in using server state listeners chain. The only thing to do is to add your own
* {@link pl.bristleback.server.bristle.states.ServerStateListener} implementation.
* You can add as many {@link pl.bristleback.server.bristle.states.ServerStateListener} as you want.
*
* Almost every element of plugin is configurable, user can specify how actions or message will be looked.
* Yet, default implementation of those elements allow user to create "Hello world" application in just five minutes.
* Plugin settings in jwebsocket.xml file are used to configure Bristle plugin.
* Please note that this is early version of plugin, so nothing is tested as good as we would like it to be.
*
* {@link pl.bristleback.server.bristle.config.BristleConstants} class
* has fields which can be helpful in creating your first application.
*
* Current version of Bristle plugin contains two default message senders and one message dispatcher.
* To make use of message senders, users must add them into their jwebsocket configuration file.
* Example configuration is shown in this project, in "xml/jwebsocket.xml" file.
* Additional "How to make your first jWebsocket application with Bristleback plugin" web page can be found HERE.
* Created on: 2010-09-03 16:01:30
*
* @author Wojciech Niemiec
* @version 0.0.1
*/
public class BristlebackServerPlugin extends TokenPlugIn {
private static Logger log = Logger.getLogger(BristlebackServerPlugin.class.getName());
private ActionsDispatcher actionsDispatcher;
private MessageController messageController;
private ServerStateInspector serverStateInspector;
/**
* Creates a new Bristleback plugin instance and instantiating core elements of plugin.
*/
public BristlebackServerPlugin() {
setCoreElements();
}
/**
* Constructor required by TokenPlugIn class.
*
* @param configuration plugin configuration.
*/
public BristlebackServerPlugin(PluginConfiguration configuration) {
super(configuration);
setCoreElements();
}
private void setCoreElements() {
actionsDispatcher = new ActionsDispatcher();
messageController = new MessageController();
serverStateInspector = new ServerStateInspector();
}
/**
* Loading of all core elements from configuration and annotations.
* Firstly, plugin loads actions and exception handlers.
* Next step is to load message controller (dispatcher and senders) and to export senders.
* After that, server state inspector is loaded and invokes server state listeners chain.
* As soon as every element is ready, message controller starts dispatching messages to connectors.
*
* @param engine websocket engine.
*/
public void engineStarted(WebSocketEngine engine) {
WebSocketServer server = getServer();
loadActions();
loadExceptionsHandlers();
loadMessageHandler(server);
notifyServerStateInspector();
messageController.startDispatcher();
}
private void loadActions() {
ActionsInitializer actionsInitializer = new ActionsInitializer();
actionsInitializer.loadActionsContainer(getSettings());
actionsInitializer.injectActionsDependencies();
actionsDispatcher.setContainer(actionsInitializer.getContainer());
}
private void loadExceptionsHandlers() {
ExceptionHandlersInitializer exceptionHandlersInitializer = new ExceptionHandlersInitializer();
exceptionHandlersInitializer.loadExceptionsHandlers(getSettings());
actionsDispatcher.setExceptionHandlersContainer(exceptionHandlersInitializer.getExceptionHandlersContainer());
}
private void loadMessageHandler(WebSocketServer server) {
messageController.loadMessageContainer(getSettings());
messageController.assignServer(server);
messageController.exportSenders();
}
private void notifyServerStateInspector() {
serverStateInspector.loadServerStateListeners(getSettings());
serverStateInspector.serverStart();
}
/**
* In this method closing operations are performed. Dispatcher is stopped,
* server state inspector is notified about server shutdown.
*
* @param engine websocket engine.
*/
public void engineStopped(WebSocketEngine engine) {
messageController.stopDispatcher();
serverStateInspector.serverShutdown();
//todo-wojtek - free resources [unbind actions, message senders, etc]
}
/**
* When connector is started, new empty rights set is created and assigned to that connector.
* Moreover, it's possible to have a special action class with reserved name
* {@link pl.bristleback.server.bristle.actions.ReservedActionName#CONNECTION_STARTED_ACTION_NAME}.
*
* @param connector websocket connector.
*/
public void connectorStarted(WebSocketConnector connector) {
ConnectorRightsUtil.createRightsSetForConnector(connector);
Token token = TokenFactory.createToken();
actionsDispatcher.performReservedAction(connector, ReservedActionName.CONNECTION_STARTED_ACTION_NAME, token);
}
/**
* Additional operations performed when connector is stopped.
* It's possible to have a special action class with reserved name
* {@link pl.bristleback.server.bristle.actions.ReservedActionName#CONNECTION_STOPPED_ACTION_NAME}.
* Reason of closed connection is given in variable named {@code closeReason}.
*
* @param connector websocket connector.
* @param closeReason connection close reason.
*/
public void connectorStopped(WebSocketConnector connector, CloseReason closeReason) {
Token token = TokenFactory.createToken();
token.setString("closeReason", closeReason.toString());
actionsDispatcher.performReservedAction(connector, ReservedActionName.CONNECTION_STOPPED_ACTION_NAME, token);
}
/**
* Process token sent by user. If token namespace is equals to
* {@link pl.bristleback.server.bristle.config.BristleConstants#BRISTLE_PLUGIN_NAMESPACE}, then plugin chain is aborted
* and dedicated dispatcher performs action. This is one of the core elements in Bristle plugin.
* More about dispatching actions can be found in {@link pl.bristleback.server.bristle.actions.ActionsDispatcher} documentation.
*
* @param response wrapper object containing information about plugin chain state.
* @param connector websocket connector.
* @param token content of the message.
*/
public void processToken(PlugInResponse response, WebSocketConnector connector, Token token) {
String namespace = token.getNS();
if (BristleConstants.BRISTLE_PLUGIN_NAMESPACE.equals(namespace)) {
response.abortChain();
performAction(connector, token);
}
}
private void performAction(WebSocketConnector connector, Token token) {
actionsDispatcher.performAction(connector, token);
}
/**
* Gets action dispatcher with actions and handlers inside.
*
* @return actions dispatcher.
*/
public ActionsDispatcher getActionsDispatcher() {
return actionsDispatcher;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy