1 11 12 package org.jivesoftware.messenger; 13 14 import org.xmpp.packet.JID; 15 import org.jivesoftware.messenger.roster.RosterManager; 16 import org.jivesoftware.messenger.user.UserManager; 17 import org.jivesoftware.messenger.handler.*; 18 import org.jivesoftware.messenger.transport.TransportHandler; 19 import org.jivesoftware.messenger.audit.AuditManager; 20 import org.jivesoftware.messenger.audit.spi.AuditManagerImpl; 21 import org.jivesoftware.messenger.disco.ServerFeaturesProvider; 22 import org.jivesoftware.messenger.disco.ServerItemsProvider; 23 import org.jivesoftware.messenger.disco.IQDiscoInfoHandler; 24 import org.jivesoftware.messenger.disco.IQDiscoItemsHandler; 25 import org.jivesoftware.messenger.muc.MultiUserChatServer; 26 import org.jivesoftware.messenger.muc.spi.MultiUserChatServerImpl; 27 import org.jivesoftware.messenger.spi.*; 28 import org.jivesoftware.messenger.container.Module; 29 import org.jivesoftware.messenger.container.PluginManager; 30 import org.jivesoftware.messenger.net.MulticastDNSService; 31 import org.jivesoftware.messenger.component.InternalComponentManager; 32 import org.jivesoftware.util.Version; 33 import org.jivesoftware.util.LocaleUtils; 34 import org.jivesoftware.util.Log; 35 import org.jivesoftware.util.JiveGlobals; 36 import org.jivesoftware.database.DbConnectionManager; 37 import org.dom4j.io.SAXReader; 38 import org.dom4j.Document; 39 40 import java.util.*; 41 import java.io.File ; 42 import java.io.FileNotFoundException ; 43 import java.io.IOException ; 44 import java.io.InputStream ; 45 import java.lang.reflect.Method ; 46 import java.sql.PreparedStatement ; 47 import java.sql.ResultSet ; 48 import java.sql.SQLException ; 49 50 65 public class XMPPServer { 66 67 private static XMPPServer instance; 68 69 private String name; 70 private Version version; 71 private Date startDate; 72 private Date stopDate; 73 private boolean initialized = false; 74 75 78 private Map<Class ,Module> modules = new HashMap<Class ,Module>(); 79 80 84 private File messengerHome; 85 private ClassLoader loader; 86 87 private PluginManager pluginManager; 88 private InternalComponentManager componentManager; 89 90 93 private boolean setupMode = true; 94 95 private static final String STARTER_CLASSNAME = 96 "org.jivesoftware.messenger.starter.ServerStarter"; 97 private static final String WRAPPER_CLASSNAME = 98 "org.tanukisoftware.wrapper.WrapperManager"; 99 100 105 public static XMPPServer getInstance() { 106 return instance; 107 } 108 109 112 public XMPPServer() { 113 if (instance != null) { 115 throw new IllegalStateException ("A server is already running"); 116 } 117 instance = this; 118 start(); 119 } 120 121 126 public XMPPServerInfo getServerInfo() { 127 if (!initialized) { 128 throw new IllegalStateException ("Not initialized yet"); 129 } 130 return new XMPPServerInfoImpl(name, version, startDate, stopDate, getConnectionManager()); 131 } 132 133 141 public boolean isLocal(JID jid) { 142 boolean local = false; 143 if (jid != null && name != null && name.equalsIgnoreCase(jid.getDomain())) { 144 local = true; 145 } 146 return local; 147 } 148 149 157 public boolean isRemote(JID jid) { 158 if (jid != null) { 159 String domain = jid.getDomain(); 160 if (!name.equals(domain) && componentManager.getComponent(domain) == null) { 161 return true; 162 } 163 } 164 return false; 165 } 166 167 174 public JID createJID(String username, String resource) { 175 return new JID(username, name, resource); 176 } 177 178 private void initialize() throws FileNotFoundException { 179 JiveGlobals.setConfigName("jive-messenger.xml"); 181 182 locateMessenger(); 183 184 name = JiveGlobals.getProperty("xmpp.domain"); 185 if (name == null) { 186 name = "127.0.0.1"; 187 } 188 189 version = new Version(2, 2, 0, Version.ReleaseStatus.Release, -1); 190 if ("true".equals(JiveGlobals.getXMLProperty("setup"))) { 191 setupMode = false; 192 } 193 194 if (isStandAlone()) { 195 Runtime.getRuntime().addShutdownHook(new ShutdownHookThread()); 196 } 197 198 loader = Thread.currentThread().getContextClassLoader(); 199 componentManager = InternalComponentManager.getInstance(); 200 201 initialized = true; 202 } 203 204 public void start() { 205 try { 206 initialize(); 207 208 if (!setupMode) { 210 verifyDataSource(); 211 loadModules(); 214 initModules(); 216 startModules(); 218 } 219 InternalComponentManager.getInstance().start(); 221 File pluginDir = new File (messengerHome, "plugins"); 222 pluginManager = new PluginManager(pluginDir); 223 pluginManager.start(); 224 225 227 List params = new ArrayList(); 228 params.add(version.getVersionString()); 229 params.add(JiveGlobals.formatDateTime(new Date())); 230 String startupBanner = LocaleUtils.getLocalizedString("startup.name", params); 231 Log.info(startupBanner); 232 System.out.println(startupBanner); 233 234 startDate = new Date(); 235 stopDate = null; 236 } 237 catch (Exception e) { 238 e.printStackTrace(); 239 Log.error(e); 240 System.out.println(LocaleUtils.getLocalizedString("startup.error")); 241 shutdownServer(); 242 } 243 } 244 245 private void loadModules() { 246 loadModule(RoutingTableImpl.class.getName()); 248 loadModule(AuditManagerImpl.class.getName()); 249 loadModule(RosterManager.class.getName()); 250 loadModule(PrivateStorage.class.getName()); 251 loadModule(PresenceManagerImpl.class.getName()); 253 loadModule(SessionManager.class.getName()); 254 loadModule(PacketRouter.class.getName()); 255 loadModule(IQRouter.class.getName()); 256 loadModule(MessageRouter.class.getName()); 257 loadModule(PresenceRouter.class.getName()); 258 loadModule(PacketTransporterImpl.class.getName()); 259 loadModule(PacketDelivererImpl.class.getName()); 260 loadModule(TransportHandler.class.getName()); 261 loadModule(OfflineMessageStrategy.class.getName()); 262 loadModule(OfflineMessageStore.class.getName()); 263 loadModule(IQAuthHandler.class.getName()); 265 loadModule(IQPrivateHandler.class.getName()); 266 loadModule(IQRegisterHandler.class.getName()); 267 loadModule(IQRosterHandler.class.getName()); 268 loadModule(IQTimeHandler.class.getName()); 269 loadModule(IQvCardHandler.class.getName()); 270 loadModule(IQVersionHandler.class.getName()); 271 loadModule(IQLastActivityHandler.class.getName()); 272 loadModule(PresenceSubscribeHandler.class.getName()); 273 loadModule(PresenceUpdateHandler.class.getName()); 274 loadModule(IQDiscoInfoHandler.class.getName()); 275 loadModule(IQDiscoItemsHandler.class.getName()); 276 loadModule(IQOfflineMessagesHandler.class.getName()); 277 loadModule(MultiUserChatServerImpl.class.getName()); 278 loadModule(MulticastDNSService.class.getName()); 279 loadModule(ConnectionManagerImpl.class.getName()); 282 } 283 284 289 private void loadModule(String module) { 290 Module mod = null; 291 try { 292 Class modClass = loader.loadClass(module); 293 mod = (Module)modClass.newInstance(); 294 this.modules.put(modClass, mod); 295 } 296 catch (Exception e) { 297 e.printStackTrace(); 298 Log.error(LocaleUtils.getLocalizedString("admin.error"), e); 299 } 300 } 301 302 private void initModules() { 303 for (Module module : modules.values()) { 304 boolean isInitialized = false; 305 try { 306 module.initialize(this); 307 isInitialized = true; 308 } 309 catch (Exception e) { 310 e.printStackTrace(); 311 this.modules.remove(module.getClass()); 313 if (isInitialized) { 314 module.stop(); 315 module.destroy(); 316 } 317 Log.error(LocaleUtils.getLocalizedString("admin.error"), e); 318 } 319 } 320 } 321 322 327 private void startModules() { 328 for (Module module : modules.values()) { 329 boolean started = false; 330 try { 331 module.start(); 332 } 333 catch (Exception e) { 334 if (started && module != null) { 335 module.stop(); 336 module.destroy(); 337 } 338 Log.error(LocaleUtils.getLocalizedString("admin.error"), e); 339 } 340 } 341 } 342 343 347 public void restart() { 348 if (isStandAlone() && isRestartable()) { 349 try { 350 Class wrapperClass = Class.forName(WRAPPER_CLASSNAME); 351 Method restartMethod = wrapperClass.getMethod("restart", (Class [])null); 352 restartMethod.invoke(null, (Object [])null); 353 } 354 catch (Exception e) { 355 Log.error("Could not restart container", e); 356 } 357 } 358 } 359 360 364 public void stop() { 365 if (isStandAlone()) { 367 if (isRestartable()) { 369 try { 370 Class wrapperClass = Class.forName(WRAPPER_CLASSNAME); 371 Method stopMethod = wrapperClass.getMethod("stop", new Class []{Integer.TYPE}); 372 stopMethod.invoke(null, new Object []{0}); 373 } 374 catch (Exception e) { 375 Log.error("Could not stop container", e); 376 } 377 } 378 else { 379 shutdownServer(); 380 stopDate = new Date(); 381 Thread shutdownThread = new ShutdownThread(); 382 shutdownThread.setDaemon(true); 383 shutdownThread.start(); 384 } 385 } 386 } 387 388 public boolean isSetupMode() { 389 return setupMode; 390 } 391 392 public boolean isRestartable() { 393 boolean restartable = false; 394 try { 395 restartable = Class.forName(WRAPPER_CLASSNAME) != null; 396 } 397 catch (ClassNotFoundException e) { 398 restartable = false; 399 } 400 return restartable; 401 } 402 403 410 public boolean isStandAlone() { 411 boolean standalone = false; 412 try { 413 standalone = Class.forName(STARTER_CLASSNAME) != null; 414 } 415 catch (ClassNotFoundException e) { 416 standalone = false; 417 } 418 return standalone; 419 } 420 421 424 private void verifyDataSource() { 425 java.sql.Connection conn = null; 426 try { 427 conn = DbConnectionManager.getConnection(); 428 PreparedStatement stmt = conn.prepareStatement("SELECT count(*) FROM jiveID"); 429 ResultSet rs = stmt.executeQuery(); 430 rs.next(); 431 rs.close(); 432 stmt.close(); 433 } 434 catch (Exception e) { 435 System.err.println("Database setup or configuration error: " + 436 "Please verify your database settings and check the " + 437 "logs/error.log file for detailed error messages."); 438 Log.error("Database could not be accessed", e); 439 throw new IllegalArgumentException (e); 440 } 441 finally { 442 if (conn != null) { 443 try { conn.close(); } 444 catch (SQLException e) { Log.error(e); } 445 } 446 } 447 } 448 449 461 private File verifyHome(String homeGuess, String jiveConfigName) throws FileNotFoundException { 462 File realHome = null; 463 File guess = new File (homeGuess); 464 File configFileGuess = new File (guess, jiveConfigName); 465 if (configFileGuess.exists()) { 466 realHome = guess; 467 } 468 File messengerHome = new File (guess, jiveConfigName); 469 if (!messengerHome.exists()) { 470 throw new FileNotFoundException (); 471 } 472 473 try{ 474 return new File (realHome.getCanonicalPath()); 475 } 476 catch(Exception ex){ 477 throw new FileNotFoundException (); 478 } 479 } 480 481 486 private void locateMessenger() throws FileNotFoundException { 487 String jiveConfigName = "conf" + File.separator + "jive-messenger.xml"; 488 if (messengerHome == null) { 490 String homeProperty = System.getProperty("messengerHome"); 491 try { 492 if (homeProperty != null) { 493 messengerHome = verifyHome(homeProperty, jiveConfigName); 494 } 495 } 496 catch (FileNotFoundException fe) { 497 498 } 499 } 500 501 if (messengerHome == null) { 505 try { 506 messengerHome = verifyHome("..", jiveConfigName).getCanonicalFile(); 507 } 508 catch (FileNotFoundException fe) { 509 } 510 catch (IOException ie) { 511 } 512 } 513 514 if (messengerHome == null) { 518 InputStream in = null; 519 try { 520 in = getClass().getResourceAsStream("/messenger_init.xml"); 521 if (in != null) { 522 SAXReader reader = new SAXReader(); 523 Document doc = reader.read(in); 524 String path = doc.getRootElement().getText(); 525 try { 526 if (path != null) { 527 messengerHome = verifyHome(path, jiveConfigName); 528 } 529 } 530 catch (FileNotFoundException fe) { 531 fe.printStackTrace(); 532 } 533 } 534 } 535 catch (Exception e) { 536 System.err.println("Error loading messenger_init.xml to find home."); 537 e.printStackTrace(); 538 } 539 finally { 540 try { if (in != null) { in.close(); } } 541 catch (Exception e) { 542 System.err.println("Could not close open connection"); 543 e.printStackTrace(); 544 } 545 } 546 } 547 548 if (messengerHome == null) { 549 System.err.println("Could not locate home"); 550 throw new FileNotFoundException (); 551 } 552 else { 553 JiveGlobals.home = messengerHome.toString(); 554 } 555 } 556 557 564 private class ShutdownHookThread extends Thread { 565 568 public void run() { 569 shutdownServer(); 570 Log.info("Server halted"); 571 System.err.println("Server halted"); 572 } 573 } 574 575 582 private class ShutdownThread extends Thread { 583 586 public void run() { 587 try { 588 Thread.sleep(5000); 589 System.exit(0); 591 } 592 catch (InterruptedException e) { 593 } 594 595 } 596 } 597 598 601 private void shutdownServer() { 602 if (modules.isEmpty()) { 604 return; 605 } 606 for (Module module : modules.values()) { 608 module.stop(); 609 module.destroy(); 610 } 611 modules.clear(); 612 if (pluginManager != null) { 614 pluginManager.shutdown(); 615 } 616 DbConnectionManager.getConnectionProvider().destroy(); 618 Log.info("Jive Messenger stopped"); 620 } 621 622 629 public ConnectionManager getConnectionManager() { 630 return (ConnectionManager) modules.get(ConnectionManagerImpl.class); 631 } 632 633 640 public RoutingTable getRoutingTable() { 641 return (RoutingTable) modules.get(RoutingTableImpl.class); 642 } 643 644 651 public PacketDeliverer getPacketDeliverer() { 652 return (PacketDeliverer) modules.get(PacketDelivererImpl.class); 653 } 654 655 662 public RosterManager getRosterManager() { 663 return (RosterManager) modules.get(RosterManager.class); 664 } 665 666 673 public PresenceManager getPresenceManager() { 674 return (PresenceManager) modules.get(PresenceManagerImpl.class); 675 } 676 677 684 public OfflineMessageStore getOfflineMessageStore() { 685 return (OfflineMessageStore) modules.get(OfflineMessageStore.class); 686 } 687 688 695 public OfflineMessageStrategy getOfflineMessageStrategy() { 696 return (OfflineMessageStrategy)modules.get(OfflineMessageStrategy.class); 697 } 698 699 706 public PacketRouter getPacketRouter() { 707 return (PacketRouter)modules.get(PacketRouter.class); 708 } 709 710 717 public IQRegisterHandler getIQRegisterHandler() { 718 return (IQRegisterHandler)modules.get(IQRegisterHandler.class); 719 } 720 721 726 public PluginManager getPluginManager() { 727 return pluginManager; 728 } 729 730 735 public List<IQHandler> getIQHandlers() { 736 List<IQHandler> answer = new ArrayList<IQHandler>(); 737 for (Module module : modules.values()) { 738 if (module instanceof IQHandler) { 739 answer.add((IQHandler)module); 740 } 741 } 742 return answer; 743 } 744 745 752 public SessionManager getSessionManager() { 753 return (SessionManager) modules.get(SessionManager.class); 754 } 755 756 763 public TransportHandler getTransportHandler() { 764 return (TransportHandler) modules.get(TransportHandler.class); 765 } 766 767 774 public PresenceUpdateHandler getPresenceUpdateHandler() { 775 return (PresenceUpdateHandler) modules.get(PresenceUpdateHandler.class); 776 } 777 778 785 public PresenceSubscribeHandler getPresenceSubscribeHandler() { 786 return (PresenceSubscribeHandler) modules.get(PresenceSubscribeHandler.class); 787 } 788 789 796 public IQRouter getIQRouter() { 797 return (IQRouter) modules.get(IQRouter.class); 798 } 799 800 807 public MessageRouter getMessageRouter() { 808 return (MessageRouter) modules.get(MessageRouter.class); 809 } 810 811 818 public PresenceRouter getPresenceRouter() { 819 return (PresenceRouter) modules.get(PresenceRouter.class); 820 } 821 822 829 public UserManager getUserManager() { 830 return UserManager.getInstance(); 831 } 832 833 840 public AuditManager getAuditManager() { 841 return (AuditManager) modules.get(AuditManagerImpl.class); 842 } 843 844 849 public List<ServerFeaturesProvider> getServerFeaturesProviders() { 850 List<ServerFeaturesProvider> answer = new ArrayList<ServerFeaturesProvider>(); 851 for (Module module : modules.values()) { 852 if (module instanceof ServerFeaturesProvider) { 853 answer.add((ServerFeaturesProvider) module); 854 } 855 } 856 return answer; 857 } 858 859 866 public List<ServerItemsProvider> getServerItemsProviders() { 867 List<ServerItemsProvider> answer = new ArrayList<ServerItemsProvider>(); 868 for (Module module : modules.values()) { 869 if (module instanceof ServerItemsProvider) { 870 answer.add((ServerItemsProvider) module); 871 } 872 } 873 return answer; 874 } 875 876 883 public IQDiscoInfoHandler getIQDiscoInfoHandler() { 884 return (IQDiscoInfoHandler) modules.get(IQDiscoInfoHandler.class); 885 } 886 887 894 public IQDiscoItemsHandler getIQDiscoItemsHandler() { 895 return (IQDiscoItemsHandler) modules.get(IQDiscoItemsHandler.class); 896 } 897 898 905 public PrivateStorage getPrivateStorage() { 906 return (PrivateStorage) modules.get(PrivateStorage.class); 907 } 908 909 916 public MultiUserChatServer getMultiUserChatServer() { 917 return (MultiUserChatServer) modules.get(MultiUserChatServerImpl.class); 918 } 919 } 920 | Popular Tags |