summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsnowleo <schneeleo@gmail.com>2011-07-07 18:54:25 +0200
committersnowleo <schneeleo@gmail.com>2011-07-07 18:54:25 +0200
commitd02380edba4f8f8e57483d74027569210d44f8e3 (patch)
tree9c760674dca84c15528658dae70d2e6e0b7bd439
parentdb03b3c09eb6a7149392a3cf5b0f3d1eecf8c21b (diff)
downloadEssentials-d02380edba4f8f8e57483d74027569210d44f8e3.tar
Essentials-d02380edba4f8f8e57483d74027569210d44f8e3.tar.gz
Essentials-d02380edba4f8f8e57483d74027569210d44f8e3.tar.lz
Essentials-d02380edba4f8f8e57483d74027569210d44f8e3.tar.xz
Essentials-d02380edba4f8f8e57483d74027569210d44f8e3.zip
Prevent loops generated by logging directly to xmpp
-rw-r--r--EssentialsXMPP/src/com/earth2me/essentials/xmpp/XMPPManager.java145
1 files changed, 117 insertions, 28 deletions
diff --git a/EssentialsXMPP/src/com/earth2me/essentials/xmpp/XMPPManager.java b/EssentialsXMPP/src/com/earth2me/essentials/xmpp/XMPPManager.java
index fb0145ee4..4ad3ad35d 100644
--- a/EssentialsXMPP/src/com/earth2me/essentials/xmpp/XMPPManager.java
+++ b/EssentialsXMPP/src/com/earth2me/essentials/xmpp/XMPPManager.java
@@ -7,8 +7,10 @@ import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
@@ -35,11 +37,14 @@ public class XMPPManager extends Handler implements MessageListener, ChatManager
private transient XMPPConnection connection;
private transient ChatManager chatManager;
private final transient Map<String, Chat> chats = Collections.synchronizedMap(new HashMap<String, Chat>());
+ private final transient Set<LogRecord> logrecords = Collections.synchronizedSet(new HashSet<LogRecord>());
private final transient JavaPlugin parent;
private transient List<String> logUsers;
private transient Level logLevel;
private transient boolean ignoreLagMessages = true;
-
+ private transient Thread loggerThread;
+ private transient boolean threadrunning = true;
+
public XMPPManager(final JavaPlugin parent)
{
super();
@@ -48,18 +53,23 @@ public class XMPPManager extends Handler implements MessageListener, ChatManager
config.setTemplateName("/config.yml", EssentialsXMPP.class);
reloadConfig();
}
-
- public void sendMessage(final String address, final String message)
+
+ public boolean sendMessage(final String address, final String message)
{
if (address != null && !address.isEmpty())
{
try
{
startChat(address);
- final Chat chat = chats.get(address);
+ final Chat chat;
+ synchronized (chats)
+ {
+ chat = chats.get(address);
+ }
if (chat != null)
{
chat.sendMessage(message.replaceAll("ยง[0-9a-f]", ""));
+ return true;
}
}
catch (XMPPException ex)
@@ -67,8 +77,9 @@ public class XMPPManager extends Handler implements MessageListener, ChatManager
disableChat(address);
}
}
+ return false;
}
-
+
@Override
public void processMessage(final Chat chat, final Message msg)
{
@@ -90,14 +101,14 @@ public class XMPPManager extends Handler implements MessageListener, ChatManager
}
}
}
-
- private void connect()
+
+ private boolean connect()
{
final String server = config.getString("xmpp.server");
if (server == null || server.equals("example.com"))
{
LOGGER.log(Level.WARNING, "config broken for xmpp");
- return;
+ return false;
}
final int port = config.getInt("xmpp.port", 5222);
final String serviceName = config.getString("xmpp.servicename", server);
@@ -119,21 +130,33 @@ public class XMPPManager extends Handler implements MessageListener, ChatManager
connection.getRoster().setSubscriptionMode(SubscriptionMode.accept_all);
chatManager = connection.getChatManager();
chatManager.addChatListener(this);
+ return true;
}
catch (XMPPException ex)
{
LOGGER.log(Level.WARNING, "Failed to connect to server: " + server, ex);
+ return false;
}
}
-
+
public final void disconnect()
{
+ if (loggerThread != null)
+ {
+ loggerThread.interrupt();
+ }
+ if (chatManager != null)
+ {
+ chatManager.removeChatListener(this);
+ chatManager = null;
+ }
if (connection != null)
{
connection.disconnect(new Presence(Presence.Type.unavailable));
}
+
}
-
+
@Override
public void chatCreated(final Chat chat, final boolean createdLocally)
{
@@ -147,18 +170,22 @@ public class XMPPManager extends Handler implements MessageListener, ChatManager
}
}
}
-
+
@Override
public final void reloadConfig()
{
+ LOGGER.removeHandler(this);
config.load();
synchronized (chats)
{
disconnect();
chats.clear();
- connect();
+ if (!connect())
+ {
+ return;
+ }
+ startLoggerThread();
}
- LOGGER.removeHandler(this);
if (config.getBoolean("log-enabled", false))
{
LOGGER.addHandler(this);
@@ -175,7 +202,7 @@ public class XMPPManager extends Handler implements MessageListener, ChatManager
ignoreLagMessages = config.getBoolean("ignore-lag-messages", true);
}
}
-
+
@Override
public void publish(final LogRecord logRecord)
{
@@ -187,14 +214,9 @@ public class XMPPManager extends Handler implements MessageListener, ChatManager
}
if (logRecord.getLevel().intValue() >= logLevel.intValue())
{
- for (String user : logUsers)
+ synchronized (logrecords)
{
- startChat(user);
- final Chat chat = chats.get(user);
- if (chat != null)
- {
- chat.sendMessage(String.format("[" + logRecord.getLevel().getLocalizedName() + "] " + logRecord.getMessage(), logRecord.getParameters()));
- }
+ logrecords.add(logRecord);
}
}
}
@@ -204,19 +226,86 @@ public class XMPPManager extends Handler implements MessageListener, ChatManager
// Otherwise we create a loop.
}
}
-
+
@Override
public void flush()
{
// Ignore this
}
-
+
@Override
public void close() throws SecurityException
{
// Ignore this
}
-
+
+ private void startLoggerThread()
+ {
+ loggerThread = new Thread(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ final Set<LogRecord> copy = new HashSet<LogRecord>();
+ final Set<String> failedUsers = new HashSet<String>();
+ while (threadrunning)
+ {
+ synchronized (logrecords)
+ {
+ if (!logrecords.isEmpty())
+ {
+ copy.addAll(logrecords);
+ logrecords.clear();
+ }
+ }
+ if (!copy.isEmpty())
+ {
+ for (String user : logUsers)
+ {
+ try
+ {
+ XMPPManager.this.startChat(user);
+ for (LogRecord logRecord : copy)
+ {
+ final String message = String.format("[" + logRecord.getLevel().getLocalizedName() + "] " + logRecord.getMessage(), logRecord.getParameters());
+ if (!XMPPManager.this.sendMessage(user, message))
+ {
+ failedUsers.add(user);
+ break;
+ }
+
+ }
+ }
+ catch (XMPPException ex)
+ {
+ failedUsers.add(user);
+ LOGGER.removeHandler(XMPPManager.this);
+ LOGGER.log(Level.SEVERE, "Failed to deliver log message! Disabling logging to XMPP.", ex);
+ }
+ }
+ logUsers.removeAll(failedUsers);
+ if (logUsers.isEmpty())
+ {
+ LOGGER.removeHandler(XMPPManager.this);
+ threadrunning = false;
+ }
+ copy.clear();
+ }
+ try
+ {
+ Thread.sleep(2000);
+ }
+ catch (InterruptedException ex)
+ {
+ threadrunning = false;
+ }
+ }
+ LOGGER.removeHandler(XMPPManager.this);
+ }
+ });
+ loggerThread.start();
+ }
+
private void startChat(final String address) throws XMPPException
{
if (chatManager == null)
@@ -236,14 +325,14 @@ public class XMPPManager extends Handler implements MessageListener, ChatManager
}
}
}
-
+
private void sendPrivateMessage(final Chat chat, final String message)
{
final String[] parts = message.split(" ", 2);
if (parts.length == 2)
{
final List<Player> matches = parent.getServer().matchPlayer(parts[0].substring(1));
-
+
if (matches.isEmpty())
{
try
@@ -265,7 +354,7 @@ public class XMPPManager extends Handler implements MessageListener, ChatManager
}
}
}
-
+
private void sendCommand(final Chat chat, final String message)
{
if (config.getStringList("op-users", new ArrayList<String>()).contains(StringUtils.parseBareAddress(chat.getParticipant())))
@@ -280,7 +369,7 @@ public class XMPPManager extends Handler implements MessageListener, ChatManager
}
}
}
-
+
private void disableChat(final String address)
{
final Chat chat = chats.get(address);