📄 xmppserver.java
字号:
/**
* $RCSfile$
* $Revision: 3144 $
* $Date: 2005-12-01 14:20:11 -0300 (Thu, 01 Dec 2005) $
*
* Copyright (C) 2008 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, or a commercial license
* agreement with Jive.
*/
package org.jivesoftware.openfire;
import org.dom4j.Document;
import org.dom4j.io.SAXReader;
import org.jivesoftware.database.DbConnectionManager;
import org.jivesoftware.openfire.audit.AuditManager;
import org.jivesoftware.openfire.audit.spi.AuditManagerImpl;
import org.jivesoftware.openfire.clearspace.ClearspaceManager;
import org.jivesoftware.openfire.cluster.NodeID;
import org.jivesoftware.openfire.commands.AdHocCommandHandler;
import org.jivesoftware.openfire.component.InternalComponentManager;
import org.jivesoftware.openfire.container.AdminConsolePlugin;
import org.jivesoftware.openfire.container.Module;
import org.jivesoftware.openfire.container.PluginManager;
import org.jivesoftware.openfire.disco.*;
import org.jivesoftware.openfire.filetransfer.DefaultFileTransferManager;
import org.jivesoftware.openfire.filetransfer.FileTransferManager;
import org.jivesoftware.openfire.filetransfer.proxy.FileTransferProxy;
import org.jivesoftware.openfire.handler.*;
import org.jivesoftware.openfire.lockout.LockOutManager;
import org.jivesoftware.openfire.mediaproxy.MediaProxyService;
import org.jivesoftware.openfire.muc.MultiUserChatServer;
import org.jivesoftware.openfire.muc.spi.MultiUserChatServerImpl;
import org.jivesoftware.openfire.net.MulticastDNSService;
import org.jivesoftware.openfire.net.SSLConfig;
import org.jivesoftware.openfire.net.ServerTrafficCounter;
import org.jivesoftware.openfire.pep.IQPEPHandler;
import org.jivesoftware.openfire.pep.IQPEPOwnerHandler;
import org.jivesoftware.openfire.pubsub.PubSubModule;
import org.jivesoftware.openfire.roster.RosterManager;
import org.jivesoftware.openfire.session.RemoteSessionLocator;
import org.jivesoftware.openfire.spi.*;
import org.jivesoftware.openfire.stun.STUNService;
import org.jivesoftware.openfire.transport.TransportHandler;
import org.jivesoftware.openfire.update.UpdateManager;
import org.jivesoftware.openfire.user.UserManager;
import org.jivesoftware.openfire.vcard.VCardManager;
import org.jivesoftware.util.*;
import org.jivesoftware.util.cache.CacheFactory;
import org.xmpp.packet.JID;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.KeyStore;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* The main XMPP server that will load, initialize and start all the server's
* modules. The server is unique in the JVM and could be obtained by using the
* {@link #getInstance()} method.<p>
* <p/>
* The loaded modules will be initialized and may access through the server other
* modules. This means that the only way for a module to locate another module is
* through the server. The server maintains a list of loaded modules.<p>
* <p/>
* After starting up all the modules the server will load any available plugin.
* For more information see: {@link org.jivesoftware.openfire.container.PluginManager}.<p>
* <p/>
* A configuration file keeps the server configuration. This information is required for the
* server to work correctly. The server assumes that the configuration file is named
* <b>openfire.xml</b> and is located in the <b>conf</b> folder. The folder that keeps
* the configuration file must be located under the home folder. The server will try different
* methods to locate the home folder.
* <p/>
* <ol>
* <li><b>system property</b> - The server will use the value defined in the <i>openfireHome</i>
* system property.</li>
* <li><b>working folder</b> - The server will check if there is a <i>conf</i> folder in the
* working directory. This is the case when running in standalone mode.</li>
* <li><b>openfire_init.xml file</b> - Attempt to load the value from openfire_init.xml which
* must be in the classpath</li>
* </ol>
*
* @author Gaston Dombiak
*/
public class XMPPServer {
private static XMPPServer instance;
private String name;
private String host;
private Version version;
private Date startDate;
private boolean initialized = false;
private boolean started = false;
private NodeID nodeID;
private static final NodeID DEFAULT_NODE_ID = NodeID.getInstance(new byte[0]);
/**
* All modules loaded by this server
*/
private Map<Class, Module> modules = new LinkedHashMap<Class, Module>();
/**
* Listeners that will be notified when the server has started or is about to be stopped.
*/
private List<XMPPServerListener> listeners = new CopyOnWriteArrayList<XMPPServerListener>();
/**
* Location of the home directory. All configuration files should be
* located here.
*/
private File openfireHome;
private ClassLoader loader;
private PluginManager pluginManager;
private InternalComponentManager componentManager;
private RemoteSessionLocator remoteSessionLocator;
/**
* True if in setup mode
*/
private boolean setupMode = true;
private static final String STARTER_CLASSNAME =
"org.jivesoftware.openfire.starter.ServerStarter";
private static final String WRAPPER_CLASSNAME =
"org.tanukisoftware.wrapper.WrapperManager";
private boolean shuttingDown;
private XMPPServerInfoImpl xmppServerInfo;
/**
* Returns a singleton instance of XMPPServer.
*
* @return an instance.
*/
public static XMPPServer getInstance() {
return instance;
}
/**
* Creates a server and starts it.
*/
public XMPPServer() {
// We may only have one instance of the server running on the JVM
if (instance != null) {
throw new IllegalStateException("A server is already running");
}
instance = this;
start();
}
/**
* Returns a snapshot of the server's status.
*
* @return the server information current at the time of the method call.
*/
public XMPPServerInfo getServerInfo() {
if (!initialized) {
throw new IllegalStateException("Not initialized yet");
}
return xmppServerInfo;
}
/**
* Returns true if the given address is local to the server (managed by this
* server domain). Return false even if the jid's domain matches a local component's
* service JID.
*
* @param jid the JID to check.
* @return true if the address is a local address to this server.
*/
public boolean isLocal(JID jid) {
boolean local = false;
if (jid != null && name != null && name.equals(jid.getDomain())) {
local = true;
}
return local;
}
/**
* Returns true if the given address does not match the local server hostname and does not
* match a component service JID.
*
* @param jid the JID to check.
* @return true if the given address does not match the local server hostname and does not
* match a component service JID.
*/
public boolean isRemote(JID jid) {
if (jid != null) {
if (!name.equals(jid.getDomain()) && !componentManager.hasComponent(jid)) {
return true;
}
}
return false;
}
/**
* Returns an ID that uniquely identifies this server in a cluster. When not running in cluster mode
* the returned value is always the same. However, when in cluster mode the value should be set
* when joining the cluster and must be unique even upon restarts of this node.
*
* @return an ID that uniquely identifies this server in a cluster.
*/
public NodeID getNodeID() {
return nodeID == null ? DEFAULT_NODE_ID : nodeID;
}
/**
* Sets an ID that uniquely identifies this server in a cluster. When not running in cluster mode
* the returned value is always the same. However, when in cluster mode the value should be set
* when joining the cluster and must be unique even upon restarts of this node.
*
* @param nodeID an ID that uniquely identifies this server in a cluster or null if not in a cluster.
*/
public void setNodeID(NodeID nodeID) {
this.nodeID = nodeID;
}
/**
* Returns true if the given address matches a component service JID.
*
* @param jid the JID to check.
* @return true if the given address matches a component service JID.
*/
public boolean matchesComponent(JID jid) {
return jid != null && !name.equals(jid.getDomain()) && componentManager.hasComponent(jid);
}
/**
* Creates an XMPPAddress local to this server.
*
* @param username the user name portion of the id or null to indicate none is needed.
* @param resource the resource portion of the id or null to indicate none is needed.
* @return an XMPPAddress for the server.
*/
public JID createJID(String username, String resource) {
return new JID(username, name, resource);
}
/**
* Creates an XMPPAddress local to this server. The construction of the new JID
* can be optimized by skipping stringprep operations.
*
* @param username the user name portion of the id or null to indicate none is needed.
* @param resource the resource portion of the id or null to indicate none is needed.
* @param skipStringprep true if stringprep should not be applied.
* @return an XMPPAddress for the server.
*/
public JID createJID(String username, String resource, boolean skipStringprep) {
return new JID(username, name, resource, skipStringprep);
}
/**
* Returns a collection with the JIDs of the server's admins. The collection may include
* JIDs of local users and users of remote servers.
*
* @return a collection with the JIDs of the server's admins.
*/
public Collection<JID> getAdmins() {
Collection<JID> admins = new ArrayList<JID>();
// Add the JIDs of the local users that are admins
String usernames = JiveGlobals.getXMLProperty("admin.authorizedUsernames");
if (usernames == null) {
// Fall back to old method for defining admins (i.e. using adminConsole prefix
usernames = JiveGlobals.getXMLProperty("adminConsole.authorizedUsernames");
}
usernames = (usernames == null || usernames.trim().length() == 0) ? "admin" : usernames;
StringTokenizer tokenizer = new StringTokenizer(usernames, ",");
while (tokenizer.hasMoreTokens()) {
String username = tokenizer.nextToken();
try {
admins.add(createJID(username.toLowerCase().trim(), null));
}
catch (IllegalArgumentException e) {
// Ignore usernames that when appended @server.com result in an invalid JID
Log.warn("Invalid username found in authorizedUsernames at openfire.xml: " +
username, e);
}
}
// Add bare JIDs of users that are admins (may include remote users)
String jids = JiveGlobals.getXMLProperty("admin.authorizedJIDs");
jids = (jids == null || jids.trim().length() == 0) ? "" : jids;
tokenizer = new StringTokenizer(jids, ",");
while (tokenizer.hasMoreTokens()) {
String jid = tokenizer.nextToken().toLowerCase().trim();
try {
admins.add(new JID(jid));
}
catch (IllegalArgumentException e) {
Log.warn("Invalid JID found in authorizedJIDs at openfire.xml: " + jid, e);
}
}
return admins;
}
/**
* Adds a new server listener that will be notified when the server has been started
* or is about to be stopped.
*
* @param listener the new server listener to add.
*/
public void addServerListener(XMPPServerListener listener) {
listeners.add(listener);
}
/**
* Removes a server listener that was being notified when the server was being started
* or was about to be stopped.
*
* @param listener the server listener to remove.
*/
public void removeServerListener(XMPPServerListener listener) {
listeners.remove(listener);
}
private void initialize() throws FileNotFoundException {
locateOpenfire();
name = JiveGlobals.getProperty("xmpp.domain", "127.0.0.1").toLowerCase();
try {
host = InetAddress.getLocalHost().getHostName();
}
catch (UnknownHostException ex) {
Log.warn("Unable to determine local hostname.", ex);
}
version = new Version(3, 5, 1, Version.ReleaseStatus.Release, -1);
if ("true".equals(JiveGlobals.getXMLProperty("setup"))) {
setupMode = false;
}
if (isStandAlone()) {
Runtime.getRuntime().addShutdownHook(new ShutdownHookThread());
}
loader = Thread.currentThread().getContextClassLoader();
try {
CacheFactory.initialize();
} catch (InitializationException e) {
e.printStackTrace();
Log.error(e);
}
initialized = true;
}
/**
* Finish the setup process. Because this method is meant to be called from inside
* the Admin console plugin, it spawns its own thread to do the work so that the
* class loader is correct.
*/
public void finishSetup() {
if (!setupMode) {
return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -