aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/com/juick/xmpp/s2s/XMPPComponent.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/juick/xmpp/s2s/XMPPComponent.java')
-rw-r--r--src/main/java/com/juick/xmpp/s2s/XMPPComponent.java211
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");
+ }
+}