diff options
Diffstat (limited to 'src/main/java/com/juick/xmpp/s2s/XMPPComponent.java')
-rw-r--r-- | src/main/java/com/juick/xmpp/s2s/XMPPComponent.java | 211 |
1 files changed, 211 insertions, 0 deletions
diff --git a/src/main/java/com/juick/xmpp/s2s/XMPPComponent.java b/src/main/java/com/juick/xmpp/s2s/XMPPComponent.java new file mode 100644 index 00000000..ff4ec3e6 --- /dev/null +++ b/src/main/java/com/juick/xmpp/s2s/XMPPComponent.java @@ -0,0 +1,211 @@ +package com.juick.xmpp.s2s; + +import com.juick.xmpp.Stanza; +import com.juick.xmpp.StanzaChild; +import com.juick.xmpp.extensions.JuickMessage; + +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; +import java.io.FileInputStream; +import java.io.IOException; +import java.sql.Driver; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.util.*; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * + * @author ugnich + */ +public class XMPPComponent implements ServletContextListener { + + private static final Logger LOGGER = Logger.getLogger(XMPPComponent.class.getName()); + + ExecutorService executorService; + + public static String HOSTNAME = null; + public static String COMPONENTNAME = null; + public static String LOGFILE = null; + public static String STATSFILE = null; + public static ConnectionRouter connRouter; + static final List<ConnectionIn> inConnections = Collections.synchronizedList(new ArrayList<>()); + static final List<ConnectionOut> outConnections = Collections.synchronizedList(new ArrayList<>()); + static final List<CacheEntry> outCache = Collections.synchronizedList(new ArrayList<>()); + static final Integer sqlSync = 0; + static java.sql.Connection sql; + final public static HashMap<String, StanzaChild> childParsers = new HashMap<>(); + + public static void addConnectionIn(ConnectionIn c) { + synchronized (inConnections) { + inConnections.add(c); + } + } + + public static void addConnectionOut(ConnectionOut c) { + synchronized (outConnections) { + outConnections.add(c); + } + } + + public static void removeConnectionIn(ConnectionIn c) { + synchronized (inConnections) { + inConnections.remove(c); + } + } + + public static void removeConnectionOut(ConnectionOut c) { + synchronized (outConnections) { + outConnections.remove(c); + } + } + + public static String getFromCache(String hostname) { + CacheEntry ret = null; + synchronized (outCache) { + for (Iterator<CacheEntry> i = outCache.iterator(); i.hasNext();) { + CacheEntry c = i.next(); + if (c.hostname != null && c.hostname.equals(hostname)) { + ret = c; + i.remove(); + break; + } + } + } + return (ret != null) ? ret.xml : null; + } + + public static ConnectionOut getConnectionOut(String hostname, boolean needReady) { + synchronized (outConnections) { + for (ConnectionOut c : outConnections) { + if (c.to != null && c.to.equals(hostname) && (!needReady || c.streamReady)) { + return c; + } + } + } + return null; + } + + public static ConnectionIn getConnectionIn(String streamID) { + synchronized (inConnections) { + for (ConnectionIn c : inConnections) { + if (c.streamID != null && c.streamID.equals(streamID)) { + return c; + } + } + } + return null; + } + + public static void sendOut(Stanza s) { + sendOut(s.to.Host, s.toString()); + } + + public static void sendOut(String hostname, String xml) { + boolean haveAnyConn = false; + + ConnectionOut connOut = null; + synchronized (outConnections) { + for (ConnectionOut c : outConnections) { + if (c.to != null && c.to.equals(hostname)) { + if (c.streamReady) { + connOut = c; + break; + } else { + haveAnyConn = true; + break; + } + } + } + } + if (connOut != null) { + try { + connOut.sendStanza(xml); + } catch (IOException e) { + System.err.println("STREAM TO " + connOut.to + " " + connOut.streamID + " ERROR: " + e.toString()); + } + return; + } + + boolean haveCache = false; + synchronized (outCache) { + for (CacheEntry c : outCache) { + if (c.hostname != null && c.hostname.equals(hostname)) { + c.xml += xml; + c.tsUpdated = System.currentTimeMillis(); + haveCache = true; + break; + } + } + if (!haveCache) { + outCache.add(new CacheEntry(hostname, xml)); + } + } + + if (!haveAnyConn) { + new Thread(new ConnectionOut(hostname)).start(); + } + } + + @Override + public void contextInitialized(ServletContextEvent sce) { + + LOGGER.info("component initialized"); + executorService = Executors.newSingleThreadExecutor(); + executorService.submit(() -> { + Properties conf = new Properties(); + try { + conf.load(new FileInputStream("/etc/juick/s2s.conf")); + HOSTNAME = conf.getProperty("hostname"); + COMPONENTNAME = conf.getProperty("componentname"); + LOGFILE = conf.getProperty("logfile"); + STATSFILE = conf.getProperty("statsfile"); + + Class.forName("com.mysql.jdbc.Driver"); + sql = DriverManager.getConnection("jdbc:mysql://localhost/juick?autoReconnect=true&user=" + conf.getProperty("mysql_username", "") + "&password=" + conf.getProperty("mysql_password", "")); + + Runtime.getRuntime().addShutdownHook(new Shutdown()); + + childParsers.put(JuickMessage.XMLNS, new JuickMessage()); + + connRouter = new ConnectionRouter(); + new Thread(connRouter).start(); + new Thread(new ConnectionListener()).start(); + new Thread(new CleaningUp()).start(); + } catch (IOException | ClassNotFoundException | SQLException e) { + LOGGER.log(Level.SEVERE, "XMPPComponent error", e); + } + }); + } + + + + @Override + public void contextDestroyed(ServletContextEvent sce) { + // Now deregister JDBC drivers in this context's ClassLoader: + // Get the webapp's ClassLoader + ClassLoader cl = Thread.currentThread().getContextClassLoader(); + // Loop through all drivers + Enumeration<Driver> drivers = DriverManager.getDrivers(); + while (drivers.hasMoreElements()) { + Driver driver = drivers.nextElement(); + if (driver.getClass().getClassLoader() == cl) { + // This driver was registered by the webapp's ClassLoader, so deregister it: + try { + LOGGER.info(String.format("Deregistering JDBC driver %s", driver.toString())); + DriverManager.deregisterDriver(driver); + } catch (SQLException ex) { + LOGGER.log(Level.SEVERE, String.format("Error deregistering JDBC driver %s", driver), ex); + } + } else { + // driver was not registered by the webapp's ClassLoader and may be in use elsewhere + LOGGER.log(Level.SEVERE, String.format("Not deregistering JDBC driver %s as it does not belong to this webapp's ClassLoader", driver)); + } + } + executorService.shutdown(); + LOGGER.info("component destroyed"); + } +} |