Commit 9a338b7a authored by Tom Evans's avatar Tom Evans Committed by tevans

OF-655: Add configurable JMX support (initial); user docs pending

git-svn-id: http://svn.igniterealtime.org/svn/repos/openfire/trunk@13594 b35dd754-fafc-0310-a699-88a17e54d16e
parent 9d9c8887
......@@ -948,6 +948,9 @@ server.props.ssl_valid=Pros\u00edm zadejte platn\u00e9 \u010d\u00edslo SSL portu
server.props.ssl_valid1=obnovte v\u00fdchoz\u00ed
server.props.admin_port=Port administr\u00e1torsk\u00e9 konzole:
server.props.admin_secure_port=Zabezpe\u010den\u00fd port administr\u00e1torsk\u00e9 konzole:
server.props.jmx_enabled=JMX Enabled:
server.props.jmx_secure=JMX Require Admin User:
server.props.jmx_port=JMX Connector Port:
# Server stopped Page
......@@ -2172,6 +2175,12 @@ ports.http_bind.desc_secured=Port pou\u017e\u00edvan\u00fd pro zabezpe\u010den\u
ports.media_proxy=Proxy pro m\u00e9dia v re\u00e1ln\u00e9m \u010dase
ports.media_proxy.desc=Port pou\u017e\u00edvan\u00fd slu\u017ebou proxy, kter\u00fd umo\u017e\u0148uje Jingle spojen\u00ed mezi dv\u011bma entitami \
v s\u00edti XMPP.
ports.flash_cross_domain=Flash Cross Domain
ports.flash_cross_domain.desc=Service that allows Flash clients connect to other hostnames and ports.
ports.jmx_console=JMX Console
ports.jmx_console.desc=The port used by the JMX connector to provide JConsole access to Openfire via RMI.
ports.jmx_console.alt=Requires Openfire admin credentials
ports.secure.alt=This port uses SSL to encrypt traffic over the network
# Media Proxy
......
......@@ -903,6 +903,9 @@ server.props.ssl_valid=Bitte eine g\u00fcltige SSL-Portnummer eingeben oder
server.props.ssl_valid1=die vorgegebene zur\u00fccksetzen
server.props.admin_port=Port der Adminkonsole:
server.props.admin_secure_port=Port der sicheren Adminkonsole:
server.props.jmx_enabled=JMX Enabled:
server.props.jmx_secure=JMX Require Admin User:
server.props.jmx_port=JMX Connector Port:
# Server stopped Page
......@@ -2091,6 +2094,12 @@ ports.http_bind.desc_secured=The port used for secured HTTP client connections.
ports.media_proxy=Real time media proxy
ports.media_proxy.desc=The port used for the proxy service that allows Jingle connections between two entities on \
the XMPP network.
ports.flash_cross_domain=Flash Cross Domain
ports.flash_cross_domain.desc=Service that allows Flash clients connect to other hostnames and ports.
ports.jmx_console=JMX Console
ports.jmx_console.desc=The port used by the JMX connector to provide JConsole access to Openfire via RMI.
ports.jmx_console.alt=Requires Openfire admin credentials
ports.secure.alt=This port uses SSL to encrypt traffic over the network
# Media Proxy
......
......@@ -506,6 +506,15 @@
## 3.8.2
## Added keys: 'httpbind.settings.cors.*'
## Added keys: 'httpbind.settings.xff.*'
## Added key: 'ports.flash_cross_domain'
## Added key: 'ports.flash_cross_domain.desc'
## Added key: 'ports.jmx_console'
## Added key: 'ports.jmx_console.desc'
## Added key: 'ports.jmx_console.alt'
## Added key: 'ports.secure.alt'
## Added key: 'server.props.jmx_enabled'
## Added key: 'server.props.jmx_secure'
## Added key: 'server.props.jmx_port'
# Openfire
......@@ -1533,6 +1542,9 @@ server.props.ssl_valid=Please enter a valid SSL port number or
server.props.ssl_valid1=restore the default
server.props.admin_port=Admin Console Port:
server.props.admin_secure_port=Secure Admin Console Port:
server.props.jmx_enabled=JMX Enabled:
server.props.jmx_secure=JMX Require Admin User:
server.props.jmx_port=JMX Connector Port:
# Server stopped Page
......@@ -2896,6 +2908,10 @@ ports.media_proxy.desc=The port used for the proxy service that allows Jingle co
the XMPP network.
ports.flash_cross_domain=Flash Cross Domain
ports.flash_cross_domain.desc=Service that allows Flash clients connect to other hostnames and ports.
ports.jmx_console=JMX Console
ports.jmx_console.desc=The port used by the JMX connector to provide JConsole access to Openfire via RMI.
ports.jmx_console.alt=Requires Openfire admin credentials
ports.secure.alt=This port uses SSL to encrypt traffic over the network
# Media Proxy
......
......@@ -942,6 +942,9 @@ server.props.ssl_valid=Por favor ingrese un n\u00famero v\u00e1lido para el puer
server.props.ssl_valid1=reestablezca el valor por defecto
server.props.admin_port=Puerto de la Consola de Administraci\u00f3n:
server.props.admin_secure_port=Puerto de la Consola de Administraci\u00f3n Segura:
server.props.jmx_enabled=JMX Enabled:
server.props.jmx_secure=JMX Require Admin User:
server.props.jmx_port=JMX Connector Port:
# Server stopped Page
......@@ -2172,6 +2175,12 @@ ports.http_bind.desc_secured=Puerto utilizado para conexiones seguras de cliente
ports.media_proxy=Proxy de medios en tiempo real
ports.media_proxy.desc=Puerto utilizado por el servicio para permitir conexiones Jingle entre dos entidades de la \
red XMPP.
ports.flash_cross_domain=Flash Cross Domain
ports.flash_cross_domain.desc=Service that allows Flash clients connect to other hostnames and ports.
ports.jmx_console=JMX Console
ports.jmx_console.desc=The port used by the JMX connector to provide JConsole access to Openfire via RMI.
ports.jmx_console.alt=Requires Openfire admin credentials
ports.secure.alt=This port uses SSL to encrypt traffic over the network
# Media Proxy
......
......@@ -800,6 +800,9 @@ server.props.ssl_valid = Veuillez saisir un num\u00E9ro de port SSL valide ou
server.props.ssl_valid1 = restaurer les param\u00E8tres par d\u00E9faut
server.props.admin_port = Port de la Console d'Administration \:
server.props.admin_secure_port = Port S\u00E9curis\u00E9 de la Console d'Administration \:
server.props.jmx_enabled=JMX Enabled:
server.props.jmx_secure=JMX Require Admin User:
server.props.jmx_port=JMX Connector Port:
# Server stopped Page
server.stopped.title_restarting = R\u00E9d\u00E9marrage du Serveur
server.stopped.title_stopped = Serveur arr\u00EAt\u00E9
......@@ -1758,6 +1761,12 @@ ports.http_bind.desc_secured=The port used for secured HTTP client connections.
ports.media_proxy=Real time media proxy
ports.media_proxy.desc=The port used for the proxy service that allows Jingle connections between two entities on \
the XMPP network.
ports.flash_cross_domain=Flash Cross Domain
ports.flash_cross_domain.desc=Service that allows Flash clients connect to other hostnames and ports.
ports.jmx_console=JMX Console
ports.jmx_console.desc=The port used by the JMX connector to provide JConsole access to Openfire via RMI.
ports.jmx_console.alt=Requires Openfire admin credentials
ports.secure.alt=This port uses SSL to encrypt traffic over the network
# Media Proxy
......
......@@ -974,6 +974,9 @@ server.props.ssl_valid=\u9069\u5207\u306aSSL\u30dd\u30fc\u30c8\u756a\u53f7\u3092
server.props.ssl_valid1=\u3082\u3057\u304f\u306f\u30c7\u30d5\u30a9\u30eb\u30c8\u5024\u3092\u518d\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002
server.props.admin_port=\u7ba1\u7406\u30b3\u30f3\u30bd\u30fc\u30eb\u7528\u30dd\u30fc\u30c8:
server.props.admin_secure_port=\u30bb\u30ad\u30e5\u30a2\u30fc\u306a\u7ba1\u7406\u30b3\u30f3\u30bd\u30fc\u30eb\u7528\u30dd\u30fc\u30c8:
server.props.jmx_enabled=JMX Enabled:
server.props.jmx_secure=JMX Require Admin User:
server.props.jmx_port=JMX Connector Port:
# Server stopped Page
......@@ -2186,6 +2189,12 @@ ports.http_bind.desc_secured=\u30bb\u30ad\u30e5\u30a2\u30fc\u306aHTTP\u30af\u30e
ports.media_proxy=\u30ea\u30a2\u30eb\u30bf\u30a4\u30e0\u30e1\u30c7\u30a3\u30a2\u30d7\u30ed\u30ad\u30b7\u30fc
ports.media_proxy.desc=XMPP\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u4e0a\u3067\u30012\u3064\u306e\u30a8\u30f3\u30c6\u30a3\u30c6\u30a3\u306e\u9593\u3067\u306eJingle\u63a5\u7d9a\u3092\u8a31\u53ef\u3057\u3066\u3044\u308b\
\u30d7\u30ed\u30ad\u30b7\u30fc\u30b5\u30fc\u30d3\u30b9\u304c\u4f7f\u7528\u3059\u308b\u30dd\u30fc\u30c8\u3067\u3059\u3002
ports.flash_cross_domain=Flash Cross Domain
ports.flash_cross_domain.desc=Service that allows Flash clients connect to other hostnames and ports.
ports.jmx_console=JMX Console
ports.jmx_console.desc=The port used by the JMX connector to provide JConsole access to Openfire via RMI.
ports.jmx_console.alt=Requires Openfire admin credentials
ports.secure.alt=This port uses SSL to encrypt traffic over the network
# Media Proxy
......
......@@ -902,6 +902,9 @@ server.props.ssl_valid=Geef een geldig SSL poortnummer in of
server.props.ssl_valid1=ga terug naar de standaardwaarde
server.props.admin_port=Poort van de beheerconsole:
server.props.admin_secure_port=Beveiligde poort van de beheerconsole:
server.props.jmx_enabled=JMX Enabled:
server.props.jmx_secure=JMX Require Admin User:
server.props.jmx_port=JMX Connector Port:
# Server stopped Page
......@@ -2092,6 +2095,12 @@ ports.http_bind.desc_secured=The port used for secured HTTP client connections.
ports.media_proxy=Real time media proxy
ports.media_proxy.desc=The port used for the proxy service that allows Jingle connections between two entities on \
the XMPP network.
ports.flash_cross_domain=Flash Cross Domain
ports.flash_cross_domain.desc=Service that allows Flash clients connect to other hostnames and ports.
ports.jmx_console=JMX Console
ports.jmx_console.desc=The port used by the JMX connector to provide JConsole access to Openfire via RMI.
ports.jmx_console.alt=Requires Openfire admin credentials
ports.secure.alt=This port uses SSL to encrypt traffic over the network
# Media Proxy
......
......@@ -898,6 +898,9 @@ server.props.ssl_valid=Prosz\u0119 poda\u0107 poprawny numer portu SSL lub
server.props.ssl_valid1=przywr\u00f3ci\u0107 domy\u015blny
server.props.admin_port=Port konsoli administracyjnej:
server.props.admin_secure_port=Bezpieczny port konsoli administracyjnej:
server.props.jmx_enabled=JMX Enabled:
server.props.jmx_secure=JMX Require Admin User:
server.props.jmx_port=JMX Connector Port:
# Server stopped Page
......@@ -2073,6 +2076,12 @@ ports.http_bind.desc_secured=The port used for secured HTTP client connections.
ports.media_proxy=Real time media proxy
ports.media_proxy.desc=The port used for the proxy service that allows Jingle connections between two entities on \
the XMPP network.
ports.flash_cross_domain=Flash Cross Domain
ports.flash_cross_domain.desc=Service that allows Flash clients connect to other hostnames and ports.
ports.jmx_console=JMX Console
ports.jmx_console.desc=The port used by the JMX connector to provide JConsole access to Openfire via RMI.
ports.jmx_console.alt=Requires Openfire admin credentials
ports.secure.alt=This port uses SSL to encrypt traffic over the network
# Media Proxy
......
......@@ -946,6 +946,9 @@ server.props.ssl_valid1=restaure o padr\u00e3o
server.props.admin_port=Porta do Console de Administra\u00e7\u00e3o:
server.props.admin_secure_port=Porta Segura do Console de Administra\u00e7\u00e3o:
server.props.ssl_port=Porta do Cliente SSL:
server.props.jmx_enabled=JMX Enabled:
server.props.jmx_secure=JMX Require Admin User:
server.props.jmx_port=JMX Connector Port:
# Server stopped Page
......@@ -2172,6 +2175,12 @@ ports.http_bind.desc_secured=Porta utilizada para conex\u00e3o segura a clientes
ports.media_proxy=Media Proxy
ports.media_proxy.desc=Porta utilizada para conex\u00e3o ao servi\u00e7o de proxy para conex\u00f5es Jingle\
na rede XMPP.
ports.flash_cross_domain=Flash Cross Domain
ports.flash_cross_domain.desc=Service that allows Flash clients connect to other hostnames and ports.
ports.jmx_console=JMX Console
ports.jmx_console.desc=The port used by the JMX connector to provide JConsole access to Openfire via RMI.
ports.jmx_console.alt=Requires Openfire admin credentials
ports.secure.alt=This port uses SSL to encrypt traffic over the network
# Media Proxy
......
......@@ -940,6 +940,9 @@ server.props.ssl_valid=Pros\u00edm, zadajte platn\u00e9 \u010d\u00edslo SSL port
server.props.ssl_valid1=obnovi\u0165 \u0161tandardn\u00e9
server.props.admin_port=Port konzoly spr\u00e1vcu:
server.props.admin_secure_port=Port zabezpe\u010denej konzoly spr\u00e1vcu:
server.props.jmx_enabled=JMX Enabled:
server.props.jmx_secure=JMX Require Admin User:
server.props.jmx_port=JMX Connector Port:
# Server stopped Page
......@@ -2108,6 +2111,10 @@ ports.media_proxy=Multimedi\u00e1lny proxy realtime media
ports.media_proxy.desc=Tento port pou\u017e\u00edva proxy slu\u017eba, ktor\u00e1 umo\u017e\u0148uje spojenia Jingle medzi dvomi entitami v sieti XMPP.
ports.flash_cross_domain=Medzidom\u00e9nov\u00fd Flash
ports.flash_cross_domain.desc=Slu\u017eba, ktor\u00e1 umo\u017e\u0148uje Flash klientom prip\u00e1ja\u0165 sa k in\u00fdm strojom pod\u013ea n\u00e1zvu a portom.
ports.jmx_console=JMX Console
ports.jmx_console.desc=The port used by the JMX connector to provide JConsole access to Openfire via RMI.
ports.jmx_console.alt=Requires Openfire admin credentials
ports.secure.alt=This port uses SSL to encrypt traffic over the network
# Media Proxy
......
......@@ -890,6 +890,9 @@ server.props.ssl_valid=\u8bf7\u8f93\u5165\u6709\u6548\u7684 SSL \u7aef\u53e3\u53
server.props.ssl_valid1=\u6062\u590d\u7f3a\u7701\u503c
server.props.admin_port=\u7ba1\u7406\u63a7\u5236\u53f0\u7aef\u53e3\uff1a
server.props.admin_secure_port=\u5b89\u5168\u7ba1\u7406\u63a7\u5236\u53f0\u7aef\u53e3:
server.props.jmx_enabled=JMX Enabled:
server.props.jmx_secure=JMX Require Admin User:
server.props.jmx_port=JMX Connector Port:
# Server stopped Page
......@@ -1956,6 +1959,12 @@ ports.http_bind.desc_unsecured=\u4f7f\u7528\u4e0d\u5b89\u5168\u7684HTTP\u5ba2\u6
ports.http_bind.desc_secured=\u4f7f\u7528\u5b89\u5168\u7684HTTP\u5ba2\u6237\u7aef\u8fde\u63a5\u7aef\u53e3
ports.media_proxy=\u5b9e\u65f6\u5a92\u4f53\u4ee3\u7406\u670d\u52a1\u5668
ports.media_proxy.desc=\u4ee3\u7406\u670d\u52a1\u4f7f\u7528\u7684\u7aef\u53e3\u5141\u8bb8\u5728XMPP\u7f51\u7edc\u4e0a\u4e24\u4e2a\u5b9e\u4f53\u4e4b\u95f4\u8fdb\u884cJingle\u8fde\u63a5.
ports.flash_cross_domain=Flash Cross Domain
ports.flash_cross_domain.desc=Service that allows Flash clients connect to other hostnames and ports.
ports.jmx_console=JMX Console
ports.jmx_console.desc=The port used by the JMX connector to provide JConsole access to Openfire via RMI.
ports.jmx_console.alt=Requires Openfire admin credentials
ports.secure.alt=This port uses SSL to encrypt traffic over the network
# Media Proxy
......
package org.jivesoftware.openfire;
import java.lang.management.ManagementFactory;
import java.rmi.registry.Registry;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import javax.management.remote.JMXAuthenticator;
import javax.management.remote.JMXPrincipal;
import javax.management.remote.JMXServiceURL;
import javax.security.auth.Subject;
import org.eclipse.jetty.jmx.ConnectorServer;
import org.eclipse.jetty.jmx.MBeanContainer;
import org.jivesoftware.openfire.admin.AdminManager;
import org.jivesoftware.openfire.auth.AuthFactory;
import org.jivesoftware.util.JiveGlobals;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Manages the JMX configuration for Openfire.
*
* @author Tom Evans
*/
public class JMXManager {
private static final Logger Log = LoggerFactory.getLogger(JMXManager.class);
private static final String XMPP_JMX_ENABLED = "xmpp.jmx.enabled";
private static final String XMPP_JMX_SECURE = "xmpp.jmx.secure";
private static final String XMPP_JMX_PORT = "xmpp.jmx.port";
public static final int DEFAULT_PORT = Registry.REGISTRY_PORT;
private static JMXManager instance = null;
private MBeanContainer mbContainer;
private ConnectorServer jmxServer;
/**
* Returns true if the JMX connector is configured to require
* Openfire admin credentials. This option can be configured via
* the admin console or by setting the following system property:
* <pre>
* xmpp.jmx.secure=false (default: true)
* </pre>
*
* @return true if the JMX connector requires authentication
*/
public static boolean isSecure() {
return JiveGlobals.getBooleanProperty(XMPP_JMX_SECURE, true);
}
public static void setSecure(boolean secure) {
JiveGlobals.setProperty("xmpp.jmx.secure", String.valueOf(secure));
}
/**
* Returns the port number for the JMX connector. This option can
* be configured via the admin console or by setting the following
* system property:
* <pre>
* xmpp.jmx.port=[port] (default: 1099)
* </pre>
*
* @return Port number for the JMX connector
*/
public static int getPort() {
return JiveGlobals.getIntProperty(XMPP_JMX_PORT, DEFAULT_PORT);
}
public static void setPort(int port) {
JiveGlobals.setProperty("xmpp.jmx.port", String.valueOf(port));
}
/**
* Returns true if JMX support is enabled. This option can be
* configured via the admin console or by setting the following
* system property:
* <pre>
* xmpp.jmx.enabled=true (default: false)
* </pre>
*
* @return true if JMX support is enabled
*/
public static boolean isEnabled() {
return JiveGlobals.getBooleanProperty(XMPP_JMX_ENABLED, false);
}
public static void setEnabled(boolean enabled) {
JiveGlobals.setProperty("xmpp.jmx.enabled", String.valueOf(enabled));
}
public static JMXManager getInstance() {
if (instance == null) {
instance = new JMXManager();
if (isEnabled()) {
instance.start();
}
}
return instance;
}
private void start() {
setContainer(new MBeanContainer(ManagementFactory.getPlatformMBeanServer()));
getContainer().addBean(org.eclipse.jetty.util.log.Log.getLog());
int jmxPort = JMXManager.getPort();
String jmxUrl = "/jndi/rmi://localhost:" + jmxPort + "/jmxrmi";
Map<String, Object> env = new HashMap<String, Object>();
if (JMXManager.isSecure()) {
env.put("jmx.remote.authenticator", new JMXAuthenticator() {
public Subject authenticate(Object credentials) {
if (!(credentials instanceof String[])) {
if (credentials == null) {
throw new SecurityException("Credentials required");
}
throw new SecurityException("Credentials should be String[]");
}
final String[] aCredentials = (String[]) credentials;
if (aCredentials.length < 2) {
throw new SecurityException("Credentials should have at least two elements");
}
String username = (String) aCredentials[0];
String password = (String) aCredentials[1];
try {
AuthFactory.authenticate(username, password);
} catch (Exception ex) {
Log.error("Authentication failed for " + username);
throw new SecurityException();
}
if (AdminManager.getInstance().isUserAdmin(username, true)) {
return new Subject(true,
Collections.singleton(new JMXPrincipal(username)),
Collections.EMPTY_SET,
Collections.EMPTY_SET);
} else {
Log.error("Authorization failed for " + username);
throw new SecurityException();
}
}
});
}
try {
jmxServer = new ConnectorServer(new JMXServiceURL("rmi", null, jmxPort, jmxUrl),
env, "org.eclipse.jetty.jmx:name=rmiconnectorserver");
jmxServer.start();
} catch (Exception e) {
Log.error("Failed to start JMX connector", e);
}
}
public MBeanContainer getContainer() {
return mbContainer;
}
public void setContainer(MBeanContainer mbContainer) {
this.mbContainer = mbContainer;
}
}
......@@ -20,11 +20,22 @@
package org.jivesoftware.openfire.container;
import java.io.File;
import java.lang.management.ManagementFactory;
import java.security.KeyStore;
import java.security.cert.X509Certificate;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.management.remote.JMXAuthenticator;
import javax.management.remote.JMXPrincipal;
import javax.management.remote.JMXServiceURL;
import javax.security.auth.Subject;
import org.eclipse.jetty.http.ssl.SslContextFactory;
import org.eclipse.jetty.jmx.ConnectorServer;
import org.eclipse.jetty.jmx.MBeanContainer;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
......@@ -36,7 +47,10 @@ import org.eclipse.jetty.server.ssl.SslSelectChannelConnector;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.eclipse.jetty.webapp.WebAppContext;
import org.jivesoftware.openfire.JMXManager;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.admin.AdminManager;
import org.jivesoftware.openfire.auth.AuthFactory;
import org.jivesoftware.openfire.net.SSLConfig;
import org.jivesoftware.util.CertificateEventListener;
import org.jivesoftware.util.CertificateManager;
......@@ -95,6 +109,11 @@ public class AdminConsolePlugin implements Plugin {
adminPort = JiveGlobals.getXMLProperty("adminConsole.port", 9090);
adminSecurePort = JiveGlobals.getXMLProperty("adminConsole.securePort", 9091);
adminServer = new Server();
if (JMXManager.isEnabled()) {
JMXManager jmx = JMXManager.getInstance();
adminServer.getContainer().addEventListener(jmx.getContainer());
adminServer.addBean(jmx.getContainer());
}
final QueuedThreadPool tp = new QueuedThreadPool(254);
tp.setName("Jetty-QTP-AdminConsole");
adminServer.setThreadPool(tp);
......@@ -109,6 +128,7 @@ public class AdminConsolePlugin implements Plugin {
String bindInterface = getBindInterface();
httpConnector.setHost(bindInterface);
httpConnector.setPort(adminPort);
httpConnector.setStatsOn(JMXManager.isEnabled());
adminServer.addConnector(httpConnector);
}
......@@ -135,7 +155,7 @@ public class AdminConsolePlugin implements Plugin {
String bindInterface = getBindInterface();
httpsConnector.setHost(bindInterface);
httpsConnector.setPort(adminSecurePort);
httpsConnector.setStatsOn(JMXManager.isEnabled());
adminServer.addConnector(httpsConnector);
sslEnabled = true;
......@@ -168,7 +188,7 @@ public class AdminConsolePlugin implements Plugin {
logAdminConsolePorts();
}
/**
/**
* Shuts down the Jetty server.
* */
public void shutdown() {
......
......@@ -41,6 +41,7 @@ import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.eclipse.jetty.webapp.WebAppContext;
import org.jivesoftware.openfire.JMXManager;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.net.SSLConfig;
import org.jivesoftware.util.CertificateEventListener;
......@@ -118,7 +119,7 @@ public final class HttpBindManager {
private HttpSessionManager httpSessionManager;
private ContextHandlerCollection contexts;
// is all orgin allowed flag
private boolean allowAllOrigins;
......@@ -258,6 +259,7 @@ public final class HttpBindManager {
connector.setHostHeader(hostName);
}
}
connector.setStatsOn(JMXManager.isEnabled());
}
private String getBindInterface() {
......@@ -478,6 +480,11 @@ public final class HttpBindManager {
*/
private synchronized void configureHttpBindServer(int port, int securePort) {
httpBindServer = new Server();
if (JMXManager.isEnabled()) {
JMXManager jmx = JMXManager.getInstance();
httpBindServer.getContainer().addEventListener(jmx.getContainer());
httpBindServer.addBean(jmx.getContainer());
}
final QueuedThreadPool tp = new QueuedThreadPool(
JiveGlobals.getIntProperty(HTTP_BIND_THREADS, HTTP_BIND_THREADS_DEFAULT));
tp.setName("Jetty-QTP-BOSH");
......
......@@ -21,9 +21,11 @@
package org.jivesoftware.openfire.spi;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.UnknownHostException;
import java.security.KeyStore;
import java.security.KeyStoreException;
......@@ -38,21 +40,32 @@ import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import javax.management.JMException;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import org.apache.mina.common.ByteBuffer;
import org.apache.mina.common.ExecutorThreadModel;
import org.apache.mina.common.IoHandler;
import org.apache.mina.common.IoService;
import org.apache.mina.common.IoServiceConfig;
import org.apache.mina.common.IoServiceListener;
import org.apache.mina.common.IoSession;
import org.apache.mina.common.SimpleByteBufferAllocator;
import org.apache.mina.common.ThreadModel;
import org.apache.mina.filter.SSLFilter;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.executor.ExecutorFilter;
import org.apache.mina.integration.jmx.IoServiceManager;
import org.apache.mina.integration.jmx.IoSessionManager;
import org.apache.mina.transport.socket.nio.SocketAcceptor;
import org.apache.mina.transport.socket.nio.SocketAcceptorConfig;
import org.apache.mina.transport.socket.nio.SocketSessionConfig;
import org.jivesoftware.openfire.ConnectionManager;
import org.jivesoftware.openfire.JMXManager;
import org.jivesoftware.openfire.PacketDeliverer;
import org.jivesoftware.openfire.PacketRouter;
import org.jivesoftware.openfire.RoutingTable;
......@@ -217,7 +230,7 @@ public class ConnectionManagerImpl extends BasicModule implements ConnectionMana
// Start multiplexers socket unless it's been disabled.
if (isConnectionManagerListenerEnabled()) {
// Create SocketAcceptor with correct number of processors
multiplexerSocketAcceptor = buildSocketAcceptor();
multiplexerSocketAcceptor = buildSocketAcceptor("multiplexer");
// Customize Executor that will be used by processors to process incoming stanzas
ExecutorThreadModel threadModel = ExecutorThreadModel.getInstance("connectionManager");
int eventThreads = JiveGlobals.getIntProperty("xmpp.multiplex.processing.threads", 16);
......@@ -280,7 +293,7 @@ public class ConnectionManagerImpl extends BasicModule implements ConnectionMana
// Start components socket unless it's been disabled.
if (isComponentListenerEnabled() && componentAcceptor == null) {
// Create SocketAcceptor with correct number of processors
componentAcceptor = buildSocketAcceptor();
componentAcceptor = buildSocketAcceptor("component");
// Customize Executor that will be used by processors to process incoming stanzas
ExecutorThreadModel threadModel = ExecutorThreadModel.getInstance("component");
int eventThreads = JiveGlobals.getIntProperty("xmpp.component.processing.threads", 16);
......@@ -344,7 +357,7 @@ public class ConnectionManagerImpl extends BasicModule implements ConnectionMana
// Start clients plain socket unless it's been disabled.
if (isClientListenerEnabled()) {
// Create SocketAcceptor with correct number of processors
socketAcceptor = buildSocketAcceptor();
socketAcceptor = buildSocketAcceptor("client");
// Customize Executor that will be used by processors to process incoming stanzas
ExecutorThreadModel threadModel = ExecutorThreadModel.getInstance("client");
int eventThreads = JiveGlobals.getIntProperty("xmpp.client.processing.threads", 16);
......@@ -412,7 +425,7 @@ public class ConnectionManagerImpl extends BasicModule implements ConnectionMana
String algorithm = JiveGlobals.getProperty("xmpp.socket.ssl.algorithm", "TLS");
try {
// Create SocketAcceptor with correct number of processors
sslSocketAcceptor = buildSocketAcceptor();
sslSocketAcceptor = buildSocketAcceptor("client_ssl");
// Customize Executor that will be used by processors to process incoming stanzas
int eventThreads = JiveGlobals.getIntProperty("xmpp.client_ssl.processing.threads", 16);
ExecutorFilter executorFilter = new ExecutorFilter();
......@@ -810,7 +823,7 @@ public class ConnectionManagerImpl extends BasicModule implements ConnectionMana
restartClientSSLListeners();
}
private SocketAcceptor buildSocketAcceptor() {
private SocketAcceptor buildSocketAcceptor(String name) {
SocketAcceptor socketAcceptor;
// Create SocketAcceptor with correct number of processors
int ioThreads = JiveGlobals.getIntProperty("xmpp.processor.count", Runtime.getRuntime().availableProcessors());
......@@ -842,9 +855,53 @@ public class ConnectionManagerImpl extends BasicModule implements ConnectionMana
}
socketSessionConfig.setTcpNoDelay(
JiveGlobals.getBooleanProperty("xmpp.socket.tcp-nodelay", socketSessionConfig.isTcpNoDelay()));
if (JMXManager.isEnabled()) {
configureJMX(socketAcceptor, name);
}
return socketAcceptor;
}
private void configureJMX(SocketAcceptor acceptor, String suffix) {
final String prefix = IoServiceManager.class.getPackage().getName();
// monitor the IoService
try {
IoServiceManager mbean = new IoServiceManager(acceptor);
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
ObjectName name = new ObjectName(prefix + ":type=SocketAcceptor,name=" + suffix);
mbs.registerMBean( mbean, name );
mbean.startCollectingStats(JiveGlobals.getIntProperty("xmpp.socket.jmx.interval", 60000));
} catch (JMException ex) {
Log.warn("Failed to register MINA acceptor mbean (JMX): " + ex);
}
// optionally register IoSession mbeans (one per session)
if (JiveGlobals.getBooleanProperty("xmpp.socket.jmx.sessions", false)) {
acceptor.addListener(new IoServiceListener() {
public void sessionCreated(IoSession session) {
try {
IoSessionManager mbean = new IoSessionManager(session);
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
ObjectName name = new ObjectName(prefix + ":type=IoSession,name=" +
session.getRemoteAddress().toString().replace(':', '/'));
mbs.registerMBean(mbean, name);
} catch(JMException ex) {
Log.warn("Failed to register MINA session mbean (JMX): " + ex);
}
}
public void sessionDestroyed(IoSession session) {
try {
ObjectName name = new ObjectName(prefix + ":type=IoSession,name=" +
session.getRemoteAddress().toString().replace(':', '/'));
ManagementFactory.getPlatformMBeanServer().unregisterMBean(name);
} catch(JMException ex) {
Log.warn("Failed to unregister MINA session mbean (JMX): " + ex);
}
}
public void serviceActivated(IoService is, SocketAddress sa, IoHandler ih, IoServiceConfig isc) { }
public void serviceDeactivated(IoService is, SocketAddress sa, IoHandler ih, IoServiceConfig isc) { }
});
}
}
// #####################################################################
// Module management
// #####################################################################
......
......@@ -44,6 +44,13 @@
Hazelcast Clustering Plugin Changelog
</h1>
<p><b>1.0.5</b> -- March 26, 2013</p>
<p>JMX Support (<a href="http://issues.igniterealtime.org/browse/OF-655">OF-655</a>)</p>
<ul>
<li>Optionally enable JMX instrumentation for Hazelcast if JMX is enabled for Openfire (via the admin console).</li>
<li>Updated minimum server version to Openfire 3.8.2 (release pending)</li>
</ul>
<p><b>1.0.4</b> -- February 6, 2013</p>
<p>Performance-related enhancements:</p>
<ul>
......
......@@ -5,7 +5,7 @@
<name>${plugin.name}</name>
<description>${plugin.description}</description>
<author>Tom Evans</author>
<version>1.0.4</version>
<date>02/06/2013</date>
<minServerVersion>3.8.0</minServerVersion>
<version>1.0.5</version>
<date>03/26/2013</date>
<minServerVersion>3.8.2</minServerVersion>
</plugin>
......@@ -179,6 +179,10 @@ property (described below), or in the classpath of your own custom plugin.</li>
<li><i>hazelcast.config.xml.directory</i> ({OPENFIRE_HOME}/conf): Directory
that will be added to the plugin's classpath. This allows a custom Hazelcast
configuration file to be located outside the Openfire home directory.</li>
<li><i>hazelcast.config.jmx.enabled</i> (false): Enables JMX support for
the Hazelcast cluster if JMX has been enabled via the Openfire admin console.
Refer to the <a href="http://www.hazelcast.com/docs/2.5/manual/multi_html/ch06.html">
Hazelcast JMX docs</a> for additional information.</li>
</ol>
</p>
<p>
......
......@@ -34,6 +34,7 @@ import java.util.concurrent.TimeoutException;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import org.jivesoftware.openfire.JMXManager;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.cluster.ClusterNodeInfo;
import org.jivesoftware.openfire.cluster.NodeID;
......@@ -76,6 +77,8 @@ public class ClusteredCacheFactory implements CacheFactoryStrategy {
JiveGlobals.getLongProperty("hazelcast.startup.retry.count", 1);
private static final String HAZELCAST_CONFIG_FILE =
JiveGlobals.getProperty("hazelcast.config.xml.filename", "hazelcast-cache-config.xml");
private static final boolean HAZELCAST_JMX_ENABLED =
JiveGlobals.getBooleanProperty("hazelcast.config.jmx.enabled", false);
private static Logger logger = LoggerFactory.getLogger(ClusteredCacheFactory.class);
......@@ -120,6 +123,10 @@ public class ClusteredCacheFactory implements CacheFactoryStrategy {
try {
Config config = new ClasspathXmlConfig(HAZELCAST_CONFIG_FILE);
config.setInstanceName("openfire");
if (JMXManager.isEnabled() && HAZELCAST_JMX_ENABLED) {
config.setProperty("hazelcast.jmx", "true");
config.setProperty("hazelcast.jmx.detailed", "true");
}
hazelcast = Hazelcast.newHazelcastInstance(config);
cluster = hazelcast.getCluster();
......
......@@ -454,7 +454,7 @@
<% if (!CertificateManager.isRSACertificate(SSLConfig.getKeyStore(), XMPPServer.getInstance().getServerInfo().getXMPPDomain()) || LocalClientSession.getTLSPolicy() == org.jivesoftware.openfire.Connection.TLSPolicy.disabled) { %>
<td><img src="images/blank.gif" width="1" height="1" alt=""/></td>
<% } else { %>
<td><img src="images/lock.gif" width="16" height="16" border="0" alt=""/></td>
<td><img src="images/lock.gif" width="16" height="16" border="0" alt="<fmt:message key="ports.secure.alt" />" title="<fmt:message key="ports.secure.alt" />"/></td>
<% } %>
<% } catch (Exception e) { %>
<td><img src="images/blank.gif" width="1" height="1" alt=""/></td>
......@@ -474,7 +474,7 @@
<tr>
<td><%= "0.0.0.0".equals(address.getHostName()) ? LocaleUtils.getLocalizedString("ports.all_ports") : address.getHostName() %></td>
<td><%= address.getPort() %></td>
<td><img src="images/lock.gif" width="16" height="16" border="0" alt=""/></td>
<td><img src="images/lock.gif" width="16" height="16" border="0" alt="<fmt:message key="ports.secure.alt" />" title="<fmt:message key="ports.secure.alt" />"/></td>
<td><fmt:message key="ports.client_to_server" /></td>
<td><fmt:message key="ports.client_to_server.desc_old_ssl">
<fmt:param value="<a href='ssl-settings.jsp'>" />
......@@ -490,7 +490,7 @@
<td><%= interfaceName == null ? LocaleUtils.getLocalizedString("ports.all_ports") : serverPort.getIPAddress() %></td>
<td><%= serverPort.getPort() %></td>
<% if (JiveGlobals.getBooleanProperty("xmpp.server.tls.enabled", true)) { %>
<td><img src="images/lock.gif" width="16" height="16" border="0" alt=""/></td>
<td><img src="images/lock.gif" width="16" height="16" border="0" alt="<fmt:message key="ports.secure.alt" />" title="<fmt:message key="ports.secure.alt" />"/></td>
<% } else { %>
<td><img src="images/blank.gif" width="1" height="1" alt=""/></td>
<% } %>
......@@ -514,7 +514,7 @@
<% if (LocalConnectionMultiplexerSession.getTLSPolicy() == org.jivesoftware.openfire.Connection.TLSPolicy.disabled) { %>
<td><img src="images/blank.gif" width="1" height="1" alt=""></td>
<% } else { %>
<td><img src="images/lock.gif" width="16" height="16" border="0" alt=""/></td>
<td><img src="images/lock.gif" width="16" height="16" border="0" alt="<fmt:message key="ports.secure.alt" />" title="<fmt:message key="ports.secure.alt" />"/></td>
<% } %>
<td><fmt:message key="ports.connection_manager" /></td>
<td><fmt:message key="ports.connection_manager.desc">
......@@ -552,7 +552,7 @@
<tr>
<td><%= adminConsolePlugin.getBindInterface() == null ? LocaleUtils.getLocalizedString("ports.all_ports") : adminConsolePlugin.getBindInterface() %></td>
<td><%= adminConsolePlugin.getAdminSecurePort() %></td>
<td><img src="images/lock.gif" width="16" height="16" border="0" alt=""/></td>
<td><img src="images/lock.gif" width="16" height="16" border="0" alt="<fmt:message key="ports.secure.alt" />" title="<fmt:message key="ports.secure.alt" />"/></td>
<td><fmt:message key="ports.admin_console" /></td>
<td><fmt:message key="ports.admin_console.desc_secured" /></td>
</tr>
......@@ -588,7 +588,7 @@
<tr>
<td><%= interfaceName == null ? LocaleUtils.getLocalizedString("ports.all_ports") : interfaceName %></td>
<td><%= httpBindManager.getHttpBindSecurePort() %></td>
<td><img src="images/lock.gif" width="16" height="16" border="0" alt=""/></td>
<td><img src="images/lock.gif" width="16" height="16" border="0" alt="<fmt:message key="ports.secure.alt" />" title="<fmt:message key="ports.secure.alt" />"/></td>
<td><fmt:message key="ports.http_bind" /></td>
<td><fmt:message key="ports.http_bind.desc_secured" /></td>
</tr>
......@@ -612,6 +612,21 @@
<td><fmt:message key="ports.flash_cross_domain" /></td>
<td><fmt:message key="ports.flash_cross_domain.desc" /></td>
</tr>
<%
if (JMXManager.isEnabled()) {
%>
<tr>
<td><%= interfaceName == null ? LocaleUtils.getLocalizedString("ports.all_ports") : interfaceName %></td>
<td><%= JMXManager.getPort() %></td>
<td><% if (JMXManager.isSecure()) {
%><img src="images/user.gif" width="16" height="16" border="0" alt="<fmt:message key="ports.jmx_console.alt" />" title="<fmt:message key="ports.jmx_console.alt" />"/><%
} else {
%><img src="images/blank.gif" width="1" height="1" alt=""><% }
%></td>
<td><fmt:message key="ports.jmx_console" /></td>
<td><fmt:message key="ports.jmx_console.desc" /></td>
</tr>
<% } %>
</tbody>
</table>
</div>
......
......@@ -21,6 +21,7 @@
org.jivesoftware.util.ParamUtils,
org.jivesoftware.openfire.ConnectionManager,
org.jivesoftware.openfire.XMPPServer,
org.jivesoftware.openfire.JMXManager,
java.net.InetAddress,
java.util.HashMap"
%>
......@@ -45,6 +46,9 @@
boolean sslEnabled = ParamUtils.getBooleanParameter(request, "sslEnabled");
int componentPort = ParamUtils.getIntParameter(request, "componentPort", -1);
int serverPort = ParamUtils.getIntParameter(request, "serverPort", -1);
boolean jmxEnabled = ParamUtils.getBooleanParameter(request, "jmxEnabled");
boolean jmxSecure = ParamUtils.getBooleanParameter(request, "jmxSecure");
int jmxPort = ParamUtils.getIntParameter(request, "jmxPort", -1);
boolean save = request.getParameter("save") != null;
boolean defaults = request.getParameter("defaults") != null;
boolean cancel = request.getParameter("cancel") != null;
......@@ -63,6 +67,9 @@
embeddedPort = 9090;
embeddedSecurePort = 9091;
sslEnabled = true;
jmxEnabled = false;
jmxSecure = true;
jmxPort = JMXManager.DEFAULT_PORT;
save = true;
}
......@@ -106,6 +113,9 @@
errors.put("portsEqual", "");
}
}
if (jmxPort < 1 && jmxEnabled) {
errors.put("jmxPort", "");
}
if (errors.size() == 0) {
boolean needRestart = false;
if (!serverName.equals(server.getServerInfo().getXMPPDomain())) {
......@@ -125,6 +135,10 @@
JiveGlobals.setXMLProperty("adminConsole.securePort", String.valueOf(embeddedSecurePort));
needRestart = true;
}
JMXManager.setEnabled(jmxEnabled);
JMXManager.setSecure(jmxSecure);
JMXManager.setPort(jmxPort);
// Log the event
webManager.logEvent("edit server properties", "serverName = "+serverName+"\nport = "+port+"\nsslPort = "+sslPort+"\ncomponentPort = "+componentPort+"\nserverPort = "+serverPort+"\nembeddedPort = "+embeddedPort+"\nembeddedSecurePort = "+embeddedSecurePort);
if (needRestart) {
......@@ -149,6 +163,9 @@
embeddedSecurePort = Integer.parseInt(JiveGlobals.getXMLProperty("adminConsole.securePort"));
} catch (Exception ignored) {
}
jmxEnabled = JMXManager.isEnabled();
jmxSecure = JMXManager.isSecure();
jmxPort = JMXManager.getPort();
}
%>
......@@ -356,6 +373,73 @@
</td>
</tr>
<% } %>
<tr>
<td class="c1">
<fmt:message key="server.props.jmx_enabled" />
</td>
<td class="c2">
<table cellpadding="0" cellspacing="0" border="0">
<tbody>
<tr>
<td>
<input type="radio" name="jmxEnabled" value="true" <%= (jmxEnabled ? "checked" : "") %>
id="JMX01">
</td>
<td><label for="JMX01"><fmt:message key="server.props.enable" /></label></td>
</tr>
<tr>
<td>
<input type="radio" name="jmxEnabled" value="false" <%= (!jmxEnabled ? "checked" : "") %>
id="JMX02">
</td>
<td><label for="JMX02"><fmt:message key="server.props.disable" /></label></td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td class="c1">
<fmt:message key="server.props.jmx_secure" />
</td>
<td class="c2">
<table cellpadding="0" cellspacing="0" border="0">
<tbody>
<tr>
<td>
<input type="radio" name="jmxSecure" value="true" <%= (jmxSecure ? "checked" : "") %>
id="JMX03">
</td>
<td><label for="JMX03"><fmt:message key="server.props.enable" /></label></td>
</tr>
<tr>
<td>
<input type="radio" name="jmxSecure" value="false" <%= (!jmxSecure ? "checked" : "") %>
id="JMX04">
</td>
<td><label for="JMX04"><fmt:message key="server.props.disable" /></label></td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td class="c1">
<fmt:message key="server.props.jmx_port" />
</td>
<td class="c2">
<input type="text" name="jmxPort" value="<%= (jmxPort > 0 ? String.valueOf(jmxPort) : "") %>"
size="5" maxlength="5">
<% if (errors.containsKey("jmxPort")) { %>
<br>
<span class="jive-error-text">
<fmt:message key="server.props.jmx_valid" />
<a href="#" onclick="document.editform.jmxPort.value='<%=java.rmi.registry.Registry.REGISTRY_PORT%>';"
><fmt:message key="server.props.jmx_valid1" /></a>.
</span>
<% } %>
</td>
</tr>
</tbody>
<tfoot>
<tr>
......
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