// ---------------------------------------------------------------------------
// jWebSocket - Copyright (c) 2010 jwebsocket.org
// ---------------------------------------------------------------------------
// 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 program 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. See the GNU Lesser General Public License for
// more details.
// You should have received a copy of the GNU Lesser General Public License along
// with this program; if not, see <http://www.gnu.org/licenses/lgpl.html>.
// ---------------------------------------------------------------------------
package org.jwebsocket.factory;
import org.apache.log4j.Logger;
import org.jwebsocket.logging.Logging;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.util.List;
import java.util.Map;
import javolution.util.FastList;
import javolution.util.FastMap;
import org.jwebsocket.api.EngineConfiguration;
import org.jwebsocket.api.ServerConfiguration;
import org.jwebsocket.api.WebSocketEngine;
import org.jwebsocket.api.WebSocketFilter;
import org.jwebsocket.api.WebSocketInitializer;
import org.jwebsocket.api.WebSocketPlugIn;
import org.jwebsocket.api.WebSocketServer;
import org.jwebsocket.config.JWebSocketConfig;
import org.jwebsocket.config.LoggingConfig;
import org.jwebsocket.config.xml.EngineConfig;
import org.jwebsocket.config.xml.FilterConfig;
import org.jwebsocket.config.xml.PluginConfig;
import org.jwebsocket.config.xml.ServerConfig;
/**
* Intialize the engine, servers and plugins based on jWebSocket.xml
* configuration
*
* @author puran
* @version $Id: JWebSocketXmlConfigInitializer.java 424 2010-05-01 19:11:04Z
* mailtopuran $
*
*/
public final class JWebSocketXmlConfigInitializer implements
WebSocketInitializer {
// don't initialize logger here! Will be initialized with loaded settings!
private static Logger mLog = null;
private final JWebSocketJarClassLoader mClassLoader = new JWebSocketJarClassLoader();
private JWebSocketConfig mConfig;
/**
* private constructor
*/
private JWebSocketXmlConfigInitializer(JWebSocketConfig aConfig) {
this.mConfig = aConfig;
}
/**
* Returns the initializer object
*
* @param aConfig
* the jWebSocket config
* @return the initializer object
*/
public static JWebSocketXmlConfigInitializer getInitializer(
JWebSocketConfig aConfig) {
return new JWebSocketXmlConfigInitializer(aConfig);
}
/**
* {@inheritDoc}
*/
@Override
public void initializeLogging() {
LoggingConfig lLoggingConfig = mConfig.getLoggingConfig();
// initialize log4j logging engine
// BEFORE instantiating any jWebSocket classes
Logging.initLogs(lLoggingConfig.getLevel(), lLoggingConfig.getAppender(),
lLoggingConfig.getFilename(), lLoggingConfig.getPattern(),
lLoggingConfig.getBufferSize(),
new String[]{"%JWEBSOCKET_HOME%/logs", "%CATALINA_HOME%/logs"});
mLog = Logging.getLogger(JWebSocketXmlConfigInitializer.class);
if (mLog.isDebugEnabled()) {
mLog.debug("Logging settings"
+ ": appender: " + lLoggingConfig.getAppender()
+ ", filename: " + lLoggingConfig.getFilename()
+ ", level: " + lLoggingConfig.getLevel()
+ ", buffersize: " + lLoggingConfig.getBufferSize()
+ ", pattern: " + lLoggingConfig.getPattern());
}
if (mLog.isDebugEnabled()) {
mLog.debug("Starting jWebSocket Server Sub System...");
}
}
/**
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
@Override
public WebSocketEngine initializeEngine() {
WebSocketEngine newEngine = null;
EngineConfig engineConfig = mConfig.getEngines().get(0);
String jarFilePath = "-";
try {
Class lEngineClass = null;
// try to load engine from classpath first,
// could be located in server bundle
try {
lEngineClass = Class.forName(engineConfig.getName());
if (mLog.isDebugEnabled()) {
mLog.debug("Engine '" + engineConfig.getName() + "' loaded from classpath.");
}
} catch (ClassNotFoundException ex) {
// in case of a class not found exception we DO NOT want to
// show the exception but subsequently load the class from
if (mLog.isDebugEnabled()) {
mLog.debug("Engine '" + engineConfig.getName() + "' not yet in classpath, hence trying to load from file...");
}
}
// if not in classpath...
// try to load engine from given .jar file
if (lEngineClass == null) {
jarFilePath = JWebSocketConfig.getLibraryFolderPath(engineConfig.getJar());
// jarFilePath may be null if .jar is included in server bundle
if (jarFilePath != null) {
if (mLog.isDebugEnabled()) {
mLog.debug("Loading engine '" + engineConfig.getName() + "' from '" + jarFilePath + "'...");
}
mClassLoader.addFile(jarFilePath);
lEngineClass = (Class<WebSocketEngine>) mClassLoader.loadClass(engineConfig.getName());
}
}
// if class found
// try to create an instance
if (lEngineClass != null) {
Constructor<WebSocketEngine> ctor = lEngineClass.getDeclaredConstructor(EngineConfiguration.class);
ctor.setAccessible(true);
newEngine = ctor.newInstance(new Object[]{engineConfig});
if (mLog.isDebugEnabled()) {
mLog.debug("Engine '" + engineConfig.getId() + "' successfully instantiated.");
}
} else {
mLog.error("jWebSocket engine class " + engineConfig.getName() + " could not be loaded.");
}
} catch (MalformedURLException e) {
mLog.error("Couldn't load the jar file for engine, make sure jar file exists or name is correct", e);
} catch (ClassNotFoundException e) {
mLog.error("Engine class '" + engineConfig.getName() + "'@'" + jarFilePath + "' not found", e);
} catch (InstantiationException e) {
mLog.error("Engine class could not be instantiated", e);
} catch (IllegalAccessException e) {
mLog.error("Illegal Access Exception while intializing engine", e);
} catch (NoSuchMethodException e) {
mLog.error("No Constructor found with given 3 arguments", e);
} catch (InvocationTargetException e) {
mLog.error("Exception invoking engine object", e);
}
return newEngine;
}
/**
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
@Override
public List<WebSocketServer> initializeServers() {
List<WebSocketServer> lServers = new FastList<WebSocketServer>();
List<ServerConfig> lServerConfigs = mConfig.getServers();
for (ServerConfig lServerConfig : lServerConfigs) {
WebSocketServer lServer = null;
String lJarFilePath = "-";
try {
Class lServerClass = null;
// try to load server from classpath first,
// could be located in server bundle
try {
lServerClass = Class.forName(lServerConfig.getName());
if (mLog.isDebugEnabled()) {
mLog.debug("Server '" + lServerConfig.getName() + "' loaded from classpath.");
}
} catch (ClassNotFoundException ex) {
// in case of a class not found exception we DO NOT want to
// show the exception but subsequently load the class from
if (mLog.isDebugEnabled()) {
mLog.debug("Server '" + lServerConfig.getName() + "' not yet in classpath, hence trying to load from file...");
}
}
// if not in classpath...
// try to load server from given .jar file
if (lServerClass == null) {
lJarFilePath = JWebSocketConfig.getLibraryFolderPath(lServerConfig.getJar());
// jarFilePath may be null if .jar is included in server bundle
if (lJarFilePath != null) {
if (mLog.isDebugEnabled()) {
mLog.debug("Loading server '" + lServerConfig.getName() + "' from '" + lJarFilePath + "'...");
}
mClassLoader.addFile(lJarFilePath);
lServerClass = (Class<WebSocketServer>) mClassLoader.loadClass(lServerConfig.getName());
}
}
// if class found
// try to create an instance
if (lServerClass != null) {
Constructor<WebSocketServer> ctor = lServerClass.getDeclaredConstructor(ServerConfiguration.class);
ctor.setAccessible(true);
lServer = ctor.newInstance(new Object[]{lServerConfig});
if (mLog.isDebugEnabled()) {
mLog.debug("Server '" + lServerConfig.getId() + "' successfully instantiated.");
}
// add the initialized server to the list
lServers.add(lServer);
} else {
mLog.error("jWebSocket server class " + lServerConfig.getName() + " could not be loaded.");
}
} catch (MalformedURLException e) {
mLog.error(
"Couldn't load the jar file for server, make sure jar file '" + lJarFilePath + "' exists and name is correct.",
e);
} catch (ClassNotFoundException e) {
mLog.error(
"Server class '" + lServerConfig.getName() + "'@'" + lJarFilePath + "' not found.", e);
} catch (InstantiationException e) {
mLog.error(
"Server class '" + lServerConfig.getName() + "' could not be instantiated.", e);
} catch (IllegalAccessException e) {
mLog.error(
"Illegal Access Exception while intializing server '" + lServerConfig.getName() + "'.", e);
} catch (NoSuchMethodException e) {
mLog.error(
"No constructor found with given 1 arguments", e);
} catch (InvocationTargetException e) {
mLog.error(
"Exception invoking server object.", e);
}
}
return lServers;
}
/**
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
@Override
public Map<String, List<WebSocketPlugIn>> initializePlugins() {
Map<String, List<WebSocketPlugIn>> lPluginMap = new FastMap<String, List<WebSocketPlugIn>>();
// populate the plugin FastMap with server id and empty list
for (ServerConfig lServerConfig : mConfig.getServers()) {
lPluginMap.put(lServerConfig.getId(), new FastList<WebSocketPlugIn>());
}
// now initialize the pluin
for (PluginConfig lPluginConfig : mConfig.getPlugins()) {
try {
Class lPluginClass = null;
// try to load plug-in from classpath first,
// could be located in server bundle
try {
lPluginClass = Class.forName(lPluginConfig.getName());
if (mLog.isDebugEnabled()) {
mLog.debug("Plug-in '" + lPluginConfig.getName() + "' loaded from classpath.");
}
} catch (ClassNotFoundException ex) {
// in case of a class not found exception we DO NOT want to
// show the exception but subsequently load the class from
if (mLog.isDebugEnabled()) {
mLog.debug("Plug-in '" + lPluginConfig.getName() + "' not yet in classpath, hence trying to load from file...");
}
}
// if not in classpath...
// try to load plug-in from given .jar file
if (lPluginClass == null) {
String jarFilePath = JWebSocketConfig.getLibraryFolderPath(lPluginConfig.getJar());
// jarFilePath may be null if .jar is included in server bundle
if (jarFilePath != null) {
mClassLoader.addFile(jarFilePath);
if (mLog.isDebugEnabled()) {
mLog.debug("Loading plug-in '" + lPluginConfig.getName() + "' from '" + jarFilePath + "'...");
}
lPluginClass = (Class<WebSocketPlugIn>) mClassLoader.loadClass(lPluginConfig.getName());
}
}
// if class found
// try to create an instance
if (lPluginClass != null) {
/*
Constructor<WebSocketPlugIn> ctor = pluginClass.getDeclaredConstructor();
ctor.setAccessible(true);
Object lObj = ctor.newInstance(new Object[]{});
log.debug("lObj.classname = " + lObj.getClass().getName());
Object plugin = null;
try {
plugin = lObj;
log.info(
"lObj instanceof WebSocketPlugIn " + ( lObj instanceof WebSocketPlugIn ? "YES" : "NO" )
);
} catch (Exception ex) {
log.error(
ex.getClass().getSimpleName() + " while instantiating class '" + pluginConfig.getName() + "'.");
}
*/
WebSocketPlugIn lPlugIn = (WebSocketPlugIn) lPluginClass.newInstance();
// TODO: Also set id and name once these are available
lPlugIn.addAllSettings(lPluginConfig.getSettings());
if (mLog.isDebugEnabled()) {
mLog.debug("Plug-in '" + lPluginConfig.getId() + "' successfully instantiated.");
}
// now add the plugin to plugin map based on server ids
for (String lServerId : lPluginConfig.getServers()) {
List<WebSocketPlugIn> lPlugIns = lPluginMap.get(lServerId);
if (lPlugIns != null) {
lPlugIns.add((WebSocketPlugIn) lPlugIn);
}
}
}
} catch (MalformedURLException ex) {
mLog.error(
"Couldn't load the jar file for plugin, make sure the jar file exists and the name is correct.", ex);
} catch (ClassNotFoundException ex) {
mLog.error(
"Plugin class '" + lPluginConfig.getName() + "' not found.", ex);
} catch (InstantiationException ex) {
mLog.error(
"Plugin class '" + lPluginConfig.getName() + "' could not be instantiated.", ex);
} catch (IllegalAccessException ex) {
mLog.error(
"Illegal Access Exception while instantiating plugin.", ex);
} catch (Exception ex) {
mLog.error(
ex.getClass().getSimpleName() + " while instantiating plugin '" + lPluginConfig.getName() + "'.", ex);
}
}
return lPluginMap;
}
/**
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
@Override
public Map<String, List<WebSocketFilter>> initializeFilters() {
Map<String, List<WebSocketFilter>> lFilterMap = new FastMap<String, List<WebSocketFilter>>();
// populate the filter FastMap with server id and empty list
for (ServerConfig lServerConfig : mConfig.getServers()) {
lFilterMap.put(lServerConfig.getId(),
new FastList<WebSocketFilter>());
}
// now initialize the filter
for (FilterConfig lFilterConfig : mConfig.getFilters()) {
try {
Class lFilterClass = null;
// try to load filter from classpath first,
// could be located in server bundle
try {
lFilterClass = Class.forName(lFilterConfig.getName());
if (mLog.isDebugEnabled()) {
mLog.debug("Filter '" + lFilterConfig.getName() + "' loaded from classpath.");
}
} catch (ClassNotFoundException ex) {
// in case of a class not found exception we DO NOT want to
// show the exception but subsequently load the class from
if (mLog.isDebugEnabled()) {
mLog.debug("Filter '" + lFilterConfig.getName() + "' not yet in classpath, hence trying to load from file...");
}
}
// if not in classpath...
// try to load plug-in from given .jar file
if (lFilterClass == null) {
String jarFilePath = JWebSocketConfig.getLibraryFolderPath(lFilterConfig.getJar());
// jarFilePath may be null if .jar is included in server bundle
if (jarFilePath != null) {
mClassLoader.addFile(jarFilePath);
if (mLog.isDebugEnabled()) {
mLog.debug("Loading filter '" + lFilterConfig.getName() + "' from '" + jarFilePath + "'...");
}
lFilterClass = (Class<WebSocketFilter>) mClassLoader.loadClass(lFilterConfig.getName());
}
}
// if class found
// try to create an instance
if (lFilterClass != null) {
Constructor<WebSocketFilter> lConstr = lFilterClass.getDeclaredConstructor(String.class);
lConstr.setAccessible(true);
WebSocketFilter lFilter = lConstr.newInstance(new Object[]{lFilterConfig.getId()});
// TODO: Also set settings, id and name once these are available
// filter.addAllSettings(filterConfig.getSettings());
if (mLog.isDebugEnabled()) {
mLog.debug("Filter '" + lFilterConfig.getName() + "' successfully instantiated.");
}
// now add the filter to filter FastMap based on server ids
for (String lServerId : lFilterConfig.getServers()) {
List<WebSocketFilter> lFilters = lFilterMap.get(lServerId);
if (lFilters != null) {
lFilters.add(lFilter);
}
}
}
} catch (MalformedURLException e) {
mLog.error(
"Couldn't Load the jar file for filter, make sure jar file exists and name is correct.",
e);
} catch (ClassNotFoundException e) {
mLog.error(
"Filter class not found.", e);
} catch (InstantiationException e) {
mLog.error(
"Filter class could not be instantiated.", e);
} catch (IllegalAccessException e) {
mLog.error(
"Illegal Access Exception while intializing filter.", e);
} catch (NoSuchMethodException e) {
mLog.error(
"No Constructor found with given 3 arguments.", e);
} catch (InvocationTargetException e) {
mLog.error(
"Exception invoking filter object.", e);
}
}
return lFilterMap;
}
}