Commit ea69e703 authored by Alex Wenckus's avatar Alex Wenckus Committed by alex

Merged http-bind changes.

git-svn-id: http://svn.igniterealtime.org/svn/repos/wildfire/trunk@5912 b35dd754-fafc-0310-a699-88a17e54d16e
parent a0996044
......@@ -132,6 +132,11 @@
<attribute name="URI" value="/WEB-INF/lib/jaxen.jar" />
<url>jar://$MODULE_DIR$/build/lib/merge/jaxen.jar!/</url>
</containerElement>
<containerElement type="library" level="module">
<attribute name="method" value="0" />
<attribute name="URI" value="/WEB-INF/lib/jetty-util.jar" />
<url>jar://$MODULE_DIR$/build/lib/merge/jetty-util.jar!/</url>
</containerElement>
<containerElement type="library" level="module">
<attribute name="method" value="0" />
<attribute name="URI" value="/WEB-INF/lib/jetty.jar" />
......@@ -142,6 +147,11 @@
<attribute name="URI" value="/WEB-INF/lib/jmdns.jar" />
<url>jar://$MODULE_DIR$/build/lib/merge/jmdns.jar!/</url>
</containerElement>
<containerElement type="library" level="module">
<attribute name="method" value="0" />
<attribute name="URI" value="&lt;N/A&gt;" />
<url>jar://$MODULE_DIR$/build/lib/merge/jsp-api.jar!/</url>
</containerElement>
<containerElement type="library" level="module">
<attribute name="method" value="0" />
<attribute name="URI" value="/WEB-INF/lib/jstl.jar" />
......
......@@ -57,7 +57,6 @@
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="file://J:/whack/source/java" />
<root url="jar://$MODULE_DIR$/build/lib/merge/whack.jar!/" />
</SOURCES>
</library>
......@@ -149,9 +148,7 @@
<root url="jar://$MODULE_DIR$/build/lib/merge/dom4j.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="file://$MODULE_DIR$/../../java/dom4j-1.6.1/src/java" />
</SOURCES>
<SOURCES />
</library>
</orderEntry>
<orderEntry type="module-library" exported="">
......@@ -337,7 +334,16 @@
<orderEntry type="module-library">
<library>
<CLASSES>
<root url="jar://$MODULE_DIR$/../../Documents and Settings/gato/.IntelliJIdea60/config/plugins/Clover_for_IDEA_2848.jar!/" />
<root url="jar://$MODULE_DIR$/build/lib/merge/jetty-util.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
<orderEntry type="module-library">
<library>
<CLASSES>
<root url="jar://$MODULE_DIR$/build/lib/merge/jsp-api.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
......
......@@ -302,7 +302,6 @@
</component>
<component name="ProjectRootManager" version="2" assert-keyword="true" jdk-15="true" project-jdk-name="JDK 1.5.0" project-jdk-type="JavaSDK" />
<component name="ProjectRunConfigurationManager" />
<component name="ProjectRunConfigurationManager" />
<component name="RmicSettings">
<option name="IS_EANABLED" value="false" />
<option name="DEBUGGING_INFO" value="true" />
......
No preview for this file type
Name | Version
---------------------------------------------
ant.jar | Jetty 5.1.10
ant.jar | Jetty 6.1.0 (1.6.5)
ant-contrib.jar | 1.0b1
ant-subdirtask.jar | Revision 1.4 (CVS)
bouncycastle.jar | JDK 1.5, 134 (bcprov-jdk15-134.jar)
commons-logging.jar | Jetty 5.1.10
commons-el.jar | Jetty 5.1.10
commons-el.jar | Jetty 6.1.0 (1.0)
commons-httpclient.jar | 3.0
commons-codec.jar | 1.3
dom4j.jar | 1.6.1
hsqldb.jar | 1.8.0.5
jetty.jar | Jetty 5.1.10
jasper-compiler.jar | Jetty 5.1.10
jasper-runtime.jar | Jetty 5.1.10
jetty.jar | Jetty 6.1.0
jetty-util.jar | Jetty 6.1.0
jasper-compiler.jar | Jetty 6.1.0 (5.5.15)
jasper-runtime.jar | Jetty 6.1.0 (5.5.15)
jaxen.jar | 1.1 beta 4 (from DOM4J 1.6.1)
junit.jar | 3.8.1
jdic.jar | 0.9.1 (for windows only)
jstl.jar | Jakarta standard taglib 1.1.2
jmdns.jar | 1.0 RC1
jsp-api.jar | Jetty 6.1.0 (2.0)
jtds.jar | 1.2
jzlib.jar | 1.0.7
mail.jar | 1.4.0 (JavaMail)
mysql.jar | 3.1.13
pack200task.jar | August 5, 2004
postgres.jar | 8.1-404 JDBC 3
servlet.jar | Jetty 5.1.10
servlet.jar | Jetty 6.1.0 (2.5)
shaj.jar | 0.5
sitemesh.jar | 2.2.1
standard.jar | Jakarta standard taglib 1.1.2
......
......@@ -45,6 +45,8 @@ tab.server.descr=Klikn\u011bte pro spr\u00e1vu nastaven\u00ed serveru
sidebar.external-components-settings.descr=Klikn\u011bte pro zm\u011bnu nastaven\u00ed extern\u00edch komponent
sidebar.connection-managers-settings=Spr\u00e1vci p\u0159ipojen\u00ed
sidebar.connection-managers-settings.descr=Klikn\u011bte pro konfiguraci nastaven\u00ed spr\u00e1vce p\u0159ipojen\u00ed
sidebar.http-bind=HTTP Binding
sidebar.http-bind.descr=Click to configure HTTP binding settings
sidebar.server-reg-and-login=Registrace &amp; p\u0159ihl\u00e1\u0161en\u00ed
sidebar.server-reg-and-login.descr=Klikn\u011bte pro \u00fapravu registrace &amp; p\u0159ihla\u0161ovac\u00edch politik
sidebar.server-session-conflict=Politika zdroj\u016f
......@@ -1969,6 +1971,22 @@ plugin.enterprise.dont.show= Nezobrazovat znovu tuto str\u00e1nku
plugin.enterprise.installing = Instaluje se dopln\u011bk Enterprise ...
plugin.enterprise.installed = Dopln\u011bk Enterprise \u00fasp\u011b\u0161n\u011b nainstalov\u00e1n. Moment\u00e1ln\u011b prob\u00edh\u00e1 obnoven\u00ed...
# http bind settings page
httpbind.settings.enabled.legend=Service Enabled
httpbind.settings.title=HTTP Bind Settings
httpbind.settings.info=HTTP binding allows clients using the HTTP protocol to connect to Wildfire.
httpbind.settings.label_disable=Disabled
httpbind.settings.label_disable_info=Clients will not be able to connect with this server using HTTP binding.
httpbind.settings.label_enable=Enabled
httpbind.settings.label_enable_info=Clients can connect to this server using HTTP binding.
httpbind.settings.vanilla_port=Port:
httpbind.settings.label_seperate=Use Admin Console Ports
httpbind.settings.label_seperate_info=The HTTP bind service will be run on the same ports as the admin console
httpbind.settings.label_same=Use Distinct Ports
httpbind.settings.label_same_info=The HTTP bind service will use distinct ports from those of the admin console
httpbind.settings.secure_port=Secure Port
# Profile Settings
profile-settings.title=Nastaven\u00ed profilu
......
......@@ -44,6 +44,8 @@ tab.server.descr=Hier klicken um die Servereinstellungen zu verwalten
sidebar.external-components-settings.descr=
sidebar.connection-managers-settings=Connection Managers
sidebar.connection-managers-settings.descr=Click to configure connection manager settings
sidebar.http-bind=HTTP Binding
sidebar.http-bind.descr=Click to configure HTTP binding settings
sidebar.server-reg-and-login=Registrierung &amp; Anmeldung
sidebar.server-reg-and-login.descr=Hier klicken um die Registrierungs- und Anmeldungsrichtlinien zu bearbeiten
sidebar.server-session-conflict=Ressourcerichtlinien
......@@ -1726,3 +1728,19 @@ calendar.close = Close
calendar.today = Today
calendar.time_part = (Shift-)Click or drag to change value
calendar.time = Time:
# http bind settings page
httpbind.settings.enabled.legend=Service Enabled
httpbind.settings.title=HTTP Bind Settings
httpbind.settings.info=HTTP binding allows clients using the HTTP protocol to connect to Wildfire.
httpbind.settings.label_disable=Disabled
httpbind.settings.label_disable_info=Clients will not be able to connect with this server using HTTP binding.
httpbind.settings.label_enable=Enabled
httpbind.settings.label_enable_info=Clients can connect to this server using HTTP binding.
httpbind.settings.vanilla_port=Port:
httpbind.settings.label_seperate=Use Admin Console Ports
httpbind.settings.label_seperate_info=The HTTP bind service will be run on the same ports as the admin console
httpbind.settings.label_same=Use Distinct Ports
httpbind.settings.label_same_info=The HTTP bind service will use distinct ports from those of the admin console
httpbind.settings.secure_port=Secure Port
\ No newline at end of file
......@@ -125,6 +125,23 @@
## Added key: 'plugin.enterprise.installing'
## Added key: 'plugin.enterprise.installed'
##
## 3.2.0
## Added key: 'sidebar.http-bind'
## Added key: 'sidebar.http-bind.descr'
## Added key: 'httpbind.settings.enabled.legend'
## Added key: 'httpbind.settings.title'
## Added key: 'httpbind.settings.info'
## Added key: 'httpbind.settings.label_disable'
## Added key: 'httpbind.settings.label_disable_info'
## Added key: 'httpbind.settings.label_enable'
## Added key: 'httpbind.settings.label_enable_info'
## Added key: 'httpbind.settings.vanilla_port'
## Added key: 'httpbind.settings.label_seperate'
## Added key: 'httpbind.settings.label_seperate_info'
## Added key: 'httpbind.settings.label_same'
## Added key: 'httpbind.settings.label_same_info'
## Added key: 'httpbind.settings.secure_port'
##
## 3.1.1
## Added key: 'global.second'
## Added key: 'global.minute'
......@@ -193,6 +210,8 @@ tab.server.descr=Click to manage server settings
sidebar.external-components-settings.descr=Click to configure external component settings
sidebar.connection-managers-settings=Connection Managers
sidebar.connection-managers-settings.descr=Click to configure connection manager settings
sidebar.http-bind=HTTP Binding
sidebar.http-bind.descr=Click to configure HTTP binding settings
sidebar.server-reg-and-login=Registration &amp; Login
sidebar.server-reg-and-login.descr=Click to edit registration &amp; login policies
sidebar.server-session-conflict=Resource Policy
......@@ -2121,6 +2140,22 @@ plugin.enterprise.dont.show= Don't show this page again
plugin.enterprise.installing = Installing Enterprise Plugin...
plugin.enterprise.installed = Enterprise plugin installed successfully. Refreshing momentarily...
# http bind settings page
httpbind.settings.enabled.legend=Service Enabled
httpbind.settings.title=HTTP Bind Settings
httpbind.settings.info=HTTP binding allows clients using the HTTP protocol to connect to Wildfire.
httpbind.settings.label_disable=Disabled
httpbind.settings.label_disable_info=Clients will not be able to connect with this server using HTTP binding.
httpbind.settings.label_enable=Enabled
httpbind.settings.label_enable_info=Clients can connect to this server using HTTP binding.
httpbind.settings.vanilla_port=Port:
httpbind.settings.label_seperate=Use Admin Console Ports
httpbind.settings.label_seperate_info=The HTTP bind service will be run on the same ports as the admin console
httpbind.settings.label_same=Use Distinct Ports
httpbind.settings.label_same_info=The HTTP bind service will use distinct ports from those of the admin console
httpbind.settings.secure_port=SSL Port:
# Profile Settings
profile-settings.title=Profile Settings
......
......@@ -41,6 +41,8 @@ tab.server.descr=Presione para administrar la configuraci\u00f3n del servidor
sidebar.external-components-settings.descr=Presione para configurar los componentes externos
sidebar.connection-managers-settings=Administradores de Conexiones
sidebar.connection-managers-settings.descr=Presione para configurar los administradores de conexiones
sidebar.http-bind=HTTP Binding
sidebar.http-bind.descr=Click to configure HTTP binding settings
sidebar.server-reg-and-login=Registro y Conexiones
sidebar.server-reg-and-login.descr=Presione para editar la pol\u00edtica de registro y conexiones
sidebar.server-session-conflict=Pol\u00edtica de Recursos
......@@ -1837,6 +1839,22 @@ plugin.enterprise.dont.show= No mostrar esta p\u00e1gina nuevamente
plugin.enterprise.installing = Instalando Plugin Corporativo...
plugin.enterprise.installed = Plugin Corporativo instalado exitosamente. Refrescando en un instante...
# http bind settings page
httpbind.settings.enabled.legend=Service Enabled
httpbind.settings.title=HTTP Bind Settings
httpbind.settings.info=HTTP binding allows clients using the HTTP protocol to connect to Wildfire.
httpbind.settings.label_disable=Disabled
httpbind.settings.label_disable_info=Clients will not be able to connect with this server using HTTP binding.
httpbind.settings.label_enable=Enabled
httpbind.settings.label_enable_info=Clients can connect to this server using HTTP binding.
httpbind.settings.vanilla_port=Port:
httpbind.settings.label_seperate=Use Admin Console Ports
httpbind.settings.label_seperate_info=The HTTP bind service will be run on the same ports as the admin console
httpbind.settings.label_same=Use Distinct Ports
httpbind.settings.label_same_info=The HTTP bind service will use distinct ports from those of the admin console
httpbind.settings.secure_port=Secure Port
# Profile Settings
profile-settings.title=Seteos de Perfil
......
......@@ -42,6 +42,8 @@ tab.server.descr=Klik hier om de serverinstellingen te beheren
sidebar.external-components-settings.descr=
sidebar.connection-managers-settings=Connection Managers
sidebar.connection-managers-settings.descr=Click to configure connection manager settings
sidebar.http-bind=HTTP Binding
sidebar.http-bind.descr=Click to configure HTTP binding settings
sidebar.server-reg-and-login=Registratie &amp; aanmelding
sidebar.server-reg-and-login.descr=Klik hier om het registratie- &amp; aanmeldingsbeleid te wijzigen
sidebar.server-session-conflict=Extensiebeleid
......@@ -1732,3 +1734,19 @@ calendar.close = Close
calendar.today = Today
calendar.time_part = (Shift-)Click or drag to change value
calendar.time = Time:
# http bind settings page
httpbind.settings.enabled.legend=Service Enabled
httpbind.settings.title=HTTP Bind Settings
httpbind.settings.info=HTTP binding allows clients using the HTTP protocol to connect to Wildfire.
httpbind.settings.label_disable=Disabled
httpbind.settings.label_disable_info=Clients will not be able to connect with this server using HTTP binding.
httpbind.settings.label_enable=Enabled
httpbind.settings.label_enable_info=Clients can connect to this server using HTTP binding.
httpbind.settings.vanilla_port=Port:
httpbind.settings.label_seperate=Use Admin Console Ports
httpbind.settings.label_seperate_info=The HTTP bind service will be run on the same ports as the admin console
httpbind.settings.label_same=Use Distinct Ports
httpbind.settings.label_same_info=The HTTP bind service will use distinct ports from those of the admin console
httpbind.settings.secure_port=Secure Port
\ No newline at end of file
......@@ -46,6 +46,8 @@ tab.server.descr=Zarz\u0105dzanie ustawieniami serwera
sidebar.external-components-settings.descr=Kliknij aby skonfigurowa\u0107 ustawienia zewn\u0119trznych komponent\u00f3w
sidebar.connection-managers-settings=Menad\u017cer po\u0142\u0105cze\u0144
sidebar.connection-managers-settings.descr=Kliknij aby skonfigurowa\u0107 menad\u017cera po\u0142\u0105cze\u0144
sidebar.http-bind=HTTP Binding
sidebar.http-bind.descr=Click to configure HTTP binding settings
sidebar.server-reg-and-login=Rejestracja i logowanie
sidebar.server-reg-and-login.descr=Kliknij aby edytowa\u0107 ustawienia rejestracji i logowania u\u017cytkownik\u00f3w
sidebar.server-session-conflict=Polityka zasob\u00f3w
......@@ -1702,3 +1704,19 @@ calendar.close = Zamknij
calendar.today = Dzisiaj
calendar.time_part = (Shift-)klik lub chwy\u0107 aby zmieni\u0107 warto\u015b\u0107
calendar.time = Czas:
# http bind settings page
httpbind.settings.enabled.legend=Service Enabled
httpbind.settings.title=HTTP Bind Settings
httpbind.settings.info=HTTP binding allows clients using the HTTP protocol to connect to Wildfire.
httpbind.settings.label_disable=Disabled
httpbind.settings.label_disable_info=Clients will not be able to connect with this server using HTTP binding.
httpbind.settings.label_enable=Enabled
httpbind.settings.label_enable_info=Clients can connect to this server using HTTP binding.
httpbind.settings.vanilla_port=Port:
httpbind.settings.label_seperate=Use Admin Console Ports
httpbind.settings.label_seperate_info=The HTTP bind service will be run on the same ports as the admin console
httpbind.settings.label_same=Use Distinct Ports
httpbind.settings.label_same_info=The HTTP bind service will use distinct ports from those of the admin console
httpbind.settings.secure_port=Secure Port
\ No newline at end of file
......@@ -42,6 +42,8 @@ tab.server.descr=Clique para gerenciar as configura\u00e7\u00f5es do servidor
sidebar.external-components-settings.descr=Clique para editar as configura\u00e7\u00f5es de componentes externos
sidebar.connection-managers-settings=Gerenciadores de Conex\u00e3o
sidebar.connection-managers-settings.descr=Clique para configurar o gerenciador de conex\u00e3o
sidebar.http-bind=HTTP Binding
sidebar.http-bind.descr=Click to configure HTTP binding settings
sidebar.server-reg-and-login=Registro &amp; Login
sidebar.server-reg-and-login.descr=Clique para editar as pol\u00edticas de registro &amp;
sidebar.server-session-conflict=Pol\u00edtica de Recursos
......@@ -1733,3 +1735,19 @@ calendar.close = Fechar
calendar.today = Hoje
calendar.time_part = (Shift-)Clique ou arraste para mudar valor
calendar.time = Hora:
# http bind settings page
httpbind.settings.enabled.legend=Service Enabled
httpbind.settings.title=HTTP Bind Settings
httpbind.settings.info=HTTP binding allows clients using the HTTP protocol to connect to Wildfire.
httpbind.settings.label_disable=Disabled
httpbind.settings.label_disable_info=Clients will not be able to connect with this server using HTTP binding.
httpbind.settings.label_enable=Enabled
httpbind.settings.label_enable_info=Clients can connect to this server using HTTP binding.
httpbind.settings.vanilla_port=Port:
httpbind.settings.label_seperate=Use Admin Console Ports
httpbind.settings.label_seperate_info=The HTTP bind service will be run on the same ports as the admin console
httpbind.settings.label_same=Use Distinct Ports
httpbind.settings.label_same_info=The HTTP bind service will use distinct ports from those of the admin console
httpbind.settings.secure_port=Secure Port
\ No newline at end of file
......@@ -45,6 +45,8 @@ tab.server.descr=\u5355\u51fb\u53ef\u7ba1\u7406\u670d\u52a1\u5668\u8bbe\u7f6e
sidebar.external-components-settings.descr=\u70b9\u51fb\u914d\u7f6e\u5916\u90e8\u7ec4\u4ef6\u8bbe\u7f6e
sidebar.connection-managers-settings=\u8fde\u63a5\u7ba1\u7406
sidebar.connection-managers-settings.descr=\u5355\u51fb\u914d\u7f6e\u8fde\u63a5\u7ba1\u7406\u8bbe\u7f6e
sidebar.http-bind=HTTP Binding
sidebar.http-bind.descr=Click to configure HTTP binding settings
sidebar.server-reg-and-login=\u6ce8\u518c\u548c\u767b\u5f55
sidebar.server-reg-and-login.descr=\u5355\u51fb\u53ef\u7f16\u8f91\u6ce8\u518c\u548c\u767b\u5f55\u7b56\u7565
sidebar.server-session-conflict=\u8d44\u6e90\u7b56\u7565
......@@ -1769,6 +1771,22 @@ calendar.today = \u4eca\u5929
calendar.time_part = (Shift-)\u5355\u51fb\u6216\u62d6\u52a8\u6539\u53d8\u503c
calendar.time = \u65f6\u95f4:
# http bind settings page
httpbind.settings.enabled.legend=Service Enabled
httpbind.settings.title=HTTP Bind Settings
httpbind.settings.info=HTTP binding allows clients using the HTTP protocol to connect to Wildfire.
httpbind.settings.label_disable=Disabled
httpbind.settings.label_disable_info=Clients will not be able to connect with this server using HTTP binding.
httpbind.settings.label_enable=Enabled
httpbind.settings.label_enable_info=Clients can connect to this server using HTTP binding.
httpbind.settings.vanilla_port=Port:
httpbind.settings.label_seperate=Use Admin Console Ports
httpbind.settings.label_seperate_info=The HTTP bind service will be run on the same ports as the admin console
httpbind.settings.label_same=Use Distinct Ports
httpbind.settings.label_same_info=The HTTP bind service will use distinct ports from those of the admin console
httpbind.settings.secure_port=Secure Port
# Enterprise Download Page
plugin.enterprise.download.error = \u4e0d\u80fd\u4e0b\u8f7d\u4f01\u4e1a\u63d2\u4ef6\uff0c\u8bf7\u5c1d\u8bd5\u518d\u6b21\u4e0b\u8f7d
plugin.enterprise.dont.show= \u4e0d\u8981\u518d\u6b21\u663e\u793a\u6b64\u9875
......
......@@ -41,6 +41,8 @@ public interface ConnectionManager {
* @param serverPort holds information about the port on which the server is listening for
* connections.
* @param useBlockingMode true means that the server will use a thread per connection.
* @return the created socket reader.
* @throws java.io.IOException when there is an error creating the socket reader.
*/
public SocketReader createSocketReader(Socket socket, boolean isSecure, ServerPort serverPort,
boolean useBlockingMode) throws IOException;
......
/**
* $RCSfile$
* $Revision: $
* $Date: $
*
* Copyright (C) 2006 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.wildfire;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.Log;
import org.jivesoftware.util.PropertyEventDispatcher;
import org.jivesoftware.util.PropertyEventListener;
import org.jivesoftware.wildfire.net.SSLConfig;
import org.mortbay.jetty.Connector;
import org.mortbay.jetty.Server;
import org.mortbay.jetty.servlet.Context;
import org.mortbay.jetty.servlet.ServletHolder;
import org.mortbay.jetty.servlet.ServletHandler;
import org.mortbay.jetty.servlet.ServletMapping;
import org.mortbay.jetty.nio.SelectChannelConnector;
import org.mortbay.jetty.security.SslSocketConnector;
import javax.net.ssl.SSLServerSocketFactory;
import java.util.Collection;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
/**
* Manages the instances of Jetty which provide the admin console funtionality and the http binding
* functionality.
*
* @author Alexander Wenckus
*/
public class HttpServerManager {
private static final HttpServerManager instance = new HttpServerManager();
public static final String ADMIN_CONSOLE_PORT = "adminConsole.port";
public static final int ADMIN_CONSOLE_PORT_DEFAULT = 9090;
public static final String ADMIN_CONOSLE_SECURE_PORT = "adminConsole.securePort";
public static final int ADMIN_CONSOLE_SECURE_PORT_DEFAULT = 9091;
public static final String HTTP_BIND_ENABLED = "httpbind.enabled";
public static final boolean HTTP_BIND_ENABLED_DEFAULT = true;
public static final String HTTP_BIND_PORT = "httpbind.port.plain";
public static final int HTTP_BIND_PORT_DEFAULT = 8080;
public static final String HTTP_BIND_SECURE_PORT = "httpbind.port.secure";
public static final int HTTP_BIND_SECURE_PORT_DEFAULT = 8483;
public static HttpServerManager getInstance() {
return instance;
}
private int port;
private int securePort;
private Server adminServer;
private Server httpBindServer;
private Context adminConsoleContext;
private ServletHolder httpBindContext;
private String httpBindPath;
private HttpServerManager() {
PropertyEventDispatcher.addListener(new HttpServerPropertyListener());
}
public void setAdminConsoleContext(Context context) {
this.adminConsoleContext = context;
}
public void setHttpBindContext(ServletHolder context, String httpBindPath) {
this.httpBindContext = context;
this.httpBindPath = httpBindPath;
}
private void createHttpBindServer() {
port = JiveGlobals.getIntProperty(HTTP_BIND_PORT, ADMIN_CONSOLE_PORT_DEFAULT);
securePort = JiveGlobals.getIntProperty(HTTP_BIND_SECURE_PORT,
ADMIN_CONSOLE_SECURE_PORT_DEFAULT);
createHttpBindServer(port, securePort);
}
private void createHttpBindServer(int port, int securePort) {
httpBindServer = new Server();
Collection<Connector> connectors = createAdminConsoleConnectors(port, securePort);
if(connectors.size() == 0) {
httpBindServer = null;
return;
}
for (Connector connector : connectors) {
httpBindServer.addConnector(connector);
}
}
private void createAdminConsoleServer() {
int port = JiveGlobals.getXMLProperty(ADMIN_CONSOLE_PORT, ADMIN_CONSOLE_PORT_DEFAULT);
int securePort = JiveGlobals.getXMLProperty(ADMIN_CONOSLE_SECURE_PORT,
ADMIN_CONSOLE_SECURE_PORT_DEFAULT);
boolean loadConnectors = true;
if(httpBindServer != null) {
if(port == this.port && securePort == this.securePort) {
adminServer = httpBindServer;
loadConnectors = false;
}
else if(checkPorts(new int[] { this.port, this.securePort },
new int [] {port, securePort})) {
Log.warn("Http bind ports must be either the same or distinct from admin console" +
" ports.");
httpBindServer = null;
httpBindServer = new Server();
adminServer = httpBindServer;
}
else {
adminServer = new Server();
}
}
else {
adminServer = new Server();
}
if (loadConnectors) {
Collection<Connector> connectors = createAdminConsoleConnectors(port, securePort);
if(connectors.size() == 0) {
adminServer = null;
return;
}
for (Connector connector : connectors) {
adminServer.addConnector(connector);
}
}
}
private boolean checkPorts(int [] httpBindPorts, int [] adminConsolePorts) {
return httpBindPorts[0] == adminConsolePorts[0] || httpBindPorts[0] == adminConsolePorts[0]
|| httpBindPorts[1] == adminConsolePorts[0]
|| httpBindPorts[1] == adminConsolePorts[1];
}
public void startup() {
if(httpBindContext != null && isHttpBindServiceEnabled()) {
createHttpBindServer();
}
if(adminConsoleContext != null) {
createAdminConsoleServer();
}
addContexts();
if(httpBindServer != null) {
try {
httpBindServer.start();
}
catch (Exception e) {
Log.error("Could not start http bind server", e);
}
}
if(adminServer != null && adminServer != httpBindServer) {
try {
adminServer.start();
}
catch (Exception e) {
Log.error("Could not start admin conosle server", e);
}
}
}
private boolean isHttpBindServiceEnabled() {
return JiveGlobals.getBooleanProperty(HTTP_BIND_ENABLED, HTTP_BIND_ENABLED_DEFAULT);
}
private void addContexts() {
if(httpBindServer == adminServer && httpBindServer != null) {
adminConsoleContext.addServlet(httpBindContext, httpBindPath);
if (adminConsoleContext.getServer() == null) {
adminServer.addHandler(adminConsoleContext);
}
return;
}
if(adminServer != null) {
if(adminServer.getHandler() != null) {
removeHttpBindServlet(adminConsoleContext);
}
else {
adminServer.addHandler(adminConsoleContext);
}
}
if(httpBindServer != null) {
ServletHandler servletHandler = new ServletHandler();
servletHandler.addServletWithMapping(httpBindContext, httpBindPath);
httpBindServer.addHandler(servletHandler);
}
}
private void removeHttpBindServlet(Context adminConsoleContext) {
ServletHandler handler = adminConsoleContext.getServletHandler();
ServletMapping[] servletMappings = handler.getServletMappings();
List<ServletMapping> toAdd = new ArrayList<ServletMapping>();
for(ServletMapping mapping : servletMappings) {
if(mapping.getServletName().equals(httpBindContext.getName())) {
continue;
}
toAdd.add(mapping);
}
ServletHolder [] servletHolder = handler.getServlets();
List<ServletHolder> toAddServlets = new ArrayList<ServletHolder>();
for(ServletHolder holder : servletHolder) {
if(holder.equals(httpBindContext)) {
continue;
}
toAddServlets.add(holder);
}
handler.setServletMappings(toAdd.toArray(new ServletMapping[toAdd.size()]));
handler.setServlets(toAddServlets.toArray(new ServletHolder[toAddServlets.size()]));
}
public void shutdown() {
if(httpBindServer != null) {
try {
httpBindServer.stop();
}
catch (Exception e) {
Log.error("Error stopping http bind server", e);
}
httpBindServer = null;
}
//noinspection ConstantConditions
if(adminServer != null && adminServer != httpBindServer) {
try {
adminServer.stop();
}
catch (Exception e) {
Log.error("Error stopping admin console server", e);
}
adminServer = null;
}
}
private Collection<Connector> createAdminConsoleConnectors(int port, int securePort) {
List<Connector> connectorList = new ArrayList<Connector>();
if (port > 0) {
SelectChannelConnector connector = new SelectChannelConnector();
connector.setPort(port);
connectorList.add(connector);
}
try {
if (securePort > 0) {
SslSocketConnector sslConnector = new JiveSslConnector();
sslConnector.setPort(securePort);
sslConnector.setTrustPassword(SSLConfig.getTrustPassword());
sslConnector.setTruststoreType(SSLConfig.getStoreType());
sslConnector.setTruststore(SSLConfig.getTruststoreLocation());
sslConnector.setNeedClientAuth(false);
sslConnector.setWantClientAuth(false);
sslConnector.setKeyPassword(SSLConfig.getKeyPassword());
sslConnector.setKeystoreType(SSLConfig.getStoreType());
sslConnector.setKeystore(SSLConfig.getKeystoreLocation());
connectorList.add(sslConnector);
}
}
catch (Exception e) {
Log.error(e);
}
return connectorList;
}
/**
* Returns true if the HTTP bind server is currently enabled.
*
* @return true if the HTTP bind server is currently enabled.
*/
public boolean isHttpBindEnabled() {
return httpBindServer != null && httpBindServer.isRunning();
}
/**
* Returns the HTTP binding port which does not use SSL.
*
* @return the HTTP binding port which does not use SSL.
*/
public int getHttpBindUnsecurePort() {
return JiveGlobals.getIntProperty(HTTP_BIND_PORT, HTTP_BIND_PORT_DEFAULT);
}
/**
* Returns the HTTP binding port which uses SSL.
*
* @return the HTTP binding port which uses SSL.
*/
public int getHttpBindSecurePort() {
return JiveGlobals.getIntProperty(HTTP_BIND_SECURE_PORT, HTTP_BIND_SECURE_PORT_DEFAULT);
}
/**
* Returns true if the HTTP binding service is running on a seperate server than the admin
* console.
*
* @return true if the HTTP binding service is running on a seperate server than the admin
* console.
*/
public boolean isSeperateHttpBindServerConfigured() {
return (httpBindServer != null && httpBindServer != adminServer) || (httpBindServer == null
&& (getAdminUnsecurePort() != JiveGlobals.getIntProperty(HTTP_BIND_PORT, 9090)
|| getAdminSecurePort()
!= JiveGlobals.getIntProperty(HTTP_BIND_SECURE_PORT, 9091)));
}
public void setHttpBindEnabled(boolean isEnabled) {
JiveGlobals.setProperty(HTTP_BIND_ENABLED, String.valueOf(isEnabled));
}
/**
* Set the ports on which the HTTP bind service will be running.
*
* @param unsecurePort the unsecured connection port which clients can connect to.
* @param securePort the secured connection port which clients can connect to.
*/
public void setHttpBindPorts(int unsecurePort, int securePort) {
changeHttpBindPorts(unsecurePort, securePort);
port = unsecurePort;
this.securePort = securePort;
if (unsecurePort != getAdminUnsecurePort()) {
JiveGlobals.setProperty(HTTP_BIND_PORT, String.valueOf(unsecurePort));
}
else {
JiveGlobals.deleteProperty(HTTP_BIND_PORT);
}
if (securePort != getAdminSecurePort()) {
JiveGlobals.setProperty(HTTP_BIND_SECURE_PORT, String.valueOf(securePort));
}
else {
JiveGlobals.deleteProperty(HTTP_BIND_SECURE_PORT);
}
}
private void changeHttpBindPorts(int unsecurePort, int securePort) {
if(unsecurePort < 0 && securePort < 0) {
throw new IllegalArgumentException("At least one port must be greater than zero.");
}
if(unsecurePort == securePort) {
throw new IllegalArgumentException("Ports must be distinct.");
}
int adminPort = JiveGlobals.getXMLProperty(ADMIN_CONSOLE_PORT, ADMIN_CONSOLE_PORT_DEFAULT);
int adminSecurePort = JiveGlobals.getXMLProperty(ADMIN_CONOSLE_SECURE_PORT,
ADMIN_CONSOLE_SECURE_PORT_DEFAULT);
if (checkPorts(new int[]{unsecurePort, securePort},
new int[]{adminPort, adminSecurePort}))
{
if(unsecurePort != adminPort || securePort != adminSecurePort) {
Log.warn("Http bind ports must be either the same or distinct from admin console" +
" ports, http binding will run on the admin console ports.");
}
if (httpBindServer == adminServer) {
return;
}
if (httpBindServer != null) {
try {
httpBindServer.stop();
}
catch (Exception e) {
Log.error("Error stopping http bind service", e);
}
httpBindServer = null;
}
httpBindServer = adminServer;
addContexts();
return;
}
if (httpBindServer != adminServer) {
try {
httpBindServer.stop();
}
catch (Exception e) {
Log.error("Error stopping http bind service", e);
}
}
createHttpBindServer(unsecurePort, securePort);
addContexts();
try {
httpBindServer.start();
}
catch (Exception e) {
Log.error("Error starting http bind service", e);
}
}
public int getAdminUnsecurePort() {
return JiveGlobals.getXMLProperty(ADMIN_CONSOLE_PORT, ADMIN_CONSOLE_PORT_DEFAULT);
}
public int getAdminSecurePort() {
return JiveGlobals.getXMLProperty(ADMIN_CONOSLE_SECURE_PORT,
ADMIN_CONSOLE_SECURE_PORT_DEFAULT);
}
private void doEnableHttpBind(boolean shouldEnable) {
if(shouldEnable && httpBindServer == null) {
changeHttpBindPorts(JiveGlobals.getIntProperty(HTTP_BIND_PORT,
ADMIN_CONSOLE_PORT_DEFAULT),JiveGlobals.getIntProperty(HTTP_BIND_SECURE_PORT,
ADMIN_CONSOLE_SECURE_PORT_DEFAULT));
}
else if(!shouldEnable && httpBindServer != null) {
if (httpBindServer != adminServer) {
try {
httpBindServer.stop();
}
catch (Exception e) {
Log.error("Error stopping http bind service", e);
}
httpBindServer = null;
}
else {
removeHttpBindServlet(adminConsoleContext);
httpBindServer = null;
}
}
}
private void setUnsecureHttpBindPort(int value) {
if (value == port) {
return;
}
try {
changeHttpBindPorts(value, JiveGlobals.getIntProperty(HTTP_BIND_SECURE_PORT,
ADMIN_CONSOLE_SECURE_PORT_DEFAULT));
port = value;
}
catch (Exception ex) {
Log.error("Error setting http bind ports", ex);
}
}
private void setSecureHttpBindPort(int value) {
if (value == securePort) {
return;
}
try {
changeHttpBindPorts(JiveGlobals.getIntProperty(HTTP_BIND_PORT,
ADMIN_CONSOLE_PORT_DEFAULT), value);
securePort = value;
}
catch (Exception ex) {
Log.error("Error setting http bind ports", ex);
}
}
private class HttpServerPropertyListener implements PropertyEventListener {
public void propertySet(String property, Map params) {
if (property.equalsIgnoreCase(HTTP_BIND_ENABLED)) {
doEnableHttpBind(Boolean.valueOf(params.get("value").toString()));
}
else if (property.equalsIgnoreCase(HTTP_BIND_PORT)) {
int value;
try {
value = Integer.valueOf(params.get("value").toString());
}
catch (NumberFormatException ne) {
JiveGlobals.deleteProperty(HTTP_BIND_PORT);
return;
}
setUnsecureHttpBindPort(value);
}
else if (property.equalsIgnoreCase(HTTP_BIND_SECURE_PORT)) {
int value;
try {
value = Integer.valueOf(params.get("value").toString());
}
catch (NumberFormatException ne) {
JiveGlobals.deleteProperty(HTTP_BIND_SECURE_PORT);
return;
}
setSecureHttpBindPort(value);
}
}
public void propertyDeleted(String property, Map params) {
if(property.equalsIgnoreCase(HTTP_BIND_ENABLED)) {
doEnableHttpBind(HTTP_BIND_ENABLED_DEFAULT);
}
else if (property.equalsIgnoreCase(HTTP_BIND_PORT)) {
setUnsecureHttpBindPort(ADMIN_CONSOLE_PORT_DEFAULT);
}
else if (property.equalsIgnoreCase(HTTP_BIND_SECURE_PORT)) {
setSecureHttpBindPort(ADMIN_CONSOLE_SECURE_PORT_DEFAULT);
}
}
public void xmlPropertySet(String property, Map params) {
}
public void xmlPropertyDeleted(String property, Map params) {
}
}
private class JiveSslConnector extends SslSocketConnector {
@Override
protected SSLServerSocketFactory createFactory() throws Exception {
return SSLConfig.getServerSocketFactory();
}
}
}
......@@ -30,6 +30,7 @@ import org.jivesoftware.wildfire.server.OutgoingSessionPromise;
import org.jivesoftware.wildfire.spi.BasicStreamIDFactory;
import org.jivesoftware.wildfire.user.UserManager;
import org.jivesoftware.wildfire.user.UserNotFoundException;
import org.jivesoftware.wildfire.http.HttpSession;
import org.xmpp.packet.JID;
import org.xmpp.packet.Message;
import org.xmpp.packet.Packet;
......@@ -541,6 +542,21 @@ public class SessionManager extends BasicModule {
return session;
}
public HttpSession createClientHttpSession(InetAddress address, StreamID id)
throws UnauthorizedException
{
if (serverName == null) {
throw new UnauthorizedException("Server not initialized");
}
HttpSession session = new HttpSession(serverName, address, id);
Connection conn = session.getConnection();
conn.init(session);
conn.registerCloseListener(clientSessionListener, session);
preAuthenticatedSessions.put(session.getAddress().getResource(), session);
usersSessionsCounter.incrementAndGet();
return session;
}
public Session createComponentSession(Connection conn) throws UnauthorizedException {
if (serverName == null) {
throw new UnauthorizedException("Server not initialized");
......
......@@ -22,9 +22,10 @@ import org.jivesoftware.wildfire.audit.AuditManager;
import org.jivesoftware.wildfire.audit.spi.AuditManagerImpl;
import org.jivesoftware.wildfire.commands.AdHocCommandHandler;
import org.jivesoftware.wildfire.component.InternalComponentManager;
import org.jivesoftware.wildfire.container.AdminConsolePlugin;
import org.jivesoftware.wildfire.container.Module;
import org.jivesoftware.wildfire.container.PluginManager;
import org.jivesoftware.wildfire.container.PluginListener;
import org.jivesoftware.wildfire.container.Plugin;
import org.jivesoftware.wildfire.disco.IQDiscoInfoHandler;
import org.jivesoftware.wildfire.disco.IQDiscoItemsHandler;
import org.jivesoftware.wildfire.disco.ServerFeaturesProvider;
......@@ -125,6 +126,7 @@ public class XMPPServer {
"org.jivesoftware.wildfire.starter.ServerStarter";
private static final String WRAPPER_CLASSNAME =
"org.tanukisoftware.wrapper.WrapperManager";
private HttpServerManager httpServerManager;
/**
* Returns a singleton instance of XMPPServer.
......@@ -295,6 +297,7 @@ public class XMPPServer {
loader = Thread.currentThread().getContextClassLoader();
componentManager = InternalComponentManager.getInstance();
httpServerManager = HttpServerManager.getInstance();
initialized = true;
}
......@@ -327,8 +330,8 @@ public class XMPPServer {
// Otherwise, the page that requested the setup finish won't
// render properly!
Thread.sleep(1000);
((AdminConsolePlugin) pluginManager.getPlugin("admin"))
.restartListeners();
httpServerManager.shutdown();
httpServerManager.startup();
}
}
......@@ -383,6 +386,19 @@ public class XMPPServer {
ServerTrafficCounter.initStatistics();
// Load plugins (when in setup mode only the admin console will be loaded)
pluginManager.addPluginListener(new PluginListener() {
public void pluginCreated(String pluginName, Plugin plugin) {
if("admin".equals(pluginName)) {
httpServerManager.startup();
}
}
public void pluginDestroyed(String pluginName, Plugin plugin) {
if ("admin".equals(pluginName)) {
httpServerManager.shutdown();
}
}
});
pluginManager.start();
// Log that the server has been started
......
......@@ -13,16 +13,8 @@ package org.jivesoftware.wildfire.container;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.LocaleUtils;
import org.jivesoftware.util.Log;
import org.jivesoftware.wildfire.XMPPServer;
import org.mortbay.http.HttpContext;
import org.mortbay.http.HttpListener;
import org.mortbay.http.SunJsseListener;
import org.mortbay.jetty.Server;
import org.mortbay.log.Factory;
import org.mortbay.log.LogImpl;
import org.mortbay.log.OutputStreamLogSink;
import org.mortbay.util.InetAddrPort;
import org.jivesoftware.wildfire.HttpServerManager;
import org.mortbay.jetty.webapp.WebAppContext;
import java.io.File;
/**
......@@ -33,108 +25,20 @@ import java.io.File;
*/
public class AdminConsolePlugin implements Plugin {
private static Server jetty = null;
private int port;
private int securePort;
private File pluginDir;
private HttpContext context = null;
private HttpListener plainListener = null;
private HttpListener secureListener = null;
private HttpServerManager serverManager;
/**
* Create a jetty module.
*/
public AdminConsolePlugin() {
}
public void restartListeners() {
try {
String restarting = LocaleUtils.getLocalizedString("admin.console.restarting");
System.out.println(restarting);
Log.info(restarting);
jetty.stop();
if (plainListener != null) {
jetty.removeListener(plainListener);
plainListener = null;
}
if (secureListener != null) {
jetty.removeListener(secureListener);
secureListener = null;
}
jetty.removeContext(context);
loadListeners();
// Add web-app. Check to see if we're in development mode. If so, we don't
// add the normal web-app location, but the web-app in the project directory.
if (Boolean.getBoolean("developmentMode")) {
System.out.println(LocaleUtils.getLocalizedString("admin.console.devmode"));
context = jetty.addWebApplication("/",
pluginDir.getParentFile().getParentFile().getParentFile().getParent() + File.separator + "src" +
File.separator + "web");
}
else {
context = jetty.addWebApplication("/",
pluginDir.getAbsoluteFile() + File.separator + "webapp");
}
context.setWelcomeFiles(new String[]{"index.jsp"});
jetty.start();
printListenerMessages();
}
catch (Exception e) {
Log.error(e);
}
}
private void loadListeners() throws Exception {
// Configure HTTP socket listener. Setting the interface property to a
// non null value will imply that the Jetty server will only
// accept connect requests to that IP address.
String interfaceName = JiveGlobals.getXMLProperty("network.interface");
port = JiveGlobals.getXMLProperty("adminConsole.port", 9090);
InetAddrPort address = new InetAddrPort(interfaceName, port);
if (port > 0) {
plainListener = jetty.addListener(address);
}
try {
securePort = JiveGlobals.getXMLProperty("adminConsole.securePort", 9091);
if (securePort > 0) {
SunJsseListener listener = new SunJsseListener();
// Get the keystore location. The default location is security/keystore
String keyStoreLocation = JiveGlobals.getProperty("xmpp.socket.ssl.keystore",
"resources" + File.separator + "security" + File.separator + "keystore");
// The location is relative to the home directory of the application.
keyStoreLocation = JiveGlobals.getHomeDirectory() + File.separator + keyStoreLocation;
// Get the keystore password. The default password is "changeit".
String keypass = JiveGlobals.getProperty("xmpp.socket.ssl.keypass", "changeit");
keypass = keypass.trim();
listener.setKeystore(keyStoreLocation);
listener.setKeyPassword(keypass);
listener.setPassword(keypass);
listener.setHost(interfaceName);
listener.setPort(securePort);
secureListener = jetty.addListener(listener);
}
}
catch (Exception e) {
Log.error(e);
}
serverManager = HttpServerManager.getInstance();
}
public void initializePlugin(PluginManager manager, File pluginDir) {
this.pluginDir = pluginDir;
try {
// Configure logging to a file, creating log dir if needed
System.setProperty("org.apache.commons.logging.LogFactory", "org.mortbay.log.Factory");
File logDir = null;
File logDir;
String logDirectory = JiveGlobals.getXMLProperty("log.directory");
// Check if the "log.directory" was defined
if (logDirectory != null) {
......@@ -151,108 +55,33 @@ public class AdminConsolePlugin implements Plugin {
if (!logDir.exists()) {
logDir.mkdirs();
}
File logFile = new File(logDir, "admin-console.log");
OutputStreamLogSink logSink = new OutputStreamLogSink(logFile.toString());
logSink.start();
// In some cases, commons-logging settings can be stomped by other
// libraries in the classpath. Make sure that hasn't happened before
// setting configuration.
Object logImpl = Factory.getFactory().getInstance("");
if (logImpl instanceof LogImpl) {
LogImpl log = (LogImpl)logImpl;
// Ignore INFO logs unless debugging turned on.
if (Log.isDebugEnabled() &&
JiveGlobals.getBooleanProperty("jetty.debug.enabled", true)) {
log.setVerbose(1);
serverManager.setAdminConsoleContext(createWebAppContext());
}
else {
log.setVerbose(-1);
catch (Exception e) {
System.err.println("Error starting admin console: " + e.getMessage());
Log.error("Trouble initializing admin console", e);
}
log.add(logSink);
}
jetty = new Server();
loadListeners();
private WebAppContext createWebAppContext() {
WebAppContext context;
// Add web-app. Check to see if we're in development mode. If so, we don't
// add the normal web-app location, but the web-app in the project directory.
if (Boolean.getBoolean("developmentMode")) {
System.out.println(LocaleUtils.getLocalizedString("admin.console.devmode"));
context = jetty.addWebApplication("/",
pluginDir.getParentFile().getParentFile().getParentFile().getParent() + File.separator + "src" +
File.separator + "web");
context = new WebAppContext(
pluginDir.getParentFile().getParentFile().getParent() + File.separator +
"src" + File.separator + "web", "/");
}
else {
context = jetty.addWebApplication("/",
pluginDir.getAbsoluteFile() + File.separator + "webapp");
context = new WebAppContext(pluginDir.getAbsoluteFile() + File.separator + "webapp",
"/");
}
context.setWelcomeFiles(new String[]{"index.jsp"});
jetty.start();
printListenerMessages();
}
catch (Exception e) {
System.err.println("Error starting admin console: " + e.getMessage());
Log.error("Trouble initializing admin console", e);
}
return context;
}
public void destroyPlugin() {
plainListener = null;
secureListener = null;
try {
if (jetty != null) {
jetty.stop();
jetty = null;
}
}
catch (InterruptedException e) {
Log.error(LocaleUtils.getLocalizedString("admin.error"), e);
}
}
/**
* Returns the Jetty instance started by this plugin.
*
* @return the Jetty server instance.
*/
public static Server getJettyServer() {
return jetty;
}
/**
* Writes out startup messages for the listeners.
*/
private void printListenerMessages() {
String warning = LocaleUtils.getLocalizedString("admin.console.warning");
String listening = LocaleUtils.getLocalizedString("admin.console.listening");
if (plainListener == null && secureListener == null) {
Log.info(warning);
System.out.println(warning);
}
else if (plainListener == null) {
Log.info(listening + " https://" +
XMPPServer.getInstance().getServerInfo().getName() + ":" + securePort);
System.out.println(listening + " https://" +
XMPPServer.getInstance().getServerInfo().getName() + ":" + securePort);
}
else if (secureListener == null) {
Log.info(listening + " http://" +
XMPPServer.getInstance().getServerInfo().getName() + ":" + port);
System.out.println(listening + " http://" +
XMPPServer.getInstance().getServerInfo().getName() + ":" + port);
}
else {
String msg = listening + ":" + System.getProperty("line.separator") +
" http://" + XMPPServer.getInstance().getServerInfo().getName() + ":" +
port + System.getProperty("line.separator") +
" https://" + XMPPServer.getInstance().getServerInfo().getName() + ":" +
securePort;
Log.info(msg);
System.out.println(msg);
}
}
}
\ No newline at end of file
/**
* $RCSfile$
* $Revision: $
* $Date: $
*
* Copyright (C) 2006 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.wildfire.container;
/**
* Allows for notifications that a plugin has been either created or destroyed.
*
* @author Alexander Wenckus
*/
public interface PluginListener {
/**
* Called when a plugin has been created.
*
* @param pluginName the name of the created plugin.
* @param plugin the plugin that was created.
*/
void pluginCreated(String pluginName, Plugin plugin);
/**
* Called when a plugin has been destroyed.
*
* @param pluginName the name of the destroyed plugin.
* @param plugin the plugin that was destroyed.
*/
void pluginDestroyed(String pluginName, Plugin plugin);
}
......@@ -58,6 +58,7 @@ public class PluginManager {
private Map<Plugin, String> childPluginMap;
private Set<String> devPlugins;
private PluginMonitor pluginMonitor;
private Set<PluginListener> pluginListeners = new HashSet<PluginListener>();
/**
* Constructs a new plugin manager.
......@@ -458,6 +459,7 @@ public class PluginManager {
AdminConsole.addModel(pluginName, adminElement);
}
firePluginCreatedEvent(pluginDir.getName(), plugin);
}
else {
Log.warn("Plugin " + pluginDir + " could not be loaded: no plugin.xml file found");
......@@ -468,6 +470,14 @@ public class PluginManager {
}
}
private void firePluginCreatedEvent(String name, Plugin plugin) {
Collection<PluginListener> pluginListeners
= new ArrayList<PluginListener>(this.pluginListeners);
for(PluginListener listener : pluginListeners) {
listener.pluginCreated(name, plugin);
}
}
/**
* Unloads a plugin. The {@link Plugin#destroyPlugin()} method will be called and then
* any resources will be released. The name should be the name of the plugin directory
......@@ -538,6 +548,15 @@ public class PluginManager {
unloadPlugin(childPluginMap.get(plugin));
}
childPluginMap.remove(plugin);
firePluginDestroyedEvent(pluginName, plugin);
}
private void firePluginDestroyedEvent(String name, Plugin plugin) {
Collection<PluginListener> pluginListeners
= new ArrayList<PluginListener>(this.pluginListeners);
for (PluginListener listener : pluginListeners) {
listener.pluginDestroyed(name, plugin);
}
}
/**
......@@ -1054,4 +1073,12 @@ public class PluginManager {
return dir.delete();
}
}
public void addPluginListener(PluginListener listener) {
pluginListeners.add(listener);
}
public void removePluginListener(PluginListener listener) {
pluginListeners.remove(listener);
}
}
\ No newline at end of file
/**
* $RCSfile: $
* $Revision: $
* $Date: $
*
* Copyright (C) 2006 Jive Software. All rights reserved.
* This software is the proprietary information of Jive Software. Use is subject to license terms.
*/
package org.jivesoftware.wildfire.http;
/**
*
*/
public class HttpBindException extends Exception {
private boolean shouldCloseSession;
private int httpError;
public HttpBindException(String message, boolean shouldCloseSession, int httpError) {
super(message);
this.shouldCloseSession = shouldCloseSession;
this.httpError = httpError;
}
public int getHttpError() {
return httpError;
}
public boolean shouldCloseSession() {
return shouldCloseSession;
}
}
/**
* $RCSfile$
* $Revision: $
* $Date: $
*
* Copyright (C) 2006 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.wildfire.http;
import org.xmlpull.v1.XmlPullParserFactory;
import org.xmlpull.v1.XmlPullParserException;
import org.jivesoftware.util.Log;
import org.jivesoftware.wildfire.net.MXParser;
import org.jivesoftware.wildfire.auth.UnauthorizedException;
import org.dom4j.io.XMPPPacketReader;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.DocumentHelper;
import org.mortbay.util.ajax.ContinuationSupport;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletException;
import java.io.IOException;
import java.net.InetAddress;
/**
* Handles requests to the HTTP Bind service.
*
* @author Alexander Wenckus
*/
public class HttpBindServlet extends HttpServlet {
private HttpSessionManager sessionManager;
private static XmlPullParserFactory factory;
static {
try {
factory = XmlPullParserFactory.newInstance(MXParser.class.getName(), null);
}
catch (XmlPullParserException e) {
Log.error("Error creating a parser factory", e);
}
}
public HttpBindServlet(HttpSessionManager sessionManager) {
this.sessionManager = sessionManager;
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
if (isContinuation(request, response)) {
return;
}
Document document;
try {
document = createDocument(request);
}
catch (Exception e) {
Log.warn("Error parsing user request. [" + request.getRemoteAddr() + "]");
response.sendError(HttpServletResponse.SC_BAD_REQUEST,
"Unable to parse request content: " + e.getMessage());
return;
}
Element node = document.getRootElement();
if (node == null || !"body".equals(node.getName())) {
Log.warn("Body missing from request content. [" + request.getRemoteAddr() + "]");
response.sendError(HttpServletResponse.SC_BAD_REQUEST,
"Body missing from request content.");
return;
}
String sid = node.attributeValue("sid");
// We have a new session
if (sid == null) {
createNewSession(request, response, node);
}
else {
handleSessionRequest(sid, request, response, node);
}
}
private boolean isContinuation(HttpServletRequest request, HttpServletResponse response)
throws IOException
{
HttpConnection connection = (HttpConnection) request.getAttribute("request-connection");
if (connection == null) {
return false;
}
respond(response, connection);
return true;
}
private void handleSessionRequest(String sid, HttpServletRequest request,
HttpServletResponse response, Element rootNode)
throws IOException
{
long rid = getLongAttribue(rootNode.attributeValue("rid"), -1);
if (rid <= 0) {
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Body missing RID (Request ID)");
return;
}
HttpSession session = sessionManager.getSession(sid);
if (session == null) {
Log.warn("Client provided invalid session: " + sid + ". [" +
request.getRemoteAddr() + "]");
response.sendError(HttpServletResponse.SC_NOT_FOUND, "Invalid SID.");
return;
}
synchronized (session) {
HttpConnection connection;
try {
connection = sessionManager.forwardRequest(rid, session,
request.isSecure(), rootNode);
}
catch (HttpBindException e) {
response.sendError(e.getHttpError(), e.getMessage());
if(e.shouldCloseSession()) {
session.close();
}
return;
}
catch (HttpConnectionClosedException nc) {
Log.error("Error sending packet to client.", nc);
return;
}
String type = rootNode.attributeValue("type");
if ("terminate".equals(type)) {
session.close();
respond(response, createEmptyBody().getBytes("utf-8"));
}
else {
connection
.setContinuation(ContinuationSupport.getContinuation(request, connection));
request.setAttribute("request-connection", connection);
respond(response, connection);
}
}
}
private void createNewSession(HttpServletRequest request, HttpServletResponse response,
Element rootNode)
throws IOException
{
long rid = getLongAttribue(rootNode.attributeValue("rid"), -1);
if (rid <= 0) {
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Body missing RID (Request ID)");
return;
}
try {
HttpConnection connection = new HttpConnection(rid, request.isSecure());
InetAddress address = InetAddress.getByName(request.getRemoteAddr());
connection.setSession(sessionManager.createSession(address, rootNode, connection));
respond(response, connection);
}
catch (UnauthorizedException e) {
// Server wasn't initialized yet.
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
"Server Not initialized");
}
catch (HttpBindException e) {
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
}
private void respond(HttpServletResponse response, HttpConnection connection)
throws IOException
{
byte[] content;
try {
content = connection.getDeliverable().getBytes("utf-8");
}
catch (HttpBindTimeoutException e) {
content = createEmptyBody().getBytes("utf-8");
}
respond(response, content);
}
private void respond(HttpServletResponse response, byte [] content) throws IOException {
response.setStatus(HttpServletResponse.SC_OK);
response.setContentType("text/xml");
response.setCharacterEncoding("utf-8");
response.setContentLength(content.length);
response.getOutputStream().write(content);
}
private String createEmptyBody() {
Element body = DocumentHelper.createElement("body");
body.addNamespace("", "http://jabber.org/protocol/httpbind");
return body.asXML();
}
private long getLongAttribue(String value, long defaultValue) {
if (value == null || "".equals(value)) {
return defaultValue;
}
try {
return Long.valueOf(value);
}
catch (Exception ex) {
return defaultValue;
}
}
private Document createDocument(HttpServletRequest request) throws
DocumentException, IOException, XmlPullParserException {
// Reader is associated with a new XMPPPacketReader
XMPPPacketReader reader = new XMPPPacketReader();
reader.setXPPFactory(factory);
return reader.read(request.getInputStream());
}
}
/**
* $RCSfile$
* $Revision: $
* $Date: $
*
* Copyright (C) 2006 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.wildfire.http;
/**
* An exception which indicates that the maximum waiting time for a client response has been
* surpassed and an empty response should be returned to the requesting client.
*
* @author Alexander Wenckus
*/
class HttpBindTimeoutException extends Exception {
public HttpBindTimeoutException(String message) {
super(message);
}
public HttpBindTimeoutException() {
super();
}
}
/**
* $RCSfile: $
* $Revision: $
* $Date: $
*
* Copyright (C) 2006 Jive Software. All rights reserved.
* This software is the proprietary information of Jive Software. Use is subject to license terms.
*/
package org.jivesoftware.wildfire.http;
import org.jivesoftware.wildfire.Connection;
import org.mortbay.util.ajax.Continuation;
/**
* A connection to a client. The client will wait on getDeliverable() until the server forwards a
* message to it or the wait time on the session timesout.
*
* @author Alexander Wenckus
*/
public class HttpConnection {
private Connection.CompressionPolicy compressionPolicy;
private long requestId;
private String body;
private HttpSession session;
private Continuation continuation;
private boolean isClosed;
private boolean isSecure = false;
public HttpConnection(long requestId, boolean isSecure) {
this.requestId = requestId;
this.isSecure = isSecure;
}
public boolean validate() {
return false;
}
/**
* The connection should be closed without delivering a stanza to the requestor.
*/
public void close() {
if (isClosed) {
return;
}
try {
deliverBody(null);
}
catch (HttpConnectionClosedException e) {
/* Shouldn't happen */
}
}
public boolean isClosed() {
return isClosed;
}
public boolean isSecure() {
return isSecure;
}
/**
* Delivers content to the client. The content should be valid XMPP wrapped inside of a body.
* A <i>null</i> value for body indicates that the connection should be closed and the client
* sent an empty body.
*
* @param body the XMPP content to be forwarded to the client inside of a body tag.
*
* @throws HttpConnectionClosedException when this connection to the client has already recieved
* a deliverable to forward to the client
*/
public void deliverBody(String body) throws HttpConnectionClosedException {
// We only want to use this function once so we will close it when the body is delivered.
if (isClosed) {
throw new HttpConnectionClosedException("The http connection is no longer " +
"available to deliver content");
}
else {
isClosed = true;
}
if (continuation != null) {
continuation.setObject(body);
continuation.resume();
}
else {
this.body = body;
}
}
/**
* A call that will cause a wait, or in the case of Jetty the thread to be freed, if there is no
* deliverable currently available. Once the deliverable becomes available it is returned.
*
* @return the deliverable to send to the client
*
* @throws HttpBindTimeoutException to indicate that the maximum wait time requested by the
* client has been surpassed and an empty response should be returned.
*/
public String getDeliverable() throws HttpBindTimeoutException {
if (body == null && continuation != null) {
body = waitForDeliverable();
}
else if (body == null && continuation == null) {
throw new IllegalStateException("Continuation not set, cannot wait for deliverable.");
}
return body;
}
private String waitForDeliverable() throws HttpBindTimeoutException {
if (continuation.suspend(session.getWait() * 1000)) {
String deliverable = (String) continuation.getObject();
// This will occur when the hold attribute of a session has been exceded.
if (deliverable == null) {
throw new HttpBindTimeoutException();
}
return deliverable;
}
throw new HttpBindTimeoutException("Request " + requestId + " exceded response time from " +
"server of " + session.getWait() + " seconds.");
}
public boolean isCompressed() {
return false;
}
public Connection.CompressionPolicy getCompressionPolicy() {
return compressionPolicy;
}
public void setCompressionPolicy(Connection.CompressionPolicy compressionPolicy) {
this.compressionPolicy = compressionPolicy;
}
public long getRequestId() {
return requestId;
}
/**
* Set the session that this connection belongs to.
*
* @param session the session that this connection belongs to.
*/
void setSession(HttpSession session) {
this.session = session;
}
/**
* Returns the session that this connection belongs to.
*
* @return the session that this connection belongs to.
*/
public HttpSession getSession() {
return session;
}
void setContinuation(Continuation continuation) {
this.continuation = continuation;
}
}
/**
* $RCSfile$
* $Revision: $
* $Date: $
*
* Copyright (C) 2006 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.wildfire.http;
/**
* This exception is thrown when an action attempted on the connection to the client but the
* connection has been closed.
*
* @author Alexander Wenckus
*/
public class HttpConnectionClosedException extends Exception {
public HttpConnectionClosedException(String message) {
super(message);
}
}
/**
* $RCSfile$
* $Revision: $
* $Date: $
*
* Copyright (C) 2006 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.wildfire.http;
import org.jivesoftware.wildfire.ClientSession;
import org.jivesoftware.wildfire.StreamID;
import org.jivesoftware.wildfire.Connection;
import org.jivesoftware.wildfire.XMPPServer;
import org.jivesoftware.wildfire.net.VirtualConnection;
import org.jivesoftware.wildfire.net.SASLAuthentication;
import org.jivesoftware.wildfire.auth.UnauthorizedException;
import org.xmpp.packet.Packet;
import org.xmpp.packet.Message;
import org.dom4j.Element;
import org.dom4j.DocumentHelper;
import org.dom4j.QName;
import org.dom4j.Namespace;
import java.util.*;
import java.net.InetAddress;
/**
* A session represents a serious of interactions with an XMPP client sending packets using the HTTP
* Binding protocol specified in
* <a href="http://www.xmpp.org/extensions/xep-0124.html">XEP-0124</a>. A session can have several
* client connections open simultaneously while awaiting packets bound for the client from the
* server.
*
* @author Alexander Wenckus
*/
public class HttpSession extends ClientSession {
private int wait;
private int hold = -1000;
private String language;
private final Queue<HttpConnection> connectionQueue = new LinkedList<HttpConnection>();
private final List<Deliverable> pendingElements = new ArrayList<Deliverable>();
private boolean isSecure;
private int maxPollingInterval;
private long lastPoll = -1;
private Set<SessionListener> listeners = new HashSet<SessionListener>();
private boolean isClosed;
private int inactivityTimeout;
public HttpSession(String serverName, InetAddress address, StreamID streamID) {
super(serverName, null, streamID);
conn = new HttpVirtualConnection(address);
}
void addConnection(HttpConnection connection, boolean isPoll) throws HttpBindException,
HttpConnectionClosedException
{
if(connection == null) {
throw new IllegalArgumentException("Connection cannot be null.");
}
if(isPoll) {
checkPollingInterval();
}
if(isSecure && !connection.isSecure()) {
throw new HttpBindException("Session was started from secure connection, all " +
"connections on this session must be secured.", false, 403);
}
connection.setSession(this);
if (pendingElements.size() > 0) {
String deliverable = createDeliverable(pendingElements);
pendingElements.clear();
fireConnectionOpened(connection);
connection.deliverBody(deliverable);
fireConnectionClosed(connection);
}
else {
// With this connection we need to check if we will have too many connections open,
// closing any extras.
while (hold > 0 && connectionQueue.size() >= hold) {
HttpConnection toClose = connectionQueue.remove();
toClose.close();
fireConnectionClosed(toClose);
}
connectionQueue.offer(connection);
fireConnectionOpened(connection);
}
}
private void fireConnectionOpened(HttpConnection connection) {
Collection<SessionListener> listeners =
new HashSet<SessionListener>(this.listeners);
for(SessionListener listener : listeners) {
listener.connectionOpened(this, connection);
}
}
private void checkPollingInterval() throws HttpBindException {
long time = System.currentTimeMillis();
if(lastPoll > 0 && ((time - lastPoll) / 1000) < maxPollingInterval) {
throw new HttpBindException("Too frequent polling minimum interval is "
+ maxPollingInterval + ", current interval " + ((lastPoll - time) / 1000),
true, 403);
}
lastPoll = time;
}
public Collection<Element> getAvailableStreamFeaturesElements() {
List<Element> elements = new ArrayList<Element>();
Element sasl = SASLAuthentication.getSASLMechanismsElement(this);
if(sasl != null) {
elements.add(sasl);
}
// Include Stream Compression Mechanism
if (conn.getCompressionPolicy() != Connection.CompressionPolicy.disabled &&
!conn.isCompressed()) {
Element compression = DocumentHelper.createElement(new QName("compression",
new Namespace("", "http://jabber.org/features/compress")));
Element method = compression.addElement("method");
method.setText("zlib");
elements.add(compression);
}
Element bind = DocumentHelper.createElement(new QName("bind",
new Namespace("", "urn:ietf:params:xml:ns:xmpp-bind")));
elements.add(bind);
Element session = DocumentHelper.createElement(new QName("session",
new Namespace("", "urn:ietf:params:xml:ns:xmpp-session")));
elements.add(session);
return elements;
}
public String getAvailableStreamFeatures() {
StringBuilder sb = new StringBuilder(200);
for(Element element : getAvailableStreamFeaturesElements()) {
sb.append(element.asXML());
}
return sb.toString();
}
public InetAddress getInetAddress() {
return null;
}
public synchronized void close() {
conn.close();
}
private synchronized void closeConnection() {
if(isClosed) {
return;
}
isClosed = true;
if(pendingElements.size() > 0) {
failDelivery();
}
Collection<SessionListener> listeners =
new HashSet<SessionListener>(this.listeners);
this.listeners.clear();
for(SessionListener listener : listeners) {
listener.sessionClosed(this);
}
}
private void failDelivery() {
for(Deliverable deliverable : pendingElements) {
Packet packet = deliverable.packet;
if (packet != null && packet instanceof Message) {
XMPPServer.getInstance().getOfflineMessageStrategy()
.storeOffline((Message) packet);
}
}
pendingElements.clear();
}
public synchronized boolean isClosed() {
return isClosed;
}
private synchronized void deliver(String text) {
deliver(new Deliverable(text));
}
private synchronized void deliver(Packet stanza) {
deliver(new Deliverable(stanza));
}
private void deliver(Deliverable stanza) {
String deliverable = createDeliverable(Arrays.asList(stanza));
boolean delivered = false;
while(!delivered && connectionQueue.size() > 0) {
HttpConnection connection = connectionQueue.remove();
try {
connection.deliverBody(deliverable);
delivered = true;
fireConnectionClosed(connection);
}
catch (HttpConnectionClosedException e) {
/* Connection was closed, try the next one */
}
}
if(!delivered) {
pendingElements.add(stanza);
}
}
private void fireConnectionClosed(HttpConnection connection) {
Collection<SessionListener> listeners =
new HashSet<SessionListener>(this.listeners);
for(SessionListener listener : listeners) {
listener.connectionClosed(this, connection);
}
}
private String createDeliverable(Collection<Deliverable> elements) {
StringBuilder builder = new StringBuilder();
builder.append("<body xmlns='" + "http://jabber.org/protocol/httpbind" + "'>");
for(Deliverable child : elements) {
builder.append(child.getDeliverable());
}
builder.append("</body>");
return builder.toString();
}
/**
* This attribute specifies the longest time (in seconds) that the connection manager is allowed
* to wait before responding to any request during the session. This enables the client to
* prevent its TCP connection from expiring due to inactivity, as well as to limit the delay
* before it discovers any network failure.
*
* @param wait the longest time it is permissible to wait for a response.
*/
public void setWait(int wait) {
this.wait = wait;
}
/**
* This attribute specifies the longest time (in seconds) that the connection manager is allowed
* to wait before responding to any request during the session. This enables the client to
* prevent its TCP connection from expiring due to inactivity, as well as to limit the delay
* before it discovers any network failure.
*
* @return the longest time it is permissible to wait for a response.
*/
public int getWait() {
return wait;
}
/**
* This attribute specifies the maximum number of requests the connection manager is allowed
* to keep waiting at any one time during the session. (For example, if a constrained client
* is unable to keep open more than two HTTP connections to the same HTTP server simultaneously,
* then it SHOULD specify a value of "1".)
*
* @param hold the maximum number of simultaneous waiting requests.
*
*/
public void setHold(int hold) {
this.hold = hold;
}
/**
* This attribute specifies the maximum number of requests the connection manager is allowed
* to keep waiting at any one time during the session. (For example, if a constrained client
* is unable to keep open more than two HTTP connections to the same HTTP server simultaneously,
* then it SHOULD specify a value of "1".)
*
* @return the maximum number of simultaneous waiting requests
*/
public int getHold() {
return hold;
}
public void setLanaguage(String language) {
this.language = language;
}
public String getLanguage() {
return language;
}
/**
* Sets the max interval within which a client can send polling requests. If more than one
* request occurs in the interval the session will be terminated.
*
* @param maxPollingInterval time in seconds a client needs to wait before sending polls to the
* server, a negative <i>int</i> indicates that there is no limit.
*/
public void setMaxPollingInterval(int maxPollingInterval) {
this.maxPollingInterval = maxPollingInterval;
}
/**
* Sets whether the initial request on the session was secure.
*
* @param isSecure true if the initial request was secure and false if it wasn't.
*/
protected void setSecure(boolean isSecure) {
this.isSecure = isSecure;
}
/**
* Returns true if all connections on this session should be secured, and false if
* they should not.
*
* @return true if all connections on this session should be secured, and false if
* they should not.
*/
public boolean isSecure() {
return isSecure;
}
public void addSessionCloseListener(SessionListener listener) {
listeners.add(listener);
}
public void removeSessionCloseListener(SessionListener listener) {
listeners.remove(listener);
}
public void setInactivityTimeout(int inactivityTimeout) {
this.inactivityTimeout = inactivityTimeout;
}
public int getInactivityTimeout() {
return inactivityTimeout;
}
public int getConnectionCount() {
return connectionQueue.size();
}
/**
* A virtual server connection relates to a http session which its self can relate to many
* http connections.
*/
public static class HttpVirtualConnection extends VirtualConnection {
private InetAddress address;
public HttpVirtualConnection(InetAddress address) {
this.address = address;
}
public void closeVirtualConnection() {
((HttpSession)session).closeConnection();
}
public InetAddress getInetAddress() {
return address;
}
public void systemShutdown() {
((HttpSession)session).closeConnection();
}
public void deliver(Packet packet) throws UnauthorizedException {
((HttpSession)session).deliver(packet);
}
public void deliverRawText(String text) {
((HttpSession)session).deliver(text);
}
}
private class Deliverable {
private final String text;
private final Packet packet;
public Deliverable(String text) {
this.text = text;
this.packet = null;
}
public Deliverable(Packet element) {
this.text = null;
this.packet = element.createCopy();
}
public String getDeliverable() {
if(text == null) {
return packet.toXML();
}
else {
return text;
}
}
}
}
/**
* $RCSfile$
* $Revision: $
* $Date: $
*
* Copyright (C) 2006 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.wildfire.http;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.Log;
import org.jivesoftware.wildfire.SessionManager;
import org.jivesoftware.wildfire.StreamID;
import org.jivesoftware.wildfire.multiplex.MultiplexerPacketRouter;
import org.jivesoftware.wildfire.multiplex.UnknownStanzaException;
import org.jivesoftware.wildfire.auth.UnauthorizedException;
import org.dom4j.*;
import java.util.*;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
/**
*
*/
public class HttpSessionManager {
/**
* Milliseconds a connection has to be idle to be closed. Default is 30 minutes. Sending
* stanzas to the client is not considered as activity. We are only considering the connection
* active when the client sends some data or hearbeats (i.e. whitespaces) to the server.
* The reason for this is that sending data will fail if the connection is closed. And if
* the thread is blocked while sending data (because the socket is closed) then the clean up
* thread will close the socket anyway.
*/
private static int inactivityTimeout;
/**
* The connection manager MAY limit the number of simultaneous requests the client makes with
* the 'requests' attribute. The RECOMMENDED value is "2". Servers that only support polling
* behavior MUST prevent clients from making simultaneous requests by setting the 'requests'
* attribute to a value of "1" (however, polling is NOT RECOMMENDED). In any case, clients MUST
* NOT make more simultaneous requests than specified by the connection manager.
*/
private static int maxRequests;
/**
* The connection manager SHOULD include two additional attributes in the session creation
* response element, specifying the shortest allowable polling interval and the longest
* allowable inactivity period (both in seconds). Communication of these parameters enables
* the client to engage in appropriate behavior (e.g., not sending empty request elements more
* often than desired, and ensuring that the periods with no requests pending are
* never too long).
*/
private static int pollingInterval;
private InactivityTimer timer = new InactivityTimer();
private SessionManager sessionManager;
private Map<String, HttpSession> sessionMap = new HashMap<String, HttpSession>();
static {
// Set the default read idle timeout. If none was set then assume 30 minutes
inactivityTimeout = JiveGlobals.getIntProperty("xmpp.httpbind.client.idle", 30);
maxRequests = JiveGlobals.getIntProperty("xmpp.httpbind.client.requests.max", 2);
pollingInterval = JiveGlobals.getIntProperty("xmpp.httpbind.client.requests.polling", 5);
}
public HttpSessionManager() {
this.sessionManager = SessionManager.getInstance();
}
public HttpSession getSession(String streamID) {
return sessionMap.get(streamID);
}
public HttpSession createSession(InetAddress address, Element rootNode,
HttpConnection connection)
throws UnauthorizedException, HttpBindException
{
// TODO Check if IP address is allowed to connect to the server
// Default language is English ("en").
String language = rootNode.attributeValue("xml:lang");
if(language == null || "".equals(language)) {
language = "en";
}
int wait = getIntAttribute(rootNode.attributeValue("wait"), 60);
int hold = getIntAttribute(rootNode.attributeValue("hold"), 1);
HttpSession session = createSession(address);
session.setWait(wait);
session.setHold(hold);
session.setSecure(connection.isSecure());
session.setMaxPollingInterval(pollingInterval);
session.setInactivityTimeout(inactivityTimeout);
// Store language and version information in the connection.
session.setLanaguage(language);
try {
connection.deliverBody(createSessionCreationResponse(session));
}
catch (HttpConnectionClosedException e) {
/* This won't happen here. */
}
catch (DocumentException e) {
Log.error("Error creating document", e);
throw new HttpBindException("Internal server error", true, 500);
}
timer.reset(session);
return session;
}
private HttpSession createSession(InetAddress address) throws UnauthorizedException {
// Create a ClientSession for this user.
StreamID streamID = SessionManager.getInstance().nextStreamID();
// Send to the server that a new client session has been created
HttpSession session = sessionManager.createClientHttpSession(address, streamID);
// Register that the new session is associated with the specified stream ID
sessionMap.put(streamID.getID(), session);
session.addSessionCloseListener(new SessionListener() {
public void connectionOpened(HttpSession session, HttpConnection connection) {
timer.stop(session);
}
public void connectionClosed(HttpSession session, HttpConnection connection) {
if (session.getConnectionCount() <= 0) {
timer.reset(session);
}
}
public void sessionClosed(HttpSession session) {
sessionMap.remove(session.getStreamID().getID());
sessionManager.removeSession(session);
timer.stop(session);
}
});
return session;
}
private static int getIntAttribute(String value, int defaultValue) {
if(value == null || "".equals(value)) {
return defaultValue;
}
try {
return Integer.valueOf(value);
}
catch (Exception ex) {
return defaultValue;
}
}
private String createSessionCreationResponse(HttpSession session) throws DocumentException {
Element response = DocumentHelper.createElement("body");
response.addNamespace("", "http://jabber.org/protocol/httpbind");
response.addNamespace("stream", "http://etherx.jabber.org/streams");
response.addAttribute("authid", session.getStreamID().getID());
response.addAttribute("sid", session.getStreamID().getID());
response.addAttribute("secure", Boolean.TRUE.toString());
response.addAttribute("requests", String.valueOf(maxRequests));
response.addAttribute("inactivity", String.valueOf(session.getInactivityTimeout()));
response.addAttribute("polling", String.valueOf(pollingInterval));
response.addAttribute("wait", String.valueOf(session.getWait()));
Element features = response.addElement("stream:features");
for(Element feature : session.getAvailableStreamFeaturesElements()) {
features.add(feature);
}
return response.asXML();
}
public HttpConnection forwardRequest(long rid, HttpSession session, boolean isSecure,
Element rootNode) throws HttpBindException,
HttpConnectionClosedException
{
//noinspection unchecked
List<Element> elements = rootNode.elements();
boolean isPoll = elements.size() <= 0;
HttpConnection connection = new HttpConnection(rid, isSecure);
session.addConnection(connection, isPoll);
MultiplexerPacketRouter router = new MultiplexerPacketRouter(session);
for (Element packet : elements) {
try {
router.route(packet);
session.incrementClientPacketCount();
}
catch (UnsupportedEncodingException e) {
throw new HttpBindException("Bad auth request, unknown encoding", true, 400);
}
catch (UnknownStanzaException e) {
throw new HttpBindException("Unknown packet type.", false, 400);
}
}
return connection;
}
private class InactivityTimer extends Timer {
private Map<String, InactivityTimeoutTask> sessionMap
= new HashMap<String, InactivityTimeoutTask>();
public void stop(HttpSession session) {
InactivityTimeoutTask task = sessionMap.remove(session.getStreamID().getID());
if(task != null) {
task.cancel();
}
}
public void reset(HttpSession session) {
stop(session);
if(session.isClosed()) {
return;
}
InactivityTimeoutTask task = new InactivityTimeoutTask(session);
schedule(task, session.getInactivityTimeout() * 1000);
sessionMap.put(session.getStreamID().getID(), task);
}
}
private class InactivityTimeoutTask extends TimerTask {
private HttpSession session;
public InactivityTimeoutTask(HttpSession session) {
this.session = session;
}
public void run() {
session.close();
timer.sessionMap.remove(session.getStreamID().getID());
}
}
}
/**
* $RCSfile: $
* $Revision: $
* $Date: $
*
* Copyright (C) 2006 Jive Software. All rights reserved.
* This software is the proprietary information of Jive Software. Use is subject to license terms.
*/
package org.jivesoftware.wildfire.http;
/**
*
*/
public interface SessionListener {
public void connectionOpened(HttpSession session, HttpConnection connection);
public void connectionClosed(HttpSession session, HttpConnection connection);
public void sessionClosed(HttpSession session);
}
......@@ -16,11 +16,7 @@ import org.dom4j.Element;
import org.dom4j.QName;
import org.jivesoftware.util.Log;
import org.jivesoftware.wildfire.ClientSession;
import org.jivesoftware.wildfire.PacketRouter;
import org.jivesoftware.wildfire.XMPPServer;
import org.jivesoftware.wildfire.interceptor.InterceptorManager;
import org.jivesoftware.wildfire.interceptor.PacketRejectedException;
import org.jivesoftware.wildfire.net.SASLAuthentication;
import org.xmpp.packet.*;
import java.io.UnsupportedEncodingException;
......@@ -40,12 +36,10 @@ import java.util.List;
public class MultiplexerPacketHandler {
private String connectionManagerDomain;
private PacketRouter router;
private final ConnectionMultiplexerManager multiplexerManager;
public MultiplexerPacketHandler(String connectionManagerDomain) {
this.connectionManagerDomain = connectionManagerDomain;
router = XMPPServer.getInstance().getPacketRouter();
multiplexerManager = ConnectionMultiplexerManager.getInstance();
}
......@@ -160,144 +154,30 @@ public class MultiplexerPacketHandler {
sendErrorPacket(route, PacketError.Condition.item_not_found, null);
return;
}
// Connection Manager wrapped a packet from a Client Session.
Element wrappedElement = route.getChildElement();
String tag = wrappedElement.getName();
MultiplexerPacketRouter router = new MultiplexerPacketRouter(session);
try {
if ("auth".equals(tag) || "response".equals(tag)) {
SASLAuthentication.handle(session, wrappedElement);
}
else if ("iq".equals(tag)) {
processIQ(session, getIQ(wrappedElement));
}
else if ("message".equals(tag)) {
processMessage(session, new Message(wrappedElement));
router.route(route.getChildElement());
}
else if ("presence".equals(tag)) {
processPresence(session, new Presence(wrappedElement));
}
else {
catch (UnknownStanzaException use) {
Element extraError = DocumentHelper.createElement(QName.get(
"unknown-stanza",
"http://jabber.org/protocol/connectionmanager#errors"));
sendErrorPacket(route, PacketError.Condition.bad_request, extraError);
}
}
catch (UnsupportedEncodingException e) {
Log.error("Error processing wrapped packet: " + wrappedElement.asXML(), e);
Log.error("Error processing wrapped packet: " + route.getChildElement().asXML(), e);
sendErrorPacket(route, PacketError.Condition.internal_server_error, null);
}
}
private void processIQ(ClientSession session, IQ packet) {
packet.setFrom(session.getAddress());
try {
// Invoke the interceptors before we process the read packet
InterceptorManager.getInstance().invokeInterceptors(packet, session, true,
false);
router.route(packet);
// Invoke the interceptors after we have processed the read packet
InterceptorManager.getInstance().invokeInterceptors(packet, session, true,
true);
session.incrementClientPacketCount();
}
catch (PacketRejectedException e) {
// An interceptor rejected this packet so answer a not_allowed error
IQ reply = new IQ();
reply.setChildElement(packet.getChildElement().createCopy());
reply.setID(packet.getID());
reply.setTo(session.getAddress());
reply.setFrom(packet.getTo());
reply.setError(PacketError.Condition.not_allowed);
session.process(reply);
// Check if a message notifying the rejection should be sent
if (e.getRejectionMessage() != null && e.getRejectionMessage().trim().length() > 0) {
// A message for the rejection will be sent to the sender of the rejected packet
Message notification = new Message();
notification.setTo(session.getAddress());
notification.setFrom(packet.getTo());
notification.setBody(e.getRejectionMessage());
session.process(notification);
}
}
}
private void processPresence(ClientSession session, Presence packet) {
packet.setFrom(session.getAddress());
try {
// Invoke the interceptors before we process the read packet
InterceptorManager.getInstance().invokeInterceptors(packet, session, true,
false);
router.route(packet);
// Invoke the interceptors after we have processed the read packet
InterceptorManager.getInstance().invokeInterceptors(packet, session, true,
true);
session.incrementClientPacketCount();
}
catch (PacketRejectedException e) {
// An interceptor rejected this packet so answer a not_allowed error
Presence reply = new Presence();
reply.setID(packet.getID());
reply.setTo(session.getAddress());
reply.setFrom(packet.getTo());
reply.setError(PacketError.Condition.not_allowed);
session.process(reply);
// Check if a message notifying the rejection should be sent
if (e.getRejectionMessage() != null && e.getRejectionMessage().trim().length() > 0) {
// A message for the rejection will be sent to the sender of the rejected packet
Message notification = new Message();
notification.setTo(session.getAddress());
notification.setFrom(packet.getTo());
notification.setBody(e.getRejectionMessage());
session.process(notification);
}
}
}
private void processMessage(ClientSession session, Message packet) {
packet.setFrom(session.getAddress());
try {
// Invoke the interceptors before we process the read packet
InterceptorManager.getInstance().invokeInterceptors(packet, session, true,
false);
router.route(packet);
// Invoke the interceptors after we have processed the read packet
InterceptorManager.getInstance().invokeInterceptors(packet, session, true,
true);
session.incrementClientPacketCount();
}
catch (PacketRejectedException e) {
// An interceptor rejected this packet
if (e.getRejectionMessage() != null && e.getRejectionMessage().trim().length() > 0) {
// A message for the rejection will be sent to the sender of the rejected packet
Message reply = new Message();
reply.setID(packet.getID());
reply.setTo(session.getAddress());
reply.setFrom(packet.getTo());
reply.setType(packet.getType());
reply.setThread(packet.getThread());
reply.setBody(e.getRejectionMessage());
session.process(reply);
}
}
}
private IQ getIQ(Element doc) {
Element query = doc.element("query");
if (query != null && "jabber:iq:roster".equals(query.getNamespaceURI())) {
return new Roster(doc);
}
else {
return new IQ(doc);
}
}
/**
* Sends an IQ error with the specified condition to the sender of the original
* IQ packet.
*
* @param packet the packet to be bounced.
* @param extraError application specific error or null if none.
* @param error the error.
*/
private void sendErrorPacket(IQ packet, PacketError.Condition error, Element extraError) {
IQ reply = IQ.createResultIQ(packet);
......@@ -316,6 +196,7 @@ public class MultiplexerPacketHandler {
*
* @param packet the packet to be bounced.
* @param extraError application specific error or null if none.
* @param error the error.
*/
private void sendErrorPacket(Route packet, PacketError.Condition error, Element extraError) {
Route reply = new Route(packet.getStreamID());
......
/**
* $RCSfile: $
* $Revision: $
* $Date: $
*
* Copyright (C) 2006 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.wildfire.multiplex;
import org.jivesoftware.wildfire.PacketRouter;
import org.jivesoftware.wildfire.ClientSession;
import org.jivesoftware.wildfire.XMPPServer;
import org.jivesoftware.wildfire.interceptor.InterceptorManager;
import org.jivesoftware.wildfire.interceptor.PacketRejectedException;
import org.jivesoftware.wildfire.net.SASLAuthentication;
import org.xmpp.packet.*;
import org.dom4j.Element;
import java.io.UnsupportedEncodingException;
/**
* Handles the routing of packets to a particular session.
*
* @author Alexander Wenckus
*/
public class MultiplexerPacketRouter {
private ClientSession session;
private PacketRouter router;
public MultiplexerPacketRouter(ClientSession session) {
this.session = session;
router = XMPPServer.getInstance().getPacketRouter();
}
public void route(Element wrappedElement)
throws UnsupportedEncodingException, UnknownStanzaException
{
String tag = wrappedElement.getName();
if ("auth".equals(tag) || "response".equals(tag)) {
SASLAuthentication.handle(session, wrappedElement);
}
else if ("iq".equals(tag)) {
route(getIQ(wrappedElement));
}
else if ("message".equals(tag)) {
route(new Message(wrappedElement));
}
else if ("presence".equals(tag)) {
route(new Presence(wrappedElement));
}
else {
throw new UnknownStanzaException();
}
}
private IQ getIQ(Element doc) {
Element query = doc.element("query");
if (query != null && "jabber:iq:roster".equals(query.getNamespaceURI())) {
return new Roster(doc);
}
else {
return new IQ(doc);
}
}
public void route(IQ packet) {
packet.setFrom(session.getAddress());
try {
// Invoke the interceptors before we process the read packet
InterceptorManager.getInstance().invokeInterceptors(packet, session, true,
false);
router.route(packet);
// Invoke the interceptors after we have processed the read packet
InterceptorManager.getInstance().invokeInterceptors(packet, session, true,
true);
session.incrementClientPacketCount();
}
catch (PacketRejectedException e) {
// An interceptor rejected this packet so answer a not_allowed error
IQ reply = new IQ();
reply.setChildElement(packet.getChildElement().createCopy());
reply.setID(packet.getID());
reply.setTo(session.getAddress());
reply.setFrom(packet.getTo());
reply.setError(PacketError.Condition.not_allowed);
session.process(reply);
// Check if a message notifying the rejection should be sent
if (e.getRejectionMessage() != null && e.getRejectionMessage().trim().length() > 0) {
// A message for the rejection will be sent to the sender of the rejected packet
Message notification = new Message();
notification.setTo(session.getAddress());
notification.setFrom(packet.getTo());
notification.setBody(e.getRejectionMessage());
session.process(notification);
}
}
}
public void route(Message packet) {
packet.setFrom(session.getAddress());
try {
// Invoke the interceptors before we process the read packet
InterceptorManager.getInstance().invokeInterceptors(packet, session, true,
false);
router.route(packet);
// Invoke the interceptors after we have processed the read packet
InterceptorManager.getInstance().invokeInterceptors(packet, session, true,
true);
session.incrementClientPacketCount();
}
catch (PacketRejectedException e) {
// An interceptor rejected this packet
if (e.getRejectionMessage() != null && e.getRejectionMessage().trim().length() > 0) {
// A message for the rejection will be sent to the sender of the rejected packet
Message reply = new Message();
reply.setID(packet.getID());
reply.setTo(session.getAddress());
reply.setFrom(packet.getTo());
reply.setType(packet.getType());
reply.setThread(packet.getThread());
reply.setBody(e.getRejectionMessage());
session.process(reply);
}
}
}
public void route(Presence packet) {
packet.setFrom(session.getAddress());
try {
// Invoke the interceptors before we process the read packet
InterceptorManager.getInstance().invokeInterceptors(packet, session, true,
false);
router.route(packet);
// Invoke the interceptors after we have processed the read packet
InterceptorManager.getInstance().invokeInterceptors(packet, session, true,
true);
session.incrementClientPacketCount();
}
catch (PacketRejectedException e) {
// An interceptor rejected this packet so answer a not_allowed error
Presence reply = new Presence();
reply.setID(packet.getID());
reply.setTo(session.getAddress());
reply.setFrom(packet.getTo());
reply.setError(PacketError.Condition.not_allowed);
session.process(reply);
// Check if a message notifying the rejection should be sent
if (e.getRejectionMessage() != null && e.getRejectionMessage().trim().length() > 0) {
// A message for the rejection will be sent to the sender of the rejected packet
Message notification = new Message();
notification.setTo(session.getAddress());
notification.setFrom(packet.getTo());
notification.setBody(e.getRejectionMessage());
session.process(notification);
}
}
}
}
/**
* $RCSfile: $
* $Revision: $
* $Date: $
*
* Copyright (C) 2006 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.wildfire.multiplex;
/**
*
*/
public class UnknownStanzaException extends Exception {
}
......@@ -12,6 +12,9 @@
package org.jivesoftware.wildfire.net;
import org.dom4j.Element;
import org.dom4j.DocumentHelper;
import org.dom4j.QName;
import org.dom4j.Namespace;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.Log;
import org.jivesoftware.util.StringUtils;
......@@ -147,6 +150,43 @@ public class SASLAuthentication {
return sb.toString();
}
public static Element getSASLMechanismsElement(Session session) {
if (!(session instanceof ClientSession) && !(session instanceof IncomingServerSession)) {
return null;
}
Element mechs = DocumentHelper.createElement(new QName("mechanisms",
new Namespace("", "urn:ietf:params:xml:ns:xmpp-sasl")));
if (session instanceof IncomingServerSession) {
// Server connections dont follow the same rules as clients
if (session.getConnection().isSecure()) {
// Offer SASL EXTERNAL only if TLS has already been negotiated
Element mechanism = mechs.addElement("mechanism");
mechanism.setText("EXTERNAL");
}
}
else {
for (String mech : mechanisms) {
if (mech.equals("CRAM-MD5") || mech.equals("DIGEST-MD5")) {
// Check if the user provider in use supports passwords retrieval. Accessing
// to the users passwords will be required by the CallbackHandler
if (!AuthFactory.getAuthProvider().supportsPasswordRetrieval()) {
continue;
}
}
else if (mech.equals("ANONYMOUS")) {
// Check anonymous is supported
if (!XMPPServer.getInstance().getIQAuthHandler().isAnonymousAllowed()) {
continue;
}
}
Element mechanism = mechs.addElement("mechanism");
mechanism.setText(mech);
}
}
return mechs;
}
/**
* Handles the SASL authentication packet. The entity may be sending an initial
* authentication request or a response to a challenge made by the server. The returned
......
......@@ -3,7 +3,7 @@
* $Revision: 1217 $
* $Date: 2005-04-11 18:11:06 -0300 (Mon, 11 Apr 2005) $
*
* Copyright (C) 2004 Jive Software. All rights reserved.
* Copyright (C) 2006 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
......@@ -36,13 +36,14 @@ public class SSLConfig {
private static String trustpass;
private static String keyStoreLocation;
private static String trustStoreLocation;
private static String storeType;
private SSLConfig() {
}
static {
String algorithm = JiveGlobals.getProperty("xmpp.socket.ssl.algorithm", "TLS");
String storeType = JiveGlobals.getProperty("xmpp.socket.ssl.storeType", "jks");
storeType = JiveGlobals.getProperty("xmpp.socket.ssl.storeType", "jks");
// Get the keystore location. The default location is security/keystore
keyStoreLocation = JiveGlobals.getProperty("xmpp.socket.ssl.keystore",
......@@ -151,4 +152,20 @@ public class SSLConfig {
return sslFactory.createServerSocket(port, -1, ifAddress);
}
}
public static String getKeystoreLocation() {
return keyStoreLocation;
}
public static String getTruststoreLocation() {
return trustStoreLocation;
}
public static String getStoreType() {
return storeType;
}
public static SSLJiveServerSocketFactory getServerSocketFactory() {
return sslFactory;
}
}
\ No newline at end of file
......@@ -15,10 +15,14 @@ import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.LocaleUtils;
import org.jivesoftware.util.Log;
import org.jivesoftware.wildfire.*;
import org.jivesoftware.wildfire.http.HttpSessionManager;
import org.jivesoftware.wildfire.http.HttpBindServlet;
import org.jivesoftware.wildfire.container.BasicModule;
import org.jivesoftware.wildfire.multiplex.MultiplexerPacketDeliverer;
import org.jivesoftware.wildfire.net.*;
import org.mortbay.jetty.Handler;
import org.mortbay.jetty.servlet.ServletHolder;
import org.mortbay.jetty.servlet.ServletHandler;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
......@@ -48,10 +52,12 @@ public class ConnectionManagerImpl extends BasicModule implements ConnectionMana
private boolean isStarted = false;
// Used to know if the sockets have been started
private boolean isSocketStarted = false;
private HttpServerManager serverManager;
public ConnectionManagerImpl() {
super("Connection Manager");
ports = new ArrayList<ServerPort>(4);
serverManager = HttpServerManager.getInstance();
}
private void createSocket() {
......@@ -82,6 +88,8 @@ public class ConnectionManagerImpl extends BasicModule implements ConnectionMana
startClientListeners(localIPAddress);
// Start the port listener for secured clients
startClientSSLListeners(localIPAddress);
// Start the HTTP client listener
startHTTPBindListeners();
}
private void startServerListener(String localIPAddress) {
......@@ -282,6 +290,14 @@ public class ConnectionManagerImpl extends BasicModule implements ConnectionMana
}
}
private void startHTTPBindListeners() {
serverManager.setHttpBindContext(createServletHandler(), "/http-bind/");
}
private ServletHolder createServletHandler() {
return new ServletHolder(new HttpBindServlet(new HttpSessionManager()));
}
public void initialize(XMPPServer server) {
super.initialize(server);
this.server = server;
......
......@@ -72,6 +72,11 @@
url="connection-managers-settings.jsp"
description="${sidebar.connection-managers-settings.descr}" />
<!-- HTTP binding -->
<item id="http-bind" name="${sidebar.http-bind}"
url="http-bind.jsp"
description="${sidebar.http-bind.descr}" />
<!-- Manage updates -->
<item id="manage-updates" name="${sidebar.manage-updates}"
url="manage-updates.jsp"
......
<%@ page import="org.jivesoftware.wildfire.HttpServerManager" %>
<%@ page import="org.jivesoftware.util.ParamUtils" %>
<%@ page import="java.util.Map" %>
<%@ page import="java.util.HashMap" %>
<%--
- $Revision: $
- $Date: $
-
- Copyright (C) 2006 Jive Software. All rights reserved.
-
- This software is published under the terms of the GNU Public License (GPL),
- a copy of which is included in this distribution.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jstl/fmt_rt" prefix="fmt" %>
<%!
Map<String, String> errorMap = new HashMap<String, String>();
HttpServerManager serverManager = HttpServerManager.getInstance();
void handleUpdate(HttpServletRequest request) {
boolean isEnabled = ParamUtils.getBooleanParameter(request, "httpBindEnabled");
if (isEnabled) {
boolean httpPortsDistinct = ParamUtils.getBooleanParameter(request, "httpPortsDistinct",
false);
int requestedPort;
int requestedSecurePort;
if (httpPortsDistinct) {
requestedPort = ParamUtils.getIntParameter(request, "port", -1);
requestedSecurePort = ParamUtils.getIntParameter(request, "securePort", -1);
}
else {
requestedPort = serverManager.getAdminUnsecurePort();
requestedSecurePort = serverManager.getAdminSecurePort();
}
try {
serverManager.setHttpBindPorts(requestedPort, requestedSecurePort);
}
catch (Exception e) {
errorMap.put("port", e.getMessage());
}
}
serverManager.setHttpBindEnabled(isEnabled);
}
%>
<%
if (request.getParameter("update") != null) {
handleUpdate(request);
}
boolean isHttpBindEnabled = serverManager.isHttpBindEnabled();
boolean isHttpBindServerSperate = serverManager.isSeperateHttpBindServerConfigured();
int port = serverManager.getHttpBindUnsecurePort();
int securePort = serverManager.getHttpBindSecurePort();
%>
<html>
<head>
<title>
<fmt:message key="httpbind.settings.title"/>
</title>
<meta name="pageID" content="http-bind"/>
</head>
<body>
<p>
<fmt:message key="httpbind.settings.info"/>
</p>
<form action="http-bind.jsp" method="post">
<div class="jive-contentBoxHeader">
<fmt:message key="httpbind.settings.enabled.legend"/>
</div>
<div class="jive-contentBox">
<table cellpadding="3" cellspacing="0" border="0">
<tbody>
<tr valign="middle">
<td width="1%" nowrap>
<input type="radio" name="httpBindEnabled" value="false" id="rb01"
<%= (!isHttpBindEnabled ? "checked" : "") %>>
</td>
<td width="99%" colspan="2">
<label for="rb01">
<b>
<fmt:message key="httpbind.settings.label_disable"/>
</b> -
<fmt:message key="httpbind.settings.label_disable_info"/>
</label>
</td>
</tr>
<tr valign="middle">
<td width="1%" nowrap>
<input type="radio" name="httpBindEnabled" value="true" id="rb02"
<%= (isHttpBindEnabled ? "checked" : "") %>>
</td>
<td width="99%" colspan="2">
<label for="rb02">
<b>
<fmt:message key="httpbind.settings.label_enable"/>
</b> -
<fmt:message key="httpbind.settings.label_enable_info"/>
</label>
</td>
</tr>
<tr valign="middle">
<td width="1%">
&nbsp;
</td>
<td width="1%" nowrap>
<input type="radio" name="httpPortsDistinct" value="false" id="rb03"
<%= (!isHttpBindServerSperate ? "checked" : "") %>>
</td>
<td width="98%">
<label for="rb03">
<b>
<fmt:message key="httpbind.settings.label_seperate"/>
</b> -
<fmt:message key="httpbind.settings.label_seperate_info"/>
</label>
</td>
</tr>
<tr valign="middle">
<td width="1%">
&nbsp;
</td>
<td width="1%" nowrap>
<input type="radio" name="httpPortsDistinct" value="true" id="rb04"
<%= (isHttpBindServerSperate ? "checked" : "") %>>
</td>
<td width="98%">
<label for="rb04">
<b>
<fmt:message key="httpbind.settings.label_same"/>
</b> -
<fmt:message key="httpbind.settings.label_same_info"/>
</label>
</td>
</tr>
<tr>
<td width="1%">
&nbsp;
</td>
<td colspan="2">
<label for="port">
<fmt:message key="httpbind.settings.vanilla_port"/>
</label>
<input id="port" type="text" size="5" maxlength="10" name="port"
value="<%=port%>" />
</td>
</tr>
<tr>
<td width="1%">
&nbsp;
</td>
<td colspan="2">
<label for="securePort">
<fmt:message key="httpbind.settings.secure_port"/>
</label>
<input id="securePort" type="text" size="5" maxlength="10" name="securePort"
value="<%=securePort%>" />
</td>
</tr>
</tbody>
</table>
<input type="submit" id="settingsUpdate" name="update"
value="<fmt:message key="global.save_settings" />">
</div>
</form>
</body>
</html>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment