1 /* 2 * Copyright (C) 2004-2008 Jive Software. All rights reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package org.jivesoftware.openfire; 18 19 import java.io.BufferedReader; 20 import java.io.File; 21 import java.io.FileNotFoundException; 22 import java.io.IOException; 23 import java.io.InputStream; 24 import java.io.InputStreamReader; 25 import java.lang.reflect.Field; 26 import java.lang.reflect.Method; 27 import java.net.InetAddress; 28 import java.net.UnknownHostException; 29 import java.sql.Connection; 30 import java.sql.PreparedStatement; 31 import java.sql.ResultSet; 32 import java.util.*; 33 import java.util.concurrent.CopyOnWriteArrayList; 34 import java.util.concurrent.Executors; 35 import java.util.concurrent.Future; 36 import java.util.concurrent.TimeUnit; 37 38 import com.google.common.util.concurrent.SimpleTimeLimiter; 39 import com.google.common.util.concurrent.ThreadFactoryBuilder; 40 import org.apache.logging.log4j.LogManager; 41 import org.dom4j.Document; 42 import org.jivesoftware.database.DbConnectionManager; 43 import org.jivesoftware.database.JNDIDataSourceProvider; 44 import org.jivesoftware.openfire.admin.AdminManager; 45 import org.jivesoftware.openfire.audit.AuditManager; 46 import org.jivesoftware.openfire.audit.spi.AuditManagerImpl; 47 import org.jivesoftware.openfire.auth.AuthFactory; 48 import org.jivesoftware.openfire.cluster.ClusterManager; 49 import org.jivesoftware.openfire.cluster.ClusterMonitor; 50 import org.jivesoftware.openfire.cluster.NodeID; 51 import org.jivesoftware.openfire.commands.AdHocCommandHandler; 52 import org.jivesoftware.openfire.component.InternalComponentManager; 53 import org.jivesoftware.openfire.container.AdminConsolePlugin; 54 import org.jivesoftware.openfire.container.Module; 55 import org.jivesoftware.openfire.container.PluginManager; 56 import org.jivesoftware.openfire.disco.IQDiscoInfoHandler; 57 import org.jivesoftware.openfire.disco.IQDiscoItemsHandler; 58 import org.jivesoftware.openfire.disco.ServerFeaturesProvider; 59 import org.jivesoftware.openfire.disco.ServerIdentitiesProvider; 60 import org.jivesoftware.openfire.disco.ServerItemsProvider; 61 import org.jivesoftware.openfire.disco.UserFeaturesProvider; 62 import org.jivesoftware.openfire.disco.UserIdentitiesProvider; 63 import org.jivesoftware.openfire.disco.UserItemsProvider; 64 import org.jivesoftware.openfire.entitycaps.EntityCapabilitiesManager; 65 import org.jivesoftware.openfire.filetransfer.DefaultFileTransferManager; 66 import org.jivesoftware.openfire.filetransfer.FileTransferManager; 67 import org.jivesoftware.openfire.filetransfer.proxy.FileTransferProxy; 68 import org.jivesoftware.openfire.group.GroupManager; 69 import org.jivesoftware.openfire.handler.IQBindHandler; 70 import org.jivesoftware.openfire.handler.IQBlockingHandler; 71 import org.jivesoftware.openfire.handler.IQEntityTimeHandler; 72 import org.jivesoftware.openfire.handler.IQHandler; 73 import org.jivesoftware.openfire.handler.IQLastActivityHandler; 74 import org.jivesoftware.openfire.handler.IQMessageCarbonsHandler; 75 import org.jivesoftware.openfire.handler.IQOfflineMessagesHandler; 76 import org.jivesoftware.openfire.handler.IQPingHandler; 77 import org.jivesoftware.openfire.handler.IQPrivacyHandler; 78 import org.jivesoftware.openfire.handler.IQPrivateHandler; 79 import org.jivesoftware.openfire.handler.IQRegisterHandler; 80 import org.jivesoftware.openfire.handler.IQRosterHandler; 81 import org.jivesoftware.openfire.handler.IQSessionEstablishmentHandler; 82 import org.jivesoftware.openfire.handler.IQSharedGroupHandler; 83 import org.jivesoftware.openfire.handler.IQVersionHandler; 84 import org.jivesoftware.openfire.handler.IQvCardHandler; 85 import org.jivesoftware.openfire.handler.PresenceSubscribeHandler; 86 import org.jivesoftware.openfire.handler.PresenceUpdateHandler; 87 import org.jivesoftware.openfire.keystore.CertificateStoreManager; 88 import org.jivesoftware.openfire.keystore.IdentityStore; 89 import org.jivesoftware.openfire.lockout.LockOutManager; 90 import org.jivesoftware.openfire.mediaproxy.MediaProxyService; 91 import org.jivesoftware.openfire.muc.MultiUserChatManager; 92 import org.jivesoftware.openfire.net.MulticastDNSService; 93 import org.jivesoftware.openfire.net.ServerTrafficCounter; 94 import org.jivesoftware.openfire.pep.IQPEPHandler; 95 import org.jivesoftware.openfire.pep.IQPEPOwnerHandler; 96 import org.jivesoftware.openfire.pubsub.PubSubModule; 97 import org.jivesoftware.openfire.roster.DefaultRosterItemProvider; 98 import org.jivesoftware.openfire.roster.RosterItem; 99 import org.jivesoftware.openfire.roster.RosterItemProvider; 100 import org.jivesoftware.openfire.roster.RosterManager; 101 import org.jivesoftware.openfire.sasl.AnonymousSaslServer; 102 import org.jivesoftware.openfire.security.SecurityAuditManager; 103 import org.jivesoftware.openfire.session.ConnectionSettings; 104 import org.jivesoftware.openfire.session.RemoteSessionLocator; 105 import org.jivesoftware.openfire.session.SoftwareVersionManager; 106 import org.jivesoftware.openfire.session.SoftwareServerVersionManager; 107 import org.jivesoftware.openfire.spi.ConnectionManagerImpl; 108 import org.jivesoftware.openfire.spi.ConnectionType; 109 import org.jivesoftware.openfire.spi.PacketDelivererImpl; 110 import org.jivesoftware.openfire.spi.PacketRouterImpl; 111 import org.jivesoftware.openfire.spi.PacketTransporterImpl; 112 import org.jivesoftware.openfire.spi.PresenceManagerImpl; 113 import org.jivesoftware.openfire.spi.RoutingTableImpl; 114 import org.jivesoftware.openfire.spi.XMPPServerInfoImpl; 115 import org.jivesoftware.openfire.transport.TransportHandler; 116 import org.jivesoftware.openfire.update.UpdateManager; 117 import org.jivesoftware.openfire.user.User; 118 import org.jivesoftware.openfire.user.UserManager; 119 import org.jivesoftware.openfire.vcard.VCardManager; 120 import org.jivesoftware.util.*; 121 import org.jivesoftware.openfire.archive.ArchiveManager; 122 import org.jivesoftware.util.cache.CacheFactory; 123 import org.slf4j.Logger; 124 import org.slf4j.LoggerFactory; 125 import org.xmpp.packet.JID; 126 import org.xmpp.packet.Message; 127 128 import com.google.common.reflect.ClassPath; 129 130 /** 131 * The main XMPP server that will load, initialize and start all the server's 132 * modules. The server is unique in the JVM and could be obtained by using the 133 * {@link #getInstance()} method. 134 * <p> 135 * The loaded modules will be initialized and may access through the server other 136 * modules. This means that the only way for a module to locate another module is 137 * through the server. The server maintains a list of loaded modules. 138 * </p> 139 * <p> 140 * After starting up all the modules the server will load any available plugin. 141 * For more information see: {@link org.jivesoftware.openfire.container.PluginManager}. 142 * </p> 143 * <p>A configuration file keeps the server configuration. This information is required for the 144 * server to work correctly. The server assumes that the configuration file is named 145 * <b>openfire.xml</b> and is located in the <b>conf</b> folder. The folder that keeps 146 * the configuration file must be located under the home folder. The server will try different 147 * methods to locate the home folder.</p> 148 * <ol> 149 * <li><b>system property</b> - The server will use the value defined in the <i>openfireHome</i> 150 * system property.</li> 151 * <li><b>working folder</b> - The server will check if there is a <i>conf</i> folder in the 152 * working directory. This is the case when running in standalone mode.</li> 153 * <li><b>openfire_init.xml file</b> - Attempt to load the value from openfire_init.xml which 154 * must be in the classpath</li> 155 * </ol> 156 * 157 * @author Gaston Dombiak 158 */ 159 public class XMPPServer { 160 161 private static final Logger logger = LoggerFactory.getLogger(XMPPServer.class); 162 163 private static XMPPServer instance; 164 165 private boolean initialized = false; 166 private boolean started = false; 167 private NodeID nodeID; 168 private static final NodeID DEFAULT_NODE_ID = NodeID.getInstance( UUID.randomUUID().toString().getBytes() ); 169 170 private Timer terminatorTimer; 171 public static final String EXIT = "exit"; 172 private final static Set<String> XML_ONLY_PROPERTIES; 173 static { 174 final List<String> properties = new ArrayList<>(Arrays.asList( 175 // Admin console network settings 176 "adminConsole.port", "adminConsole.securePort", "adminConsole.interface", "network.interface", 177 // Misc. settings 178 "locale", "fqdn", "setup", ClusterManager.CLUSTER_PROPERTY_NAME, 179 // Database config 180 "connectionProvider.className", 181 "database.defaultProvider.driver", "database.defaultProvider.serverURL", "database.defaultProvider.username", 182 "database.defaultProvider.password", "database.defaultProvider.testSQL", "database.defaultProvider.testBeforeUse", 183 "database.defaultProvider.testAfterUse", "database.defaultProvider.testTimeout", "database.defaultProvider.timeBetweenEvictionRuns", 184 "database.defaultProvider.minIdleTime", "database.defaultProvider.maxWaitTime", "database.defaultProvider.minConnections", 185 "database.defaultProvider.maxConnections", "database.defaultProvider.connectionTimeout", "database.mysql.useUnicode", 186 "database.JNDIProvider.name" 187 )); 188 // JDNI database config Arrays.asList(JNDIDataSourceProvider.jndiPropertyKeys)189 properties.addAll(Arrays.asList(JNDIDataSourceProvider.jndiPropertyKeys)); 190 XML_ONLY_PROPERTIES = Collections.unmodifiableSet(new HashSet<>(properties)); 191 } 192 193 /** 194 * All modules loaded by this server 195 */ 196 private Map<Class, Module> modules = new LinkedHashMap<>(); 197 198 /** 199 * Listeners that will be notified when the server has started or is about to be stopped. 200 */ 201 private List<XMPPServerListener> listeners = new CopyOnWriteArrayList<>(); 202 203 /** 204 * Location of the home directory. All configuration files should be 205 * located here. 206 */ 207 private File openfireHome; 208 private ClassLoader loader; 209 210 private PluginManager pluginManager; 211 private InternalComponentManager componentManager; 212 private RemoteSessionLocator remoteSessionLocator; 213 214 /** 215 * True if in setup mode 216 */ 217 private boolean setupMode = true; 218 219 private static final String STARTER_CLASSNAME = 220 "org.jivesoftware.openfire.starter.ServerStarter"; 221 private static final String WRAPPER_CLASSNAME = 222 "org.tanukisoftware.wrapper.WrapperManager"; 223 private boolean shuttingDown; 224 private XMPPServerInfoImpl xmppServerInfo; 225 226 /** 227 * Returns a singleton instance of XMPPServer. 228 * 229 * @return an instance. 230 */ getInstance()231 public static XMPPServer getInstance() { 232 return instance; 233 } 234 235 /** 236 * TODO: (2019-04-24) Remove and replace with <a href="https://github.com/mockito/mockito/issues/1013">Mockito mocking of static methods</a>, when available 237 * 238 * @param instance the mock/stub/spy XMPPServer to return when {@link #getInstance()} is called. 239 * @deprecated - for test use only 240 */ 241 @Deprecated setInstance(final XMPPServer instance)242 public static void setInstance(final XMPPServer instance) { 243 XMPPServer.instance = instance; 244 } 245 246 /** 247 * Creates a server and starts it. 248 */ XMPPServer()249 public XMPPServer() { 250 // We may only have one instance of the server running on the JVM 251 if (instance != null) { 252 throw new IllegalStateException("A server is already running"); 253 } 254 instance = this; 255 start(); 256 } 257 258 /** 259 * Returns a snapshot of the server's status. 260 * 261 * @return the server information current at the time of the method call. 262 */ getServerInfo()263 public XMPPServerInfo getServerInfo() { 264 if (!initialized) { 265 throw new IllegalStateException("Not initialized yet"); 266 } 267 return xmppServerInfo; 268 } 269 270 /** 271 * Returns true if the given address is local to the server (managed by this 272 * server domain). Return false even if the jid's domain matches a local component's 273 * service JID. 274 * 275 * @param jid the JID to check. 276 * @return true if the address is a local address to this server. 277 */ isLocal( JID jid )278 public boolean isLocal( JID jid ) 279 { 280 return jid != null && jid.getDomain().equals( xmppServerInfo.getXMPPDomain() ); 281 } 282 283 /** 284 * Returns true if the domain-part of the given address does not match the local server hostname and does not 285 * match a component service JID 286 * 287 * @param jid the JID to check. 288 * @return true if the given address does not match the local server hostname and does not 289 * match a component service JID. 290 */ isRemote( JID jid )291 public boolean isRemote( JID jid ) 292 { 293 return jid != null 294 && !jid.getDomain().equals( xmppServerInfo.getXMPPDomain() ) 295 && !componentManager.hasComponent( new JID(null, jid.getDomain(), null, true) ); 296 } 297 298 /** 299 * Returns an ID that uniquely identifies this server in a cluster. When not running in cluster mode 300 * the returned value is always the same. However, when in cluster mode the value should be set 301 * when joining the cluster and must be unique even upon restarts of this node. 302 * 303 * @return an ID that uniquely identifies this server in a cluster. 304 */ getNodeID()305 public NodeID getNodeID() { 306 return nodeID == null ? DEFAULT_NODE_ID : nodeID; 307 } 308 309 /** 310 * Sets an ID that uniquely identifies this server in a cluster. When not running in cluster mode 311 * the returned value is always the same. However, when in cluster mode the value should be set 312 * when joining the cluster and must be unique even upon restarts of this node. 313 * 314 * @param nodeID an ID that uniquely identifies this server in a cluster or null if not in a cluster. 315 */ setNodeID(NodeID nodeID)316 public void setNodeID(NodeID nodeID) { 317 this.nodeID = nodeID; 318 } 319 320 /** 321 * Returns the default node ID used by this server before clustering is 322 * initialized. 323 * 324 * @return The default node ID. 325 */ getDefaultNodeID()326 public NodeID getDefaultNodeID() { 327 return DEFAULT_NODE_ID; 328 } 329 330 /** 331 * Returns true if the domain-part of the given address matches a component service JID for a component that is 332 * connected to the local XMPP domain. 333 * 334 * @param jid the JID to check. 335 * @return true if the given address matches a component service JID. 336 */ matchesComponent( JID jid )337 public boolean matchesComponent( JID jid ) 338 { 339 return jid != null 340 && !jid.getDomain().equals( xmppServerInfo.getXMPPDomain() ) 341 && componentManager.hasComponent( new JID(null, jid.getDomain(), null, true) ); 342 } 343 344 /** 345 * Creates an XMPPAddress local to this server. 346 * 347 * @param username the user name portion of the id or null to indicate none is needed. 348 * @param resource the resource portion of the id or null to indicate none is needed. 349 * @return an XMPPAddress for the server. 350 */ createJID(String username, String resource)351 public JID createJID(String username, String resource) { 352 return new JID(username, xmppServerInfo.getXMPPDomain(), resource); 353 } 354 355 /** 356 * Creates an XMPPAddress local to this server. The construction of the new JID 357 * can be optimized by skipping stringprep operations. 358 * 359 * @param username the user name portion of the id or null to indicate none is needed. 360 * @param resource the resource portion of the id or null to indicate none is needed. 361 * @param skipStringprep true if stringprep should not be applied. 362 * @return an XMPPAddress for the server. 363 */ createJID(String username, String resource, boolean skipStringprep)364 public JID createJID(String username, String resource, boolean skipStringprep) { 365 return new JID(username, xmppServerInfo.getXMPPDomain(), resource, skipStringprep); 366 } 367 368 /** 369 * Returns a collection with the JIDs of the server's admins. The collection may include 370 * JIDs of local users and users of remote servers. 371 * 372 * @return a collection with the JIDs of the server's admins. 373 */ getAdmins()374 public Collection<JID> getAdmins() { 375 return AdminManager.getInstance().getAdminAccounts(); 376 } 377 378 /** 379 * Adds a new server listener that will be notified when the server has been started 380 * or is about to be stopped. 381 * 382 * @param listener the new server listener to add. 383 */ addServerListener(XMPPServerListener listener)384 public void addServerListener(XMPPServerListener listener) { 385 listeners.add(listener); 386 } 387 388 /** 389 * Removes a server listener that was being notified when the server was being started 390 * or was about to be stopped. 391 * 392 * @param listener the server listener to remove. 393 */ removeServerListener(XMPPServerListener listener)394 public void removeServerListener(XMPPServerListener listener) { 395 listeners.remove(listener); 396 } 397 initialize()398 private void initialize() throws FileNotFoundException { 399 locateOpenfire(); 400 401 if ("true".equals(JiveGlobals.getXMLProperty("setup"))) { 402 setupMode = false; 403 } 404 405 if (isStandAlone()) { 406 logger.info("Registering shutdown hook (standalone mode)"); 407 Runtime.getRuntime().addShutdownHook(new ShutdownHookThread()); 408 terminatorTimer = new Timer(); // Not using TaskEngine here, as that requires configuration to be available, which it is not yet. 409 terminatorTimer.schedule(new Terminator(), 1000, 1000); 410 } 411 412 loader = Thread.currentThread().getContextClassLoader(); 413 414 try { 415 CacheFactory.initialize(); 416 } catch (InitializationException e) { 417 e.printStackTrace(); 418 logger.error(e.getMessage(), e); 419 } 420 421 JiveGlobals.migrateProperty(XMPPServerInfo.XMPP_DOMAIN.getKey()); 422 423 JiveGlobals.migrateProperty(Log.DEBUG_ENABLED.getKey()); 424 if (Log.DEBUG_ENABLED.getValue()) { 425 Log.setDebugEnabled(true); 426 } 427 if (Log.TRACE_ENABLED.getValue()) { 428 Log.setTraceEnabled(true); 429 } 430 431 // Update server info 432 xmppServerInfo = new XMPPServerInfoImpl(new Date()); 433 434 initialized = true; 435 436 if (setupMode && "true".equals(JiveGlobals.getXMLProperty("autosetup.run"))) { 437 this.runAutoSetup(); 438 JiveGlobals.deleteXMLProperty("autosetup"); 439 JiveGlobals.deleteProperty("autosetup"); 440 } 441 442 // OF-1548: Move the storage of the FQDN from the database to the XML configuration 443 final String hostNameFromDatabase = JiveGlobals.getProperty("xmpp.fqdn", ""); 444 final String hostNameFromXML = JiveGlobals.getXMLProperty("fqdn", ""); 445 if (!hostNameFromDatabase.isEmpty() && hostNameFromXML.isEmpty()) { 446 final String hostname; 447 if (ClusterManager.isClusteringEnabled()) { 448 // The database value has at best a 50% chance of being right - so instead use a sensible default 449 String hostnameFromOS; 450 try { 451 hostnameFromOS = InetAddress.getLocalHost().getCanonicalHostName(); 452 } catch (final UnknownHostException e) { 453 logger.warn("Unable to determine local hostname", e); 454 hostnameFromOS = "localhost"; 455 } 456 hostname = hostnameFromOS; 457 } else { 458 hostname = hostNameFromDatabase; 459 } 460 JiveGlobals.setXMLProperty("fqdn", hostname); 461 JiveGlobals.deleteProperty("xmpp.fqdn"); 462 } 463 } 464 runAutoSetup()465 void runAutoSetup() { 466 // Setup property encryptor as early as possible so that database related properties can use it 467 JiveGlobals.setupPropertyEncryptionAlgorithm(JiveGlobals.getXMLProperty("autosetup.encryption.algorithm", "Blowfish")); // or AES 468 JiveGlobals.setupPropertyEncryptionKey(JiveGlobals.getXMLProperty("autosetup.encryption.key", null)); 469 470 // steps from setup-datasource-standard.jsp 471 // do this first so that other changes persist 472 if ("standard".equals(JiveGlobals.getXMLProperty("autosetup.database.mode"))) { 473 JiveGlobals.setXMLProperty("database.defaultProvider.driver", JiveGlobals.getXMLProperty("autosetup.database.defaultProvider.driver")); 474 JiveGlobals.setXMLProperty("database.defaultProvider.serverURL", JiveGlobals.getXMLProperty("autosetup.database.defaultProvider.serverURL")); 475 JiveGlobals.setXMLProperty("database.defaultProvider.username", JiveGlobals.getXMLProperty("autosetup.database.defaultProvider.username")); 476 JiveGlobals.setXMLProperty("database.defaultProvider.password", JiveGlobals.getXMLProperty("autosetup.database.defaultProvider.password")); 477 478 int minConnections; 479 int maxConnections; 480 double connectionTimeout; 481 482 try { 483 minConnections = Integer.parseInt( 484 JiveGlobals.getXMLProperty("autosetup.database.defaultProvider.minConnections")); 485 } 486 catch (Exception e) { 487 minConnections = 5; 488 } 489 try { 490 maxConnections = Integer.parseInt( 491 JiveGlobals.getXMLProperty("autosetup.database.defaultProvider.maxConnections")); 492 } 493 catch (Exception e) { 494 maxConnections = 25; 495 } 496 try { 497 connectionTimeout = Double.parseDouble( 498 JiveGlobals.getXMLProperty("autosetup.database.defaultProvider.connectionTimeout")); 499 } 500 catch (Exception e) { 501 connectionTimeout = 1.0; 502 } 503 504 JiveGlobals.setXMLProperty("database.defaultProvider.minConnections", 505 Integer.toString(minConnections)); 506 JiveGlobals.setXMLProperty("database.defaultProvider.maxConnections", 507 Integer.toString(maxConnections)); 508 JiveGlobals.setXMLProperty("database.defaultProvider.connectionTimeout", 509 Double.toString(connectionTimeout)); 510 } 511 512 // mark setup as done, so that other things can be written to the DB 513 JiveGlobals.setXMLProperty("setup","true"); 514 515 // steps from index.jsp 516 String localeCode = JiveGlobals.getXMLProperty("autosetup.locale"); 517 logger.warn("Setting locale to " + localeCode); 518 JiveGlobals.setLocale(LocaleUtils.localeCodeToLocale(localeCode.trim())); 519 520 // steps from setup-host-settings.jsp 521 JiveGlobals.setXMLProperty(XMPPServerInfo.XMPP_DOMAIN.getKey(), JiveGlobals.getXMLProperty("autosetup." + XMPPServerInfo.XMPP_DOMAIN.getKey())); 522 JiveGlobals.setXMLProperty("fqdn", JiveGlobals.getXMLProperty("autosetup.xmpp.fqdn")); 523 JiveGlobals.migrateProperty(XMPPServerInfo.XMPP_DOMAIN.getKey()); 524 525 ConnectionSettings.Client.ENABLE_OLD_SSLPORT_PROPERTY.setValue(Boolean.valueOf(JiveGlobals.getXMLProperty("autosetup." + ConnectionSettings.Client.ENABLE_OLD_SSLPORT_PROPERTY.getKey(), "true"))); 526 AnonymousSaslServer.ENABLED.setValue(Boolean.valueOf(JiveGlobals.getXMLProperty("autosetup." + AnonymousSaslServer.ENABLED.getKey(), "false"))); 527 528 529 // steps from setup-profile-settings.jsp 530 if ("default".equals(JiveGlobals.getXMLProperty("autosetup.authprovider.mode", "default"))) { 531 JiveGlobals.setXMLProperty("connectionProvider.className", 532 "org.jivesoftware.database.DefaultConnectionProvider"); 533 534 JiveGlobals.setProperty(AuthFactory.AUTH_PROVIDER.getKey(), JiveGlobals.getXMLProperty(AuthFactory.AUTH_PROVIDER.getKey(), 535 AuthFactory.AUTH_PROVIDER.getDefaultValue().getName())); 536 JiveGlobals.setProperty(UserManager.USER_PROVIDER.getKey(), JiveGlobals.getXMLProperty(UserManager.USER_PROVIDER.getKey(), 537 UserManager.USER_PROVIDER.getDefaultValue().getName())); 538 JiveGlobals.setProperty(GroupManager.GROUP_PROVIDER.getKey(), JiveGlobals.getXMLProperty(GroupManager.GROUP_PROVIDER.getKey(), 539 GroupManager.GROUP_PROVIDER.getDefaultValue().getName())); 540 JiveGlobals.setProperty(VCardManager.VCARD_PROVIDER.getKey(), JiveGlobals.getXMLProperty(VCardManager.VCARD_PROVIDER.getKey(), 541 VCardManager.VCARD_PROVIDER.getDefaultValue().getName())); 542 JiveGlobals.setProperty(LockOutManager.LOCKOUT_PROVIDER.getKey(), JiveGlobals.getXMLProperty(LockOutManager.LOCKOUT_PROVIDER.getKey(), 543 LockOutManager.LOCKOUT_PROVIDER.getDefaultValue().getName())); 544 JiveGlobals.setProperty(SecurityAuditManager.AUDIT_PROVIDER.getKey(), JiveGlobals.getXMLProperty(SecurityAuditManager.AUDIT_PROVIDER.getKey(), 545 SecurityAuditManager.AUDIT_PROVIDER.getDefaultValue().getName())); 546 JiveGlobals.setProperty(AdminManager.ADMIN_PROVIDER.getKey(), JiveGlobals.getXMLProperty(AdminManager.ADMIN_PROVIDER.getKey(), 547 AdminManager.ADMIN_PROVIDER.getDefaultValue().getName())); 548 549 // make configurable? 550 JiveGlobals.setProperty("user.scramHashedPasswordOnly", "true"); 551 } 552 553 // steps from setup-admin-settings.jsp 554 try { 555 User adminUser = UserManager.getInstance().getUser("admin"); 556 adminUser.setPassword(JiveGlobals.getXMLProperty("autosetup.admin.password")); 557 adminUser.setEmail(JiveGlobals.getXMLProperty("autosetup.admin.email")); 558 Date now = new Date(); 559 adminUser.setCreationDate(now); 560 adminUser.setModificationDate(now); 561 } catch (Exception e) { 562 e.printStackTrace(); 563 logger.warn("There was an unexpected error encountered when " 564 + "setting the new admin information. Please check your error " 565 + "logs and try to remedy the problem."); 566 } 567 568 // Import any provisioned users. 569 try { 570 RosterItemProvider rosterItemProvider = null; 571 for (int userId = 1; userId < Integer.MAX_VALUE; userId++ ) { 572 final String username = JiveGlobals.getXMLProperty( "autosetup.users.user" + userId + ".username" ); 573 final String password = JiveGlobals.getXMLProperty( "autosetup.users.user" + userId + ".password" ); 574 if (username == null || password == null) { 575 break; 576 } 577 final String name = JiveGlobals.getXMLProperty( "autosetup.users.user" + userId + ".name" ); 578 final String email = JiveGlobals.getXMLProperty( "autosetup.users.user" + userId + ".email" ); 579 580 final User user = UserManager.getInstance().createUser(username, password, name, email ); 581 for (int itemId = 1; itemId < Integer.MAX_VALUE; itemId++) { 582 final String jid = JiveGlobals.getXMLProperty( "autosetup.users.user" + userId + ".roster.item" + itemId + ".jid" ); 583 if (jid == null) { 584 break; 585 } 586 final String nickname = JiveGlobals.getXMLProperty( "autosetup.users.user" + userId + ".roster.item" + itemId + ".nickname" ); 587 final RosterItem rosterItem = new RosterItem(new JID(jid), RosterItem.SubType.BOTH, RosterItem.AskType.NONE, RosterItem.RecvType.NONE, nickname, null); 588 589 if (rosterItemProvider == null) { 590 // Modules have not started at this point, so we can't go through the roster. Use the default provider instead. 591 rosterItemProvider = new DefaultRosterItemProvider(); 592 } 593 rosterItemProvider.createItem(user.getUsername(), rosterItem); 594 } 595 } 596 } catch (Exception e) { 597 e.printStackTrace(); 598 logger.warn("There was an unexpected error encountered when provisioning auto-setup provided users.", e); 599 } 600 601 // finish setup 602 this.finalSetupSteps(); 603 setupMode = false; 604 } 605 finalSetupSteps()606 private void finalSetupSteps() { 607 for (String propName : JiveGlobals.getXMLPropertyNames()) { 608 if (!XML_ONLY_PROPERTIES.contains(propName)) { 609 if (JiveGlobals.getProperty(propName) == null) { 610 JiveGlobals.setProperty(propName, JiveGlobals.getXMLProperty(propName)); 611 } 612 JiveGlobals.setPropertyEncrypted(propName, JiveGlobals.isXMLPropertyEncrypted(propName)); 613 } 614 } 615 616 // Check if keystore (that out-of-the-box is a fallback for all keystores) already has certificates for current domain. 617 CertificateStoreManager certificateStoreManager = null; // Will be a module after finishing setup. 618 try { 619 certificateStoreManager = new CertificateStoreManager(); 620 certificateStoreManager.initialize( this ); 621 certificateStoreManager.start(); 622 final IdentityStore identityStore = certificateStoreManager.getIdentityStore( ConnectionType.SOCKET_C2S ); 623 identityStore.ensureDomainCertificate(); 624 625 } catch (Exception e) { 626 logger.error("Error generating self-signed certificates", e); 627 } finally { 628 if (certificateStoreManager != null) 629 { 630 certificateStoreManager.stop(); 631 certificateStoreManager.destroy(); 632 } 633 } 634 635 // Initialize list of admins now (before we restart Jetty) 636 AdminManager.getInstance().getAdminAccounts(); 637 } 638 639 /** 640 * Finish the setup process. Because this method is meant to be called from inside 641 * the Admin console plugin, it spawns its own thread to do the work so that the 642 * class loader is correct. 643 */ finishSetup()644 public void finishSetup() { 645 if (!setupMode) { 646 return; 647 } 648 649 this.finalSetupSteps(); 650 651 // Make sure that setup finished correctly. 652 if ("true".equals(JiveGlobals.getXMLProperty("setup"))) { 653 // Iterate through all the provided XML properties and set the ones that haven't 654 // already been touched by setup prior to this method being called. 655 656 Thread finishSetup = new Thread() { 657 @Override 658 public void run() { 659 try { 660 if (isStandAlone()) { 661 // Always restart the HTTP server manager. This covers the case 662 // of changing the ports, as well as generating self-signed certificates. 663 664 // Wait a short period before shutting down the admin console. 665 // Otherwise, the page that requested the setup finish won't 666 // render properly! 667 Thread.sleep(1000); 668 ((AdminConsolePlugin) pluginManager.getPlugin("admin")).restart(); 669 } 670 671 verifyDataSource(); 672 // First load all the modules so that modules may access other modules while 673 // being initialized 674 loadModules(); 675 // Initize all the modules 676 initModules(); 677 // Start all the modules 678 startModules(); 679 scanForSystemPropertyClasses(); 680 } 681 catch (Exception e) { 682 e.printStackTrace(); 683 logger.error(e.getMessage(), e); 684 shutdownServer(); 685 } 686 } 687 }; 688 // Use the correct class loader. 689 finishSetup.setContextClassLoader(loader); 690 finishSetup.start(); 691 // We can now safely indicate that setup has finished 692 setupMode = false; 693 } 694 } 695 start()696 public void start() { 697 try { 698 initialize(); 699 700 // Create PluginManager now (but don't start it) so that modules may use it 701 File pluginDir = new File(openfireHome, "plugins"); 702 pluginManager = new PluginManager(pluginDir); 703 704 // If the server has already been setup then we can start all the server's modules 705 if (!setupMode) { 706 verifyDataSource(); 707 // First load all the modules so that modules may access other modules while 708 // being initialized 709 loadModules(); 710 // Initize all the modules 711 initModules(); 712 // Start all the modules 713 startModules(); 714 } 715 // Initialize statistics 716 ServerTrafficCounter.initStatistics(); 717 718 // Load plugins (when in setup mode only the admin console will be loaded) 719 pluginManager.start(); 720 721 // Log that the server has been started 722 String startupBanner = LocaleUtils.getLocalizedString("short.title") + " " + xmppServerInfo.getVersion().getVersionString() + 723 " [" + JiveGlobals.formatDateTime(new Date()) + "]"; 724 logger.info(startupBanner); 725 System.out.println(startupBanner); 726 727 started = true; 728 729 // Notify server listeners that the server has been started 730 for (XMPPServerListener listener : listeners) { 731 try { 732 listener.serverStarted(); 733 } catch (Exception e) { 734 logger.warn("An exception occurred while dispatching a 'serverStarted' event!", e); 735 } 736 } 737 738 if (!setupMode) { 739 scanForSystemPropertyClasses(); 740 } 741 } 742 catch (Exception e) { 743 e.printStackTrace(); 744 logger.error(e.getMessage(), e); 745 System.out.println(LocaleUtils.getLocalizedString("startup.error")); 746 shutdownServer(); 747 } 748 } 749 750 // A SystemProperty class will not appear in the System Properties screen until it is referenced. This method 751 // ensures that they are all referenced immediately. 752 // The following class cannot always be loaded as it references a class that's part of the Install4J launcher 753 private static final Set<String> CLASSES_TO_EXCLUDE = Collections.singleton("org.jivesoftware.openfire.launcher.Uninstaller"); 754 scanForSystemPropertyClasses()755 private void scanForSystemPropertyClasses() { 756 757 try { 758 final Set<ClassPath.ClassInfo> classesInPackage = ClassPath.from(getClass().getClassLoader()).getTopLevelClassesRecursive("org.jivesoftware.openfire"); 759 for (final ClassPath.ClassInfo classInfo : classesInPackage) { 760 final String className = classInfo.getName(); 761 if (!CLASSES_TO_EXCLUDE.contains(className)) { 762 try { 763 final Class<?> clazz = classInfo.load(); 764 final Field[] fields = clazz.getDeclaredFields(); 765 for (final Field field : fields) { 766 if (field.getType().equals(SystemProperty.class)) { 767 try { 768 field.setAccessible(true); 769 logger.info("Accessing SystemProperty field {}#{}", className, field.getName()); 770 field.get(null); 771 } catch (final Throwable t) { 772 logger.warn("Unable to access field {}#{}", className, field.getName(), t); 773 } 774 } 775 } 776 } catch (final Throwable t) { 777 logger.warn("Unable to load class {}", className, t); 778 } 779 } 780 } 781 } catch (final Throwable t) { 782 logger.warn("Unable to scan classpath for SystemProperty classes", t); 783 } 784 } 785 loadModules()786 private void loadModules() { 787 // Load boot modules 788 loadModule(RoutingTableImpl.class.getName()); 789 loadModule(AuditManagerImpl.class.getName()); 790 loadModule(RosterManager.class.getName()); 791 loadModule(PrivateStorage.class.getName()); 792 // Load core modules 793 loadModule(PresenceManagerImpl.class.getName()); 794 loadModule(SessionManager.class.getName()); 795 loadModule(PacketRouterImpl.class.getName()); 796 loadModule(IQRouter.class.getName()); 797 loadModule(MessageRouter.class.getName()); 798 loadModule(PresenceRouter.class.getName()); 799 loadModule(MulticastRouter.class.getName()); 800 loadModule(PacketTransporterImpl.class.getName()); 801 loadModule(PacketDelivererImpl.class.getName()); 802 loadModule(TransportHandler.class.getName()); 803 loadModule(OfflineMessageStrategy.class.getName()); 804 loadModule(OfflineMessageStore.class.getName()); 805 loadModule(VCardManager.class.getName()); 806 // Load standard modules 807 loadModule(IQBindHandler.class.getName()); 808 loadModule(IQSessionEstablishmentHandler.class.getName()); 809 loadModule(IQPingHandler.class.getName()); 810 loadModule(IQBlockingHandler.class.getName()); 811 loadModule(IQPrivateHandler.class.getName()); 812 loadModule(IQRegisterHandler.class.getName()); 813 loadModule(IQRosterHandler.class.getName()); 814 loadModule(IQEntityTimeHandler.class.getName()); 815 loadModule(IQvCardHandler.class.getName()); 816 loadModule(IQVersionHandler.class.getName()); 817 loadModule(IQLastActivityHandler.class.getName()); 818 loadModule(PresenceSubscribeHandler.class.getName()); 819 loadModule(PresenceUpdateHandler.class.getName()); 820 loadModule(IQOfflineMessagesHandler.class.getName()); 821 loadModule(IQPEPHandler.class.getName()); 822 loadModule(IQPEPOwnerHandler.class.getName()); 823 loadModule(MulticastDNSService.class.getName()); 824 loadModule(IQSharedGroupHandler.class.getName()); 825 loadModule(AdHocCommandHandler.class.getName()); 826 loadModule(IQPrivacyHandler.class.getName()); 827 loadModule(DefaultFileTransferManager.class.getName()); 828 loadModule(FileTransferProxy.class.getName()); 829 loadModule(MediaProxyService.class.getName()); 830 loadModule(PubSubModule.class.getName()); 831 loadModule(IQDiscoInfoHandler.class.getName()); 832 loadModule(IQDiscoItemsHandler.class.getName()); 833 loadModule(UpdateManager.class.getName()); 834 loadModule(InternalComponentManager.class.getName()); 835 loadModule(MultiUserChatManager.class.getName()); 836 loadModule(IQMessageCarbonsHandler.class.getName()); 837 loadModule(ArchiveManager.class.getName()); 838 loadModule(CertificateStoreManager.class.getName()); 839 loadModule(EntityCapabilitiesManager.class.getName()); 840 loadModule(SoftwareVersionManager.class.getName()); 841 loadModule(SoftwareServerVersionManager.class.getName()); 842 843 // Load this module always last since we don't want to start listening for clients 844 // before the rest of the modules have been started 845 loadModule(ConnectionManagerImpl.class.getName()); 846 loadModule(ClusterMonitor.class.getName()); 847 // Keep a reference to the internal component manager 848 componentManager = getComponentManager(); 849 } 850 851 /** 852 * Loads a module. 853 * 854 * @param module the name of the class that implements the Module interface. 855 */ loadModule(String module)856 private void loadModule(String module) { 857 try { 858 Class<Module> modClass = (Class<Module>) loader.loadClass(module); 859 Module mod = modClass.newInstance(); 860 this.modules.put(modClass, mod); 861 } 862 catch (Exception e) { 863 e.printStackTrace(); 864 logger.error(LocaleUtils.getLocalizedString("admin.error"), e); 865 } 866 } 867 initModules()868 private void initModules() { 869 for (Module module : modules.values()) { 870 try { 871 module.initialize(this); 872 } 873 catch (Exception e) { 874 e.printStackTrace(); 875 // Remove the failed initialized module 876 this.modules.remove(module.getClass()); 877 module.stop(); 878 module.destroy(); 879 logger.error(LocaleUtils.getLocalizedString("admin.error"), e); 880 } 881 } 882 883 // Register modules with service discovery provides where applicable. 884 for (Module module : modules.values() ) 885 { 886 // Service discovery info 887 if (module instanceof ServerFeaturesProvider) { 888 getIQDiscoInfoHandler().addServerFeaturesProvider( (ServerFeaturesProvider) module ); 889 } 890 891 if (module instanceof ServerIdentitiesProvider) { 892 getIQDiscoInfoHandler().addServerIdentitiesProvider( (ServerIdentitiesProvider) module ); 893 } 894 895 if (module instanceof UserIdentitiesProvider) { 896 getIQDiscoInfoHandler().addUserIdentitiesProvider( (UserIdentitiesProvider) module ); 897 } 898 899 if (module instanceof UserFeaturesProvider ) { 900 getIQDiscoInfoHandler().addUserFeaturesProvider( (UserFeaturesProvider) module ); 901 } 902 903 // Service discovery items 904 if (module instanceof ServerItemsProvider) { 905 getIQDiscoItemsHandler().addServerItemsProvider( (ServerItemsProvider) module ); 906 } 907 908 if (module instanceof UserItemsProvider) { 909 getIQDiscoItemsHandler().addUserItemsProvider( (UserItemsProvider) module); 910 } 911 } 912 913 } 914 915 /** 916 * <p>Following the loading and initialization of all the modules 917 * this method is called to iterate through the known modules and 918 * start them.</p> 919 */ startModules()920 private void startModules() { 921 for (Module module : modules.values()) { 922 try { 923 logger.debug( "Starting module: " + module.getName() ); 924 module.start(); 925 } 926 catch (Exception e) { 927 logger.error( "An exception occurred while starting module '{}'.", module.getName(), e ); 928 } 929 } 930 } 931 932 /** 933 * Restarts the server and all it's modules only if the server is restartable. Otherwise do 934 * nothing. 935 */ restart()936 public void restart() { 937 if (isStandAlone() && isRestartable()) { 938 try { 939 Class<?> wrapperClass = Class.forName(WRAPPER_CLASSNAME); 940 Method restartMethod = wrapperClass.getMethod("restart", (Class []) null); 941 restartMethod.invoke(null, (Object []) null); 942 } 943 catch (Exception e) { 944 logger.error("Could not restart container", e); 945 } 946 } 947 } 948 949 /** 950 * Restarts the HTTP server only when running in stand alone mode. The restart 951 * process will be done in another thread that will wait 1 second before doing 952 * the actual restart. The delay will give time to the page that requested the 953 * restart to fully render its content. 954 */ restartHTTPServer()955 public void restartHTTPServer() { 956 Thread restartThread = new Thread() { 957 @Override 958 public void run() { 959 if (isStandAlone()) { 960 // Restart the HTTP server manager. This covers the case 961 // of changing the ports, as well as generating self-signed certificates. 962 963 // Wait a short period before shutting down the admin console. 964 // Otherwise, this page won't render properly! 965 try { 966 Thread.sleep(1000); 967 ((AdminConsolePlugin) pluginManager.getPlugin("admin")).restart(); 968 } catch (Exception e) { 969 e.printStackTrace(); 970 } 971 } 972 } 973 }; 974 restartThread.setContextClassLoader(loader); 975 restartThread.start(); 976 } 977 978 /** 979 * Stops the server only if running in standalone mode. Do nothing if the server is running 980 * inside of another server. 981 */ stop()982 public void stop() { 983 logger.info("Initiating shutdown ..."); 984 // Only do a system exit if we're running standalone 985 if (isStandAlone()) { 986 // if we're in a wrapper, we have to tell the wrapper to shut us down 987 if (isRestartable()) { 988 try { 989 Class<?> wrapperClass = Class.forName(WRAPPER_CLASSNAME); 990 Method stopMethod = wrapperClass.getMethod("stop", Integer.TYPE); 991 stopMethod.invoke(null, 0); 992 } 993 catch (Exception e) { 994 logger.error("Could not stop container", e); 995 } 996 } 997 else { 998 shutdownServer(); 999 Thread shutdownThread = new ShutdownThread(); 1000 shutdownThread.setDaemon(true); 1001 shutdownThread.start(); 1002 } 1003 } 1004 else { 1005 // Close listening socket no matter what the condition is in order to be able 1006 // to be restartable inside a container. 1007 shutdownServer(); 1008 } 1009 } 1010 isSetupMode()1011 public boolean isSetupMode() { 1012 return setupMode; 1013 } 1014 isRestartable()1015 public boolean isRestartable() { 1016 boolean restartable; 1017 try { 1018 restartable = Class.forName(WRAPPER_CLASSNAME) != null; 1019 } 1020 catch (ClassNotFoundException e) { 1021 restartable = false; 1022 } 1023 return restartable; 1024 } 1025 1026 /** 1027 * Returns if the server is running in standalone mode. We consider that it's running in 1028 * standalone if the "org.jivesoftware.openfire.starter.ServerStarter" class is present in the 1029 * system. 1030 * 1031 * @return true if the server is running in standalone mode. 1032 */ isStandAlone()1033 public boolean isStandAlone() { 1034 boolean standalone; 1035 try { 1036 standalone = Class.forName(STARTER_CLASSNAME) != null; 1037 } 1038 catch (ClassNotFoundException e) { 1039 standalone = false; 1040 } 1041 return standalone; 1042 } 1043 1044 /** 1045 * Verify that the database is accessible. 1046 */ verifyDataSource()1047 private void verifyDataSource() { 1048 Connection con = null; 1049 PreparedStatement pstmt = null; 1050 ResultSet rs = null; 1051 try { 1052 con = DbConnectionManager.getConnection(); 1053 pstmt = con.prepareStatement("SELECT count(*) FROM ofID"); 1054 rs = pstmt.executeQuery(); 1055 rs.next(); 1056 } 1057 catch (Exception e) { 1058 System.err.println("Database setup or configuration error: " + 1059 "Please verify your database settings and check the " + 1060 "logs/error.log file for detailed error messages."); 1061 logger.error("Database could not be accessed", e); 1062 throw new IllegalArgumentException(e); 1063 } 1064 finally { 1065 DbConnectionManager.closeConnection(rs, pstmt, con); 1066 } 1067 } 1068 1069 /** 1070 * Verifies that the given home guess is a real Openfire home directory. 1071 * We do the verification by checking for the Openfire config file in 1072 * the config dir of jiveHome. 1073 * 1074 * @param homeGuess a guess at the path to the home directory. 1075 * @param jiveConfigName the name of the config file to check. 1076 * @return a file pointing to the home directory or null if the 1077 * home directory guess was wrong. 1078 * @throws java.io.FileNotFoundException if there was a problem with the home 1079 * directory provided 1080 */ verifyHome(String homeGuess, String jiveConfigName)1081 private File verifyHome(String homeGuess, String jiveConfigName) throws FileNotFoundException { 1082 File openfireHome = new File(homeGuess); 1083 File configFile = new File(openfireHome, jiveConfigName); 1084 if (!configFile.exists()) { 1085 throw new FileNotFoundException(); 1086 } 1087 else { 1088 try { 1089 return new File(openfireHome.getCanonicalPath()); 1090 } 1091 catch (Exception ex) { 1092 throw new FileNotFoundException(); 1093 } 1094 } 1095 } 1096 1097 /** 1098 * <p>Retrieve the jive home for the container.</p> 1099 * 1100 * @throws FileNotFoundException If jiveHome could not be located 1101 */ locateOpenfire()1102 private void locateOpenfire() throws FileNotFoundException { 1103 String jiveConfigName = "conf" + File.separator + "openfire.xml"; 1104 // First, try to load it openfireHome as a system property. 1105 if (openfireHome == null) { 1106 String homeProperty = System.getProperty("openfireHome"); 1107 try { 1108 if (homeProperty != null) { 1109 openfireHome = verifyHome(homeProperty, jiveConfigName); 1110 } 1111 } 1112 catch (FileNotFoundException fe) { 1113 // Ignore. 1114 } 1115 } 1116 1117 // If we still don't have home, let's assume this is standalone 1118 // and just look for home in a standard sub-dir location and verify 1119 // by looking for the config file 1120 if (openfireHome == null) { 1121 try { 1122 openfireHome = verifyHome("..", jiveConfigName).getCanonicalFile(); 1123 } catch (IOException ie) { 1124 // Ignore. 1125 } 1126 } 1127 1128 // If home is still null, no outside process has set it and 1129 // we have to attempt to load the value from openfire_init.xml, 1130 // which must be in the classpath. 1131 if (openfireHome == null) { 1132 try (InputStream in = getClass().getResourceAsStream("/openfire_init.xml")) { 1133 if (in != null) { 1134 String path = SAXReaderUtil.readRootElement(in).getText(); 1135 try { 1136 if (path != null) { 1137 openfireHome = verifyHome(path, jiveConfigName); 1138 } 1139 } 1140 catch (FileNotFoundException fe) { 1141 fe.printStackTrace(); 1142 } 1143 } 1144 } 1145 catch (Exception e) { 1146 System.err.println("Error loading openfire_init.xml to find home."); 1147 e.printStackTrace(); 1148 if (e instanceof InterruptedException) { 1149 Thread.currentThread().interrupt(); 1150 } 1151 } 1152 } 1153 1154 if (openfireHome == null) { 1155 System.err.println("Could not locate home"); 1156 throw new FileNotFoundException(); 1157 } 1158 else { 1159 // Set the home directory for the config file 1160 JiveGlobals.setHomeDirectory(openfireHome.toString()); 1161 // Set the name of the config file 1162 JiveGlobals.setConfigName(jiveConfigName); 1163 } 1164 } 1165 1166 /** 1167 * This timer task is used to monitor the System input stream 1168 * for a "terminate" command from the launcher (or the console). 1169 * This allows for a graceful shutdown when Openfire is started 1170 * via the launcher, especially in Windows. 1171 */ 1172 private class Terminator extends TimerTask { 1173 private BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); 1174 @Override run()1175 public void run() { 1176 try { 1177 if (stdin.ready()) { 1178 if (EXIT.equalsIgnoreCase(stdin.readLine())) { 1179 System.exit(0); // invokes shutdown hook(s) 1180 } 1181 } 1182 } catch (IOException ioe) { 1183 logger.error("Error reading console input", ioe); 1184 } 1185 } 1186 } 1187 1188 /** 1189 * <p>A thread to ensure the server shuts down no matter what.</p> 1190 * <p>Spawned when stop() is called in standalone mode, we wait a few 1191 * seconds then call system exit().</p> 1192 * 1193 * @author Iain Shigeoka 1194 */ 1195 private class ShutdownHookThread extends Thread { 1196 1197 /** 1198 * <p>Logs the server shutdown.</p> 1199 */ 1200 @Override run()1201 public void run() { 1202 System.err.println("Halting server..."); 1203 shutdownServer(); 1204 System.err.println("Server halted"); 1205 } 1206 } 1207 1208 /** 1209 * <p>A thread to ensure the server shuts down no matter what.</p> 1210 * <p>Spawned when stop() is called in standalone mode, we wait a few 1211 * seconds then call system exit().</p> 1212 * 1213 * @author Iain Shigeoka 1214 */ 1215 private class ShutdownThread extends Thread { 1216 1217 /** 1218 * <p>Shuts down the JVM after a 5 second delay.</p> 1219 */ 1220 @Override run()1221 public void run() { 1222 try { 1223 Thread.sleep(5000); 1224 // No matter what, we make sure it's dead 1225 System.out.println( "Openfire process forcefully killed." ); 1226 System.exit(0); 1227 } 1228 catch (InterruptedException e) { 1229 // Ignore. 1230 } 1231 1232 } 1233 } 1234 1235 /** 1236 * Makes a best effort attempt to shutdown the server 1237 */ shutdownServer()1238 private void shutdownServer() { 1239 shuttingDown = true; 1240 1241 if (terminatorTimer != null) { 1242 terminatorTimer.cancel(); 1243 } 1244 1245 ClusterManager.shutdown(); 1246 // Notify server listeners that the server is about to be stopped 1247 for (XMPPServerListener listener : listeners) { 1248 try { 1249 listener.serverStopping(); 1250 } catch (Exception ex) { 1251 logger.error("Exception during listener shutdown", ex); 1252 } 1253 } 1254 // If we don't have modules then the server has already been shutdown 1255 if (modules.isEmpty()) { 1256 return; 1257 } 1258 1259 // Stop all plugins 1260 logger.info("Shutting down plugins ..."); 1261 if (pluginManager != null) { 1262 try { 1263 pluginManager.shutdown(); 1264 } catch (Exception ex) { 1265 logger.error("Exception during plugin shutdown", ex); 1266 } 1267 } 1268 1269 logger.info("Shutting down " + modules.size() + " modules ..."); 1270 1271 final SimpleTimeLimiter timeLimiter = SimpleTimeLimiter.create( Executors.newSingleThreadExecutor( 1272 new ThreadFactoryBuilder() 1273 .setDaemon( true ) 1274 .setNameFormat( "shutdown-thread-%d" ) 1275 .build() ) ); 1276 1277 // OF-1996" Get all modules and stop and destroy them. Do this in the reverse order in which the were created. 1278 // This ensures that the 'most important' / core modules are shut down last, giving other modules the 1279 // opportunity to make use of their functionality during their shutdown (eg: MUC wants to send messages during 1280 // shutdown). 1281 final List<Class> reverseInsertionOrder = new ArrayList<>( modules.keySet() ); 1282 Collections.reverse( reverseInsertionOrder ); 1283 1284 for( final Class moduleClass : reverseInsertionOrder ) { 1285 final Module module = modules.get( moduleClass ); 1286 try { 1287 // OF-1607: Apply a configurable timeout to the duration of stop/destroy invocation. 1288 timeLimiter.runWithTimeout(() -> { 1289 stopAndDestroyModule(module); 1290 }, JiveGlobals.getLongProperty("shutdown.modules.timeout-millis", Long.MAX_VALUE), TimeUnit.MILLISECONDS); 1291 } catch ( Exception e ) { 1292 logger.warn("An exception occurred while stopping / destroying module '{}'.", module.getName(), e); 1293 System.err.println(e); 1294 } 1295 } 1296 1297 modules.clear(); 1298 // Stop the Db connection manager. 1299 try { 1300 DbConnectionManager.destroyConnectionProvider(); 1301 } catch (Exception ex) { 1302 logger.error("Exception during DB shutdown", ex); 1303 } 1304 1305 // Shutdown the task engine. 1306 TaskEngine.getInstance().shutdown(); 1307 1308 // hack to allow safe stopping 1309 logger.info("Openfire stopped"); 1310 1311 // Shut down the logging framework (causing the last few log entries to be flushed) 1312 LogManager.shutdown(); 1313 } 1314 1315 /** 1316 * Stops and destroys a module. 1317 * 1318 * @param module The module to be stopped (cannot be null). 1319 */ stopAndDestroyModule( final Module module )1320 private static void stopAndDestroyModule( final Module module ) { 1321 try { 1322 logger.debug("Stopping and shutting down module '{}'", module.getName() ); 1323 module.stop(); 1324 module.destroy(); 1325 } catch (Exception ex) { 1326 logger.error("Exception during module '{}' shutdown", module.getName(), ex); 1327 } 1328 } 1329 1330 /** 1331 * Returns true if the server is being shutdown. 1332 * 1333 * @return true if the server is being shutdown. 1334 */ isShuttingDown()1335 public boolean isShuttingDown() { 1336 return shuttingDown; 1337 } 1338 1339 /** 1340 * Returns the <code>ConnectionManager</code> registered with this server. The 1341 * <code>ConnectionManager</code> was registered with the server as a module while starting up 1342 * the server. 1343 * 1344 * @return the <code>ConnectionManager</code> registered with this server. 1345 */ getConnectionManager()1346 public ConnectionManager getConnectionManager() { 1347 return (ConnectionManager) modules.get(ConnectionManagerImpl.class); 1348 } 1349 1350 /** 1351 * Returns the <code>RoutingTable</code> registered with this server. The 1352 * <code>RoutingTable</code> was registered with the server as a module while starting up 1353 * the server. 1354 * 1355 * @return the <code>RoutingTable</code> registered with this server. 1356 */ getRoutingTable()1357 public RoutingTable getRoutingTable() { 1358 return (RoutingTable) modules.get(RoutingTableImpl.class); 1359 } 1360 1361 /** 1362 * Returns the <code>PacketDeliverer</code> registered with this server. The 1363 * <code>PacketDeliverer</code> was registered with the server as a module while starting up 1364 * the server. 1365 * 1366 * @return the <code>PacketDeliverer</code> registered with this server. 1367 */ getPacketDeliverer()1368 public PacketDeliverer getPacketDeliverer() { 1369 return (PacketDeliverer) modules.get(PacketDelivererImpl.class); 1370 } 1371 1372 /** 1373 * Returns the <code>RosterManager</code> registered with this server. The 1374 * <code>RosterManager</code> was registered with the server as a module while starting up 1375 * the server. 1376 * 1377 * @return the <code>RosterManager</code> registered with this server. 1378 */ getRosterManager()1379 public RosterManager getRosterManager() { 1380 return (RosterManager) modules.get(RosterManager.class); 1381 } 1382 1383 /** 1384 * Returns the <code>PresenceManager</code> registered with this server. The 1385 * <code>PresenceManager</code> was registered with the server as a module while starting up 1386 * the server. 1387 * 1388 * @return the <code>PresenceManager</code> registered with this server. 1389 */ getPresenceManager()1390 public PresenceManager getPresenceManager() { 1391 return (PresenceManager) modules.get(PresenceManagerImpl.class); 1392 } 1393 1394 /** 1395 * Returns the <code>OfflineMessageStore</code> registered with this server. The 1396 * <code>OfflineMessageStore</code> was registered with the server as a module while starting up 1397 * the server. 1398 * 1399 * @return the <code>OfflineMessageStore</code> registered with this server. 1400 */ getOfflineMessageStore()1401 public OfflineMessageStore getOfflineMessageStore() { 1402 return (OfflineMessageStore) modules.get(OfflineMessageStore.class); 1403 } 1404 1405 /** 1406 * Returns the <code>OfflineMessageStrategy</code> registered with this server. The 1407 * <code>OfflineMessageStrategy</code> was registered with the server as a module while starting 1408 * up the server. 1409 * 1410 * @return the <code>OfflineMessageStrategy</code> registered with this server. 1411 */ getOfflineMessageStrategy()1412 public OfflineMessageStrategy getOfflineMessageStrategy() { 1413 return (OfflineMessageStrategy) modules.get(OfflineMessageStrategy.class); 1414 } 1415 1416 /** 1417 * Returns the <code>PacketRouter</code> registered with this server. The 1418 * <code>PacketRouter</code> was registered with the server as a module while starting up 1419 * the server. 1420 * 1421 * @return the <code>PacketRouter</code> registered with this server. 1422 */ getPacketRouter()1423 public PacketRouter getPacketRouter() { 1424 return (PacketRouter) modules.get(PacketRouterImpl.class); 1425 } 1426 1427 /** 1428 * Returns the <code>IQRegisterHandler</code> registered with this server. The 1429 * <code>IQRegisterHandler</code> was registered with the server as a module while starting up 1430 * the server. 1431 * 1432 * @return the <code>IQRegisterHandler</code> registered with this server. 1433 */ getIQRegisterHandler()1434 public IQRegisterHandler getIQRegisterHandler() { 1435 return (IQRegisterHandler) modules.get(IQRegisterHandler.class); 1436 } 1437 1438 /** 1439 * Returns the <code>IQPEPHandler</code> registered with this server. The 1440 * <code>IQPEPHandler</code> was registered with the server as a module while starting up 1441 * the server. 1442 * 1443 * @return the <code>IQPEPHandler</code> registered with this server. 1444 */ getIQPEPHandler()1445 public IQPEPHandler getIQPEPHandler() { 1446 return (IQPEPHandler) modules.get(IQPEPHandler.class); 1447 } 1448 1449 /** 1450 * Returns the <code>PluginManager</code> instance registered with this server. 1451 * 1452 * @return the PluginManager instance. 1453 */ getPluginManager()1454 public PluginManager getPluginManager() { 1455 return pluginManager; 1456 } 1457 1458 /** 1459 * Returns the <code>PubSubModule</code> registered with this server. The 1460 * <code>PubSubModule</code> was registered with the server as a module while starting up 1461 * the server. 1462 * 1463 * @return the <code>PubSubModule</code> registered with this server. 1464 */ getPubSubModule()1465 public PubSubModule getPubSubModule() { 1466 return (PubSubModule) modules.get(PubSubModule.class); 1467 } 1468 1469 /** 1470 * Returns the <code>ArchiveManager</code> registered with this server. The 1471 * <code>ArchiveManager</code> was registered with the server as a module while starting up 1472 * the server. 1473 * 1474 * @return the <code>ArchiveManager</code> registered with this server. 1475 */ getArchiveManager()1476 public ArchiveManager getArchiveManager() { 1477 return (ArchiveManager) modules.get(ArchiveManager.class); 1478 } 1479 1480 /** 1481 * Returns a list with all the modules registered with the server that inherit from IQHandler. 1482 * 1483 * @return a list with all the modules registered with the server that inherit from IQHandler. 1484 */ getIQHandlers()1485 public List<IQHandler> getIQHandlers() { 1486 List<IQHandler> answer = new ArrayList<>(); 1487 for (Module module : modules.values()) { 1488 if (module instanceof IQHandler) { 1489 answer.add((IQHandler) module); 1490 } 1491 } 1492 return answer; 1493 } 1494 1495 /** 1496 * Returns the <code>SessionManager</code> registered with this server. The 1497 * <code>SessionManager</code> was registered with the server as a module while starting up 1498 * the server. 1499 * 1500 * @return the <code>SessionManager</code> registered with this server. 1501 */ getSessionManager()1502 public SessionManager getSessionManager() { 1503 return (SessionManager) modules.get(SessionManager.class); 1504 } 1505 1506 /** 1507 * Returns the <code>TransportHandler</code> registered with this server. The 1508 * <code>TransportHandler</code> was registered with the server as a module while starting up 1509 * the server. 1510 * 1511 * @return the <code>TransportHandler</code> registered with this server. 1512 */ getTransportHandler()1513 public TransportHandler getTransportHandler() { 1514 return (TransportHandler) modules.get(TransportHandler.class); 1515 } 1516 1517 /** 1518 * Returns the <code>PresenceUpdateHandler</code> registered with this server. The 1519 * <code>PresenceUpdateHandler</code> was registered with the server as a module while starting 1520 * up the server. 1521 * 1522 * @return the <code>PresenceUpdateHandler</code> registered with this server. 1523 */ getPresenceUpdateHandler()1524 public PresenceUpdateHandler getPresenceUpdateHandler() { 1525 return (PresenceUpdateHandler) modules.get(PresenceUpdateHandler.class); 1526 } 1527 1528 /** 1529 * Returns the <code>PresenceSubscribeHandler</code> registered with this server. The 1530 * <code>PresenceSubscribeHandler</code> was registered with the server as a module while 1531 * starting up the server. 1532 * 1533 * @return the <code>PresenceSubscribeHandler</code> registered with this server. 1534 */ getPresenceSubscribeHandler()1535 public PresenceSubscribeHandler getPresenceSubscribeHandler() { 1536 return (PresenceSubscribeHandler) modules.get(PresenceSubscribeHandler.class); 1537 } 1538 1539 /** 1540 * Returns the <code>IQRouter</code> registered with this server. The 1541 * <code>IQRouter</code> was registered with the server as a module while starting up 1542 * the server. 1543 * 1544 * @return the <code>IQRouter</code> registered with this server. 1545 */ getIQRouter()1546 public IQRouter getIQRouter() { 1547 return (IQRouter) modules.get(IQRouter.class); 1548 } 1549 1550 /** 1551 * Returns the <code>MessageRouter</code> registered with this server. The 1552 * <code>MessageRouter</code> was registered with the server as a module while starting up 1553 * the server. 1554 * 1555 * @return the <code>MessageRouter</code> registered with this server. 1556 */ getMessageRouter()1557 public MessageRouter getMessageRouter() { 1558 return (MessageRouter) modules.get(MessageRouter.class); 1559 } 1560 1561 /** 1562 * Returns the <code>PresenceRouter</code> registered with this server. The 1563 * <code>PresenceRouter</code> was registered with the server as a module while starting up 1564 * the server. 1565 * 1566 * @return the <code>PresenceRouter</code> registered with this server. 1567 */ getPresenceRouter()1568 public PresenceRouter getPresenceRouter() { 1569 return (PresenceRouter) modules.get(PresenceRouter.class); 1570 } 1571 1572 /** 1573 * Returns the <code>MulticastRouter</code> registered with this server. The 1574 * <code>MulticastRouter</code> was registered with the server as a module while starting up 1575 * the server. 1576 * 1577 * @return the <code>MulticastRouter</code> registered with this server. 1578 */ getMulticastRouter()1579 public MulticastRouter getMulticastRouter() { 1580 return (MulticastRouter) modules.get(MulticastRouter.class); 1581 } 1582 1583 /** 1584 * Returns the <code>UserManager</code> registered with this server. The 1585 * <code>UserManager</code> was registered with the server as a module while starting up 1586 * the server. 1587 * 1588 * @return the <code>UserManager</code> registered with this server. 1589 */ getUserManager()1590 public UserManager getUserManager() { 1591 return UserManager.getInstance(); 1592 } 1593 1594 /** 1595 * Returns the <code>LockOutManager</code> registered with this server. The 1596 * <code>LockOutManager</code> was registered with the server as a module while starting up 1597 * the server. 1598 * 1599 * @return the <code>LockOutManager</code> registered with this server. 1600 */ getLockOutManager()1601 public LockOutManager getLockOutManager() { 1602 return LockOutManager.getInstance(); 1603 } 1604 1605 /** 1606 * Returns the <code>UpdateManager</code> registered with this server. The 1607 * <code>UpdateManager</code> was registered with the server as a module while starting up 1608 * the server. 1609 * 1610 * @return the <code>UpdateManager</code> registered with this server. 1611 */ getUpdateManager()1612 public UpdateManager getUpdateManager() { 1613 return (UpdateManager) modules.get(UpdateManager.class); 1614 } 1615 1616 /** 1617 * Returns the <code>AuditManager</code> registered with this server. The 1618 * <code>AuditManager</code> was registered with the server as a module while starting up 1619 * the server. 1620 * 1621 * @return the <code>AuditManager</code> registered with this server. 1622 */ getAuditManager()1623 public AuditManager getAuditManager() { 1624 return (AuditManager) modules.get(AuditManagerImpl.class); 1625 } 1626 1627 /** 1628 * Returns the <code>EntityCapabilitiesManager</code> registered with this server. The 1629 * <code>EntityCapabilitiesManager</code> was registered with the server as a module while starting up 1630 * the server. 1631 * 1632 * @return the <code>EntityCapabilitiesManager</code> registered with this server. 1633 */ getEntityCapabilitiesManager()1634 public EntityCapabilitiesManager getEntityCapabilitiesManager() { 1635 return (EntityCapabilitiesManager) modules.get(EntityCapabilitiesManager.class); 1636 } 1637 1638 /** 1639 * Returns a list with all the modules that provide "discoverable" features. 1640 * 1641 * @return a list with all the modules that provide "discoverable" features. 1642 * @deprecated Use {@link IQDiscoInfoHandler} instead. 1643 */ 1644 @Deprecated getServerFeaturesProviders()1645 public List<ServerFeaturesProvider> getServerFeaturesProviders() { 1646 List<ServerFeaturesProvider> answer = new ArrayList<>(); 1647 for (Module module : modules.values()) { 1648 if (module instanceof ServerFeaturesProvider) { 1649 answer.add((ServerFeaturesProvider) module); 1650 } 1651 } 1652 return answer; 1653 } 1654 1655 /** 1656 * Returns a list with all the modules that provide "discoverable" identities. 1657 * 1658 * @return a list with all the modules that provide "discoverable" identities. 1659 * @deprecated Use {@link IQDiscoInfoHandler} instead. 1660 */ 1661 @Deprecated getServerIdentitiesProviders()1662 public List<ServerIdentitiesProvider> getServerIdentitiesProviders() { 1663 List<ServerIdentitiesProvider> answer = new ArrayList<>(); 1664 for (Module module : modules.values()) { 1665 if (module instanceof ServerIdentitiesProvider) { 1666 answer.add((ServerIdentitiesProvider) module); 1667 } 1668 } 1669 return answer; 1670 } 1671 1672 /** 1673 * Returns a list with all the modules that provide "discoverable" items associated with 1674 * the server. 1675 * 1676 * @return a list with all the modules that provide "discoverable" items associated with 1677 * the server. 1678 * @deprecated Use {@link IQDiscoItemsHandler} instead. 1679 */ 1680 @Deprecated getServerItemsProviders()1681 public List<ServerItemsProvider> getServerItemsProviders() { 1682 List<ServerItemsProvider> answer = new ArrayList<>(); 1683 for (Module module : modules.values()) { 1684 if (module instanceof ServerItemsProvider) { 1685 answer.add((ServerItemsProvider) module); 1686 } 1687 } 1688 return answer; 1689 } 1690 1691 /** 1692 * Returns a list with all the modules that provide "discoverable" user identities. 1693 * 1694 * @return a list with all the modules that provide "discoverable" user identities. 1695 * @deprecated Use {@link IQDiscoInfoHandler} instead. 1696 */ 1697 @Deprecated getUserIdentitiesProviders()1698 public List<UserIdentitiesProvider> getUserIdentitiesProviders() { 1699 List<UserIdentitiesProvider> answer = new ArrayList<>(); 1700 for (Module module : modules.values()) { 1701 if (module instanceof UserIdentitiesProvider) { 1702 answer.add((UserIdentitiesProvider) module); 1703 } 1704 } 1705 return answer; 1706 } 1707 1708 /** 1709 * Returns a list with all the modules that provide "discoverable" items associated with 1710 * users. 1711 * 1712 * @return a list with all the modules that provide "discoverable" items associated with 1713 * users. 1714 * @deprecated Use {@link IQDiscoInfoHandler} instead. 1715 */ 1716 @Deprecated getUserItemsProviders()1717 public List<UserItemsProvider> getUserItemsProviders() { 1718 List<UserItemsProvider> answer = new ArrayList<>(); 1719 for (Module module : modules.values()) { 1720 if (module instanceof UserItemsProvider) { 1721 answer.add((UserItemsProvider) module); 1722 } 1723 } 1724 return answer; 1725 } 1726 1727 /** 1728 * Returns the <code>IQDiscoInfoHandler</code> registered with this server. The 1729 * <code>IQDiscoInfoHandler</code> was registered with the server as a module while starting up 1730 * the server. 1731 * 1732 * @return the <code>IQDiscoInfoHandler</code> registered with this server. 1733 */ getIQDiscoInfoHandler()1734 public IQDiscoInfoHandler getIQDiscoInfoHandler() { 1735 return (IQDiscoInfoHandler) modules.get(IQDiscoInfoHandler.class); 1736 } 1737 1738 /** 1739 * Returns the <code>IQDiscoItemsHandler</code> registered with this server. The 1740 * <code>IQDiscoItemsHandler</code> was registered with the server as a module while starting up 1741 * the server. 1742 * 1743 * @return the <code>IQDiscoItemsHandler</code> registered with this server. 1744 */ getIQDiscoItemsHandler()1745 public IQDiscoItemsHandler getIQDiscoItemsHandler() { 1746 return (IQDiscoItemsHandler) modules.get(IQDiscoItemsHandler.class); 1747 } 1748 1749 /** 1750 * Returns the <code>PrivateStorage</code> registered with this server. The 1751 * <code>PrivateStorage</code> was registered with the server as a module while starting up 1752 * the server. 1753 * 1754 * @return the <code>PrivateStorage</code> registered with this server. 1755 */ getPrivateStorage()1756 public PrivateStorage getPrivateStorage() { 1757 return (PrivateStorage) modules.get(PrivateStorage.class); 1758 } 1759 1760 /** 1761 * Returns the <code>MultiUserChatManager</code> registered with this server. The 1762 * <code>MultiUserChatManager</code> was registered with the server as a module while starting up 1763 * the server. 1764 * 1765 * @return the <code>MultiUserChatManager</code> registered with this server. 1766 */ getMultiUserChatManager()1767 public MultiUserChatManager getMultiUserChatManager() { 1768 return (MultiUserChatManager) modules.get(MultiUserChatManager.class); 1769 } 1770 1771 /** 1772 * Returns the <code>AdHocCommandHandler</code> registered with this server. The 1773 * <code>AdHocCommandHandler</code> was registered with the server as a module while starting up 1774 * the server. 1775 * 1776 * @return the <code>AdHocCommandHandler</code> registered with this server. 1777 */ getAdHocCommandHandler()1778 public AdHocCommandHandler getAdHocCommandHandler() { 1779 return (AdHocCommandHandler) modules.get(AdHocCommandHandler.class); 1780 } 1781 1782 /** 1783 * Returns the <code>FileTransferProxy</code> registered with this server. The 1784 * <code>FileTransferProxy</code> was registered with the server as a module while starting up 1785 * the server. 1786 * 1787 * @return the <code>FileTransferProxy</code> registered with this server. 1788 */ getFileTransferProxy()1789 public FileTransferProxy getFileTransferProxy() { 1790 return (FileTransferProxy) modules.get(FileTransferProxy.class); 1791 } 1792 1793 /** 1794 * Returns the <code>FileTransferManager</code> registered with this server. The 1795 * <code>FileTransferManager</code> was registered with the server as a module while starting up 1796 * the server. 1797 * 1798 * @return the <code>FileTransferProxy</code> registered with this server. 1799 */ getFileTransferManager()1800 public FileTransferManager getFileTransferManager() { 1801 return (FileTransferManager) modules.get(DefaultFileTransferManager.class); 1802 } 1803 1804 /** 1805 * Returns the <code>MediaProxyService</code> registered with this server. The 1806 * <code>MediaProxyService</code> was registered with the server as a module while starting up 1807 * the server. 1808 * 1809 * @return the <code>MediaProxyService</code> registered with this server. 1810 */ getMediaProxyService()1811 public MediaProxyService getMediaProxyService() { 1812 return (MediaProxyService) modules.get(MediaProxyService.class); 1813 } 1814 1815 /** 1816 * Returns the <code>VCardManager</code> registered with this server. The 1817 * <code>VCardManager</code> was registered with the server as a module while starting up 1818 * the server. 1819 * @return the <code>VCardManager</code> registered with this server. 1820 */ getVCardManager()1821 public VCardManager getVCardManager() { 1822 return VCardManager.getInstance(); 1823 } 1824 1825 /** 1826 * Returns the <code>InternalComponentManager</code> registered with this server. The 1827 * <code>InternalComponentManager</code> was registered with the server as a module while starting up 1828 * the server. 1829 * 1830 * @return the <code>InternalComponentManager</code> registered with this server. 1831 */ getComponentManager()1832 private InternalComponentManager getComponentManager() { 1833 return (InternalComponentManager) modules.get(InternalComponentManager.class); 1834 } 1835 1836 /** 1837 * Returns the <code>CertificateStoreManager</code> registered with this server. The 1838 * <code>CertificateStoreManager</code> was registered with the server as a module while starting up 1839 * the server. 1840 * 1841 * @return the <code>CertificateStoreManager</code> registered with this server. 1842 */ getCertificateStoreManager()1843 public CertificateStoreManager getCertificateStoreManager() { 1844 return (CertificateStoreManager) modules.get( CertificateStoreManager.class ); 1845 } 1846 /** 1847 * Returns the locator to use to find sessions hosted in other cluster nodes. When not running 1848 * in a cluster a {@code null} value is returned. 1849 * 1850 * @return the locator to use to find sessions hosted in other cluster nodes. 1851 */ getRemoteSessionLocator()1852 public RemoteSessionLocator getRemoteSessionLocator() { 1853 return remoteSessionLocator; 1854 } 1855 1856 /** 1857 * Sets the locator to use to find sessions hosted in other cluster nodes. When not running 1858 * in a cluster set a {@code null} value. 1859 * 1860 * @param remoteSessionLocator the locator to use to find sessions hosted in other cluster nodes. 1861 */ setRemoteSessionLocator(RemoteSessionLocator remoteSessionLocator)1862 public void setRemoteSessionLocator(RemoteSessionLocator remoteSessionLocator) { 1863 this.remoteSessionLocator = remoteSessionLocator; 1864 } 1865 1866 /** 1867 * Returns whether or not the server has been started. 1868 * 1869 * @return whether or not the server has been started. 1870 */ isStarted()1871 public boolean isStarted() { 1872 return started; 1873 } 1874 1875 /** 1876 * Asynchronously send a message to every administrator on the system. 1877 * 1878 * @param message The message to send 1879 * @return the future result of sending the message. 1880 */ sendMessageToAdmins(final String message)1881 public Future<?> sendMessageToAdmins(final String message) { 1882 return TaskEngine.getInstance().submit(() -> { 1883 final MessageRouter messageRouter = getMessageRouter(); 1884 final Collection<JID> admins = XMPPServer.getInstance().getAdmins(); 1885 final Message notification = new Message(); 1886 notification.setFrom(getServerInfo().getXMPPDomain()); 1887 notification.setBody(message); 1888 admins.forEach(jid -> { 1889 logger.debug("Sending message to admin [jid={}, message={}]", jid, message); 1890 notification.setTo(jid); 1891 messageRouter.route(notification); 1892 }); 1893 }); 1894 } 1895 } 1896