Notification application (without options dialog)

git-svn-id: https://webim.svn.sourceforge.net/svnroot/webim/trunk@734 c66351dc-e62f-0410-b875-e3a5c0b9693f
This commit is contained in:
Evgeny Gryaznov 2010-01-23 10:35:54 +00:00
parent ecb7d3643f
commit 01217e6b7d
12 changed files with 378 additions and 44 deletions

View File

@ -45,10 +45,14 @@ public class MibewAgent {
return fThread.isOnline();
}
private void logError(String message, Throwable th) {
protected void logError(String message, Throwable th) {
System.err.println(message);
}
public MibewAgentOptions getOptions() {
return fOptions;
}
private class MibewUpdateThread extends Thread {
private volatile boolean fExiting;
@ -114,17 +118,21 @@ public class MibewAgent {
});
long maxTime = System.currentTimeMillis() + fOptions.getConnectionRefreshTimeout()*1000;
int errorsCount = 0;
while(!fExiting && (System.currentTimeMillis() < maxTime)) {
try {
createdThreads.clear();
mt.update();
fListener.updated(mt.getThreads(), createdThreads.toArray(new MibewThread[createdThreads.size()]));
} catch (Exception e) {
errorsCount = 0;
setOnline(true);
} catch (Throwable th) {
setOnline(false);
interruptableSleep(fOptions.getPollingInterval() / 2);
errorsCount++;
logError("not updated", th);
interruptableSleep(errorsCount < 10 ? fOptions.getPollingInterval() / 2 : fOptions.getPollingInterval() * 2);
continue;
}
setOnline(true);
interruptableSleep(fOptions.getPollingInterval());
}

View File

@ -1,5 +1,8 @@
package org.mibew.api;
import java.io.IOException;
import java.util.Properties;
/**
* @author inspirer
*/
@ -8,8 +11,8 @@ public class MibewAgentOptions {
private String fUrl;
private String fLogin;
private String fPassword;
private int fConnectionRefreshTimeout = 900; // 15 minutes
private int fPollingInterval = 3000; // 2 sec
private int fConnectionRefreshTimeout = 900; // in seconds (15 minutes by default)
private int fPollingInterval = 2000; // 2 sec (in milliseconds)
public MibewAgentOptions(String fUrl, String fLogin, String fPassword) {
super();
@ -37,4 +40,23 @@ public class MibewAgentOptions {
public int getPollingInterval() {
return fPollingInterval;
}
private static String getProperty(Properties p, String name, String defaultValue) throws IOException {
String result = p.getProperty(name);
if(result == null || result.trim().length() == 0) {
if(defaultValue != null) {
return defaultValue;
}
throw new IOException("No '"+name+"' property");
}
return result;
}
public static MibewAgentOptions create(Properties p) throws IOException {
String url = getProperty(p, "mibew.host", null);
String login = getProperty(p, "mibew.login", null);
String password = getProperty(p, "mibew.password", null);
return new MibewAgentOptions(url, login, password);
}
}

View File

@ -1,20 +1,23 @@
package org.mibew.api;
import java.text.MessageFormat;
/**
* @author inspirer
*/
public class MibewThread {
public class MibewThread implements Comparable<MibewThread> {
public final long fId;
public String fState;
public String fClientName = "";
public String fAgent = "";
public String fAddress = "";
public String fFirstMessage = "";
public boolean fCanOpen = false;
public boolean fCanView = false;
public boolean fCanBan = false;
public String fStateText;
private final long fId;
private String fState;
private String fClientName = "";
private String fAgent = "";
private String fAddress = "";
private String fFirstMessage = "";
private boolean fCanOpen = false;
private boolean fCanView = false;
private boolean fCanBan = false;
private String fStateText;
private long fWaitingTime;
public MibewThread(long id, String state) {
fId = id;
@ -34,5 +37,138 @@ public class MibewThread {
fCanView = updated.fCanView;
fCanBan = updated.fCanBan;
fStateText = updated.fStateText;
fWaitingTime = updated.fWaitingTime;
}
public long getId() {
return fId;
}
public String getState() {
return fState;
}
public String getStateText() {
return fStateText;
}
public void setStateText(String stateText) {
fStateText = stateText;
}
public String getAddress() {
return fAddress;
}
public void setAddress(String address) {
fAddress = address;
}
public String getAgent() {
return fAgent;
}
public void setAgent(String agent) {
fAgent = agent;
}
public String getClientName() {
return fClientName;
}
public void setClientName(String clientName) {
fClientName = clientName;
}
public String getFirstMessage() {
return fFirstMessage;
}
public void setFirstMessage(String firstMessage) {
fFirstMessage = firstMessage;
}
public boolean isCanBan() {
return fCanBan;
}
public void setCanBan(boolean canBan) {
fCanBan = canBan;
}
public boolean isCanOpen() {
return fCanOpen;
}
public void setCanOpen(boolean canOpen) {
fCanOpen = canOpen;
}
public boolean isCanView() {
return fCanView;
}
public void setCanView(boolean canView) {
fCanView = canView;
}
public long getWaitingTime() {
return fWaitingTime;
}
public void setWaitingTime(long value) {
fWaitingTime = value;
}
@Override
public int compareTo(MibewThread o) {
int res = index(this).compareTo(index(o));
if(res != 0) {
return res;
}
return getClientName().compareTo(o.getClientName());
}
private Integer index(MibewThread th) {
if("prio".equals(th.getState())) {
return -1;
}
if("wait".equals(th.getState())) {
return 0;
}
return 1;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
boolean isChat = "chat".equals(getState());
if(isChat) {
sb.append("(chat) ");
}
sb.append(getClientName());
if(!isCanOpen() && isCanView()) {
sb.append(" (view only)");
}
if(!isChat) {
sb.append(" - ");
sb.append(formatWaitingTime((System.currentTimeMillis() - getWaitingTime())/1000));
}
return sb.toString();
}
private static String atLeast2(long i) {
return i < 10 ? "0" + i : Long.toString(i);
}
private static String formatWaitingTime(long time) {
String s = atLeast2(time/60%60) + ":" + atLeast2(time%60);
if(time >= 3600) {
s = atLeast2(time/3600%24) + ":" + s;
if(time >= 24*3600) {
s = time/24/3600 + "d, " + s;
}
}
return s;
}
}

View File

@ -57,15 +57,15 @@ public class MibewTracker {
private void processUpdate(List<MibewThread> updated) {
for (MibewThread mt : updated) {
MibewThread existing = fThreads.get(mt.fId);
boolean isClosed = mt.fState.equals("closed");
MibewThread existing = fThreads.get(mt.getId());
boolean isClosed = mt.getState().equals("closed");
if (existing == null) {
if (!isClosed) {
fThreads.put(mt.fId, mt);
fThreads.put(mt.getId(), mt);
fListener.threadCreated(mt);
}
} else if (isClosed) {
fThreads.remove(mt.fId);
fThreads.remove(mt.getId());
fListener.threadClosed(existing);
} else {
existing.updateFrom(mt);

View File

@ -48,10 +48,10 @@ public class UpdateHandler extends DefaultHandler {
fCurrentThread = new MibewThread(id, stateid);
if(!stateid.equals("closed")) {
fCurrentThread.fStateText = attributes.getValue("state");
fCurrentThread.fCanOpen = booleanAttribute(attributes.getValue("canopen"));
fCurrentThread.fCanView = booleanAttribute(attributes.getValue("canview"));
fCurrentThread.fCanBan = booleanAttribute(attributes.getValue("canban"));
fCurrentThread.setStateText(attributes.getValue("state"));
fCurrentThread.setCanOpen(booleanAttribute(attributes.getValue("canopen")));
fCurrentThread.setCanView(booleanAttribute(attributes.getValue("canview")));
fCurrentThread.setCanBan(booleanAttribute(attributes.getValue("canban")));
}
}
@ -68,6 +68,14 @@ public class UpdateHandler extends DefaultHandler {
return false;
}
private long longValue(String value) throws SAXException {
try {
return Long.parseLong(value);
} catch(NumberFormatException ex) {
throw new SAXException(ex);
}
}
@Override
public void endElement(String uri, String localName, String name)
throws SAXException {
@ -99,13 +107,18 @@ public class UpdateHandler extends DefaultHandler {
String subvar = fPath.peek();
String value = new String(ch, start, length);
if("name".equals(subvar)) {
fCurrentThread.fClientName += value;
fCurrentThread.setClientName(fCurrentThread.getClientName() + value);
} else if("addr".equals(subvar)) {
fCurrentThread.fAddress += value;
fCurrentThread.setAddress(fCurrentThread.getAddress() + value);
} else if("message".equals(subvar)) {
fCurrentThread.fFirstMessage += value;
fCurrentThread.setFirstMessage(fCurrentThread.getFirstMessage() + value);
} else if("agent".equals(subvar)) {
fCurrentThread.fAgent += value;
fCurrentThread.setAgent(fCurrentThread.getAgent() + value);
} else if("modified".equals(subvar)) {
if(fCurrentThread.getWaitingTime() != 0) {
throw new SAXException("error: waiting time is already set");
}
fCurrentThread.setWaitingTime(longValue(value) - fTime + System.currentTimeMillis());
}
// TODO

View File

@ -49,7 +49,7 @@ public class Application {
@Override
public void threadCreated(MibewThread thread) {
try {
chat.sendMessage(thread.fId + ": " + thread.fAddress + " " + thread.fClientName);
chat.sendMessage(thread.getId() + ": " + thread.getAddress() + " " + thread.getClientName());
} catch (XMPPException e) {
e.printStackTrace();
}

View File

@ -0,0 +1,5 @@
# Mibew parameters
mibew.host=http://localhost:8080/webim/
mibew.login=admin
mibew.password=1

View File

@ -0,0 +1,42 @@
package org.mibew.notifier;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Arrays;
public class BrowserUtil {
static final String[] browsers = { "firefox", "opera", "konqueror", "epiphany", "seamonkey", "galeon",
"kazehakase", "mozilla", "netscape" };
/**
* Bare Bones Browser Launch
* Version 2.0 (May 26, 2009)
* By Dem Pilafian
* @param url
*/
public static void openURL(String url) throws IOException {
String osName = System.getProperty("os.name");
try {
if (osName.startsWith("Mac OS")) {
Class<?> fileMgr = Class.forName("com.apple.eio.FileManager");
Method openURL = fileMgr.getDeclaredMethod("openURL", new Class[] { String.class });
openURL.invoke(null, new Object[] { url });
} else if (osName.startsWith("Windows")) {
Runtime.getRuntime().exec("rundll32 url.dll,FileProtocolHandler " + url);
} else { // assume Unix or Linux
boolean found = false;
for (String browser : browsers)
if (!found) {
found = Runtime.getRuntime().exec(new String[] { "which", browser }).waitFor() == 0;
if (found)
Runtime.getRuntime().exec(new String[] { browser, url });
}
if (!found)
throw new Exception(Arrays.toString(browsers));
}
} catch (Throwable th) {
throw new IOException("Error attempting to launch web browser\n" + th.toString());
}
}
}

View File

@ -2,12 +2,16 @@ package org.mibew.notifier;
import org.mibew.api.MibewAgent;
import org.mibew.api.MibewAgentListener;
import org.mibew.api.MibewAgentOptions;
public class ConsoleApp {
public static void main(String[] args) {
MibewAgent agent = new MibewAgent(new MibewAgentOptions("http://localhost:8080/webim/", "admin", "1"), new MibewAgentListener() {
Options options = new Options(args);
if(!options.load()) {
return;
}
MibewAgent agent = new MibewAgent(options.getAgentOptions(), new MibewAgentListener() {
@Override
protected void onlineStateChanged(boolean isOnline) {
System.out.println("now " + (isOnline ? "online" : "offline"));

View File

@ -1,15 +1,20 @@
package org.mibew.notifier;
import org.mibew.api.MibewAgent;
import org.mibew.api.MibewAgentOptions;
import org.mibew.notifier.Options.JOptions;
public class NotifyApp {
public static void main(String[] args) {
Options options = new JOptions(args);
if(!options.load()) {
return;
}
TrayNotifier tn = new TrayNotifier();
tn.init();
MibewAgent agent = new MibewAgent(new MibewAgentOptions("http://localhost:8080/webim/", "admin", "1"), tn);
MibewAgent agent = new MibewAgent(options.getAgentOptions(), tn);
agent.launch();
tn.setAgent(agent);

View File

@ -0,0 +1,55 @@
package org.mibew.notifier;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import javax.swing.JOptionPane;
import org.mibew.api.MibewAgentOptions;
public class Options {
private MibewAgentOptions agentOptions;
private Properties myProperties;
public Options(String[] args) {
}
public boolean load() {
try {
InputStream is = getClass().getClassLoader().getResourceAsStream("mibew.ini");
if (is != null) {
myProperties = new Properties();
myProperties.load(is);
agentOptions = MibewAgentOptions.create(myProperties);
return true;
} else {
handleError("cannot find mibew.ini");
}
} catch (IOException e) {
handleError(e.getMessage());
}
return false;
}
protected void handleError(String message) {
System.err.println(message);
}
public MibewAgentOptions getAgentOptions() {
return agentOptions;
}
public static class JOptions extends Options {
public JOptions(String[] args) {
super(args);
}
@Override
protected void handleError(String message) {
JOptionPane.showMessageDialog(null, message);
}
}
}

View File

@ -1,6 +1,7 @@
package org.mibew.notifier;
import java.awt.AWTException;
import java.awt.EventQueue;
import java.awt.Image;
import java.awt.MenuItem;
import java.awt.MenuShortcut;
@ -12,6 +13,11 @@ import java.awt.TrayIcon.MessageType;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import javax.swing.JOptionPane;
import org.mibew.api.MibewAgent;
import org.mibew.api.MibewAgentListener;
@ -69,11 +75,20 @@ public class TrayNotifier extends MibewAgentListener {
}
@Override
protected void updated(MibewThread[] all, MibewThread[] created) {
PopupMenu pm = new PopupMenu();
protected void updated(MibewThread[] all, final MibewThread[] created) {
Arrays.sort(all);
final PopupMenu pm = new PopupMenu();
boolean beforeChat = false;
for(MibewThread mt : all) {
MenuItem mi = new MenuItem(mt.fClientName);
boolean isChat = "chat".equals(mt.getState());
if(beforeChat && isChat) {
pm.addSeparator();
}
MenuItem mi = new MenuItem(mt.toString());
mi.addActionListener(new LinkActionListener(agent.getOptions().getUrl() + "operator/agent.php?thread=" + mt.getId()));
pm.add(mi);
beforeChat = !isChat;
}
if(all.length > 0) {
pm.addSeparator();
@ -81,16 +96,45 @@ public class TrayNotifier extends MibewAgentListener {
MenuItem exitItem = new MenuItem("Exit", new MenuShortcut(KeyEvent.VK_X));
exitItem.addActionListener(fExit);
pm.add(exitItem);
try {
EventQueue.invokeAndWait(new Runnable() {
@Override
public void run() {
trayIcon.setPopupMenu(pm);
if(created.length == 1) {
trayIcon.displayMessage("New visitor", created[0].fClientName + "\n" + created[0].fFirstMessage, MessageType.INFO);
trayIcon.displayMessage("New visitor", created[0].getClientName() + "\n" + created[0].getFirstMessage(), MessageType.INFO);
} else if(created.length > 1) {
trayIcon.displayMessage("New visitors", "New " + created.length + " visitors", MessageType.INFO);
}
}
});
} catch (InterruptedException e) {
/* skip cycle */
} catch (InvocationTargetException e) {
/* hmm */
}
}
public void setAgent(MibewAgent agent) {
this.agent = agent;
}
private static class LinkActionListener implements ActionListener {
String link;
public LinkActionListener(String link) {
this.link = link;
}
@Override
public void actionPerformed(ActionEvent e) {
try {
BrowserUtil.openURL(link);
} catch (IOException e1) {
JOptionPane.showMessageDialog(null, e1.getMessage());
}
}
}
}