diff --git a/.gitignore b/.gitignore
index d4a3c328..7f9b38e5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,9 @@
+bin
src/messenger/.idea/workspace.xml
src/messenger/webim/install/package
src/messenger/absent_*
src/messenger/release*
+src/mibewjava/.idea/workspace.xml
+src/mibewjava/org.mibew.notifier/resources/
+mibew.ini
.DS_Store
diff --git a/README.md b/README.md
new file mode 100644
index 00000000..2cee54c4
--- /dev/null
+++ b/README.md
@@ -0,0 +1,26 @@
+Mibew Messenger
+===============
+
+Mibew Messenger is an open-source live support application written
+in PHP and MySQL. It enables one-on-one chat assistance in real-time
+directly from your website.
+
+Server requirements
+===================
+
+1. A webserver or web hosting account running on any major Operating System
+2. PHP (5.x and above) with MySQL support
+3. MySQL 5.0 and above
+
+Terms of Use
+============
+
+Mibew Messenger is distributed under the terms of the Eclipse Public
+License (or the General Public License, this means that you can choose
+one of two, and use it accordingly) with the following special exception.
+
+License exception:
+------------------
+No one may remove, alter or hide any copyright notices or links to the
+community site (http://mibew.org or http://openwebim.org) contained
+within the Program. Any derivative work must include this license exception.
diff --git a/src/mibewjava/.idea/.name b/src/mibewjava/.idea/.name
new file mode 100644
index 00000000..48d42c69
--- /dev/null
+++ b/src/mibewjava/.idea/.name
@@ -0,0 +1 @@
+mibew
\ No newline at end of file
diff --git a/src/mibewjava/.idea/ant.xml b/src/mibewjava/.idea/ant.xml
new file mode 100644
index 00000000..2581ca3f
--- /dev/null
+++ b/src/mibewjava/.idea/ant.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/src/mibewjava/.idea/compiler.xml b/src/mibewjava/.idea/compiler.xml
new file mode 100644
index 00000000..e644c940
--- /dev/null
+++ b/src/mibewjava/.idea/compiler.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/mibewjava/.idea/copyright/profiles_settings.xml b/src/mibewjava/.idea/copyright/profiles_settings.xml
new file mode 100644
index 00000000..3572571a
--- /dev/null
+++ b/src/mibewjava/.idea/copyright/profiles_settings.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/src/mibewjava/.idea/encodings.xml b/src/mibewjava/.idea/encodings.xml
new file mode 100644
index 00000000..e206d70d
--- /dev/null
+++ b/src/mibewjava/.idea/encodings.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/src/mibewjava/.idea/inspectionProfiles/Project_Default.xml b/src/mibewjava/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 00000000..c66df003
--- /dev/null
+++ b/src/mibewjava/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/mibewjava/.idea/inspectionProfiles/profiles_settings.xml b/src/mibewjava/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 00000000..3b312839
--- /dev/null
+++ b/src/mibewjava/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/mibewjava/.idea/libraries/swt.xml b/src/mibewjava/.idea/libraries/swt.xml
new file mode 100644
index 00000000..798fd500
--- /dev/null
+++ b/src/mibewjava/.idea/libraries/swt.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/mibewjava/.idea/misc.xml b/src/mibewjava/.idea/misc.xml
new file mode 100644
index 00000000..1c091f99
--- /dev/null
+++ b/src/mibewjava/.idea/misc.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ http://www.w3.org/1999/xhtml
+
+
+
+
+
+
diff --git a/src/mibewjava/.idea/modules.xml b/src/mibewjava/.idea/modules.xml
new file mode 100644
index 00000000..852f03e3
--- /dev/null
+++ b/src/mibewjava/.idea/modules.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/src/mibewjava/.idea/runConfigurations/MibewTray.xml b/src/mibewjava/.idea/runConfigurations/MibewTray.xml
new file mode 100644
index 00000000..efbaaaf6
--- /dev/null
+++ b/src/mibewjava/.idea/runConfigurations/MibewTray.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/mibewjava/.idea/uiDesigner.xml b/src/mibewjava/.idea/uiDesigner.xml
new file mode 100644
index 00000000..3b000203
--- /dev/null
+++ b/src/mibewjava/.idea/uiDesigner.xml
@@ -0,0 +1,125 @@
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+
+
diff --git a/src/mibewjava/.idea/vcs.xml b/src/mibewjava/.idea/vcs.xml
new file mode 100644
index 00000000..9ab281ac
--- /dev/null
+++ b/src/mibewjava/.idea/vcs.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/src/mibewjava/org.mibew.api/.classpath b/src/mibewjava/org.mibew.api/.classpath
new file mode 100644
index 00000000..18d70f02
--- /dev/null
+++ b/src/mibewjava/org.mibew.api/.classpath
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/src/mibewjava/org.mibew.api/.project b/src/mibewjava/org.mibew.api/.project
new file mode 100644
index 00000000..3197fa8e
--- /dev/null
+++ b/src/mibewjava/org.mibew.api/.project
@@ -0,0 +1,17 @@
+
+
+ org.mibew.api
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/src/mibewjava/org.mibew.api/org.mibew.api.iml b/src/mibewjava/org.mibew.api/org.mibew.api.iml
new file mode 100644
index 00000000..79c37165
--- /dev/null
+++ b/src/mibewjava/org.mibew.api/org.mibew.api.iml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/mibewjava/org.mibew.api/src/org/mibew/api/MibewAgent.java b/src/mibewjava/org.mibew.api/src/org/mibew/api/MibewAgent.java
new file mode 100644
index 00000000..87a1bcd5
--- /dev/null
+++ b/src/mibewjava/org.mibew.api/src/org/mibew/api/MibewAgent.java
@@ -0,0 +1,151 @@
+package org.mibew.api;
+
+import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.security.NoSuchAlgorithmException;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.xml.sax.SAXException;
+
+/**
+ * @author inspirer
+ */
+public class MibewAgent {
+
+ private final MibewAgentOptions fOptions;
+ private final MibewAgentListener fListener;
+ private final MibewUpdateThread fThread;
+ private volatile boolean started;
+
+ public MibewAgent(MibewAgentOptions options, MibewAgentListener listener) {
+ fOptions = options;
+ fListener = listener;
+ fThread = new MibewUpdateThread();
+ started = false;
+ }
+
+ public synchronized void launch() {
+ if(!started) {
+ fThread.start();
+ started = true;
+ }
+ }
+
+ public synchronized void stop() {
+ if(started) {
+ fThread.disconnect();
+ started = false;
+ }
+ }
+
+ public boolean isOnline() {
+ return fThread.isOnline();
+ }
+
+ 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;
+ private volatile boolean isOnline = false;
+ private final Object fSync = new Object();
+
+ public MibewUpdateThread() {
+ setName("Mibew Connection thread");
+ fExiting = false;
+ }
+
+ public void disconnect() {
+ synchronized (fSync) {
+ fExiting = true;
+ fSync.notifyAll();
+ }
+ }
+
+ @Override
+ public void run() {
+ while(!fExiting) {
+ try {
+ connectAndTrack();
+ } catch(InterruptedException ex) {
+ /* ignore */
+ } catch(Throwable th) {
+ logError(th.getMessage(), th);
+ }
+ }
+ setOnline(false);
+ }
+
+ private void setOnline(boolean online) {
+ if(isOnline != online) {
+ isOnline = online;
+ fListener.onlineStateChanged(online);
+ }
+ }
+
+ public boolean isOnline() {
+ return isOnline;
+ }
+
+ private void connectAndTrack() throws InterruptedException, UnsupportedEncodingException, NoSuchAlgorithmException, MalformedURLException, ParserConfigurationException, SAXException {
+ setOnline(false);
+ MibewConnection conn = new MibewConnection(fOptions.getUrl(), fOptions.getLogin(), fOptions.getPassword()) {
+ @Override
+ protected void handleError(String message, Exception ex) {
+ logError(message, ex);
+ }
+ };
+ if(!conn.connect()) {
+ logError("Wrong server, login or password.", null);
+ interruptableSleep(fOptions.getPollingInterval() * 3);
+ return;
+ }
+ final List createdThreads = new LinkedList();
+ MibewTracker mt = new MibewTracker(conn, new MibewTrackerListener(){
+ @Override
+ public void threadCreated(MibewThread thread) {
+ createdThreads.add(thread);
+ }
+ });
+ 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()]));
+ errorsCount = 0;
+ setOnline(true);
+ } catch (Throwable th) {
+ setOnline(false);
+ errorsCount++;
+ logError("not updated", th);
+ interruptableSleep(errorsCount < 10 ? fOptions.getPollingInterval() / 2 : fOptions.getPollingInterval() * 2);
+ continue;
+ }
+ interruptableSleep(fOptions.getPollingInterval());
+ }
+
+ conn.disconnect();
+ }
+
+ private void interruptableSleep(long millis) throws InterruptedException {
+ synchronized (fSync ) {
+ if(fExiting) {
+ return;
+ }
+ fSync.wait(millis);
+ }
+ }
+ }
+}
diff --git a/src/mibewjava/org.mibew.api/src/org/mibew/api/MibewAgentListener.java b/src/mibewjava/org.mibew.api/src/org/mibew/api/MibewAgentListener.java
new file mode 100644
index 00000000..78df236e
--- /dev/null
+++ b/src/mibewjava/org.mibew.api/src/org/mibew/api/MibewAgentListener.java
@@ -0,0 +1,10 @@
+package org.mibew.api;
+
+public abstract class MibewAgentListener {
+
+ protected void onlineStateChanged(boolean isOnline) {
+ }
+
+ protected void updated(MibewThread[] all, MibewThread[] created) {
+ }
+}
diff --git a/src/mibewjava/org.mibew.api/src/org/mibew/api/MibewAgentOptions.java b/src/mibewjava/org.mibew.api/src/org/mibew/api/MibewAgentOptions.java
new file mode 100644
index 00000000..9470af0d
--- /dev/null
+++ b/src/mibewjava/org.mibew.api/src/org/mibew/api/MibewAgentOptions.java
@@ -0,0 +1,62 @@
+package org.mibew.api;
+
+import java.io.IOException;
+import java.util.Properties;
+
+/**
+ * @author inspirer
+ */
+public class MibewAgentOptions {
+
+ private String fUrl;
+ private String fLogin;
+ private String fPassword;
+ 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();
+ this.fUrl = fUrl;
+ this.fLogin = fLogin;
+ this.fPassword = fPassword;
+ }
+
+ public String getLogin() {
+ return fLogin;
+ }
+
+ public String getPassword() {
+ return fPassword;
+ }
+
+ public String getUrl() {
+ return fUrl;
+ }
+
+ public int getConnectionRefreshTimeout() {
+ return fConnectionRefreshTimeout;
+ }
+
+ 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) {
+ 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);
+ }
+}
diff --git a/src/mibewjava/org.mibew.jabber/src/org/mibew/api/MibewConnection.java b/src/mibewjava/org.mibew.api/src/org/mibew/api/MibewConnection.java
similarity index 100%
rename from src/mibewjava/org.mibew.jabber/src/org/mibew/api/MibewConnection.java
rename to src/mibewjava/org.mibew.api/src/org/mibew/api/MibewConnection.java
diff --git a/src/mibewjava/org.mibew.jabber/src/org/mibew/api/MibewResponse.java b/src/mibewjava/org.mibew.api/src/org/mibew/api/MibewResponse.java
similarity index 100%
rename from src/mibewjava/org.mibew.jabber/src/org/mibew/api/MibewResponse.java
rename to src/mibewjava/org.mibew.api/src/org/mibew/api/MibewResponse.java
diff --git a/src/mibewjava/org.mibew.api/src/org/mibew/api/MibewThread.java b/src/mibewjava/org.mibew.api/src/org/mibew/api/MibewThread.java
new file mode 100644
index 00000000..5f3a8207
--- /dev/null
+++ b/src/mibewjava/org.mibew.api/src/org/mibew/api/MibewThread.java
@@ -0,0 +1,172 @@
+package org.mibew.api;
+
+
+/**
+ * @author inspirer
+ */
+public class MibewThread implements Comparable {
+
+ 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;
+ fState = state;
+ }
+
+ public void updateFrom(MibewThread updated) {
+ if(fId != updated.fId) {
+ throw new IllegalArgumentException("different threads");
+ }
+ fState = updated.fState;
+ fClientName = updated.fClientName;
+ fAgent = updated.fAgent;
+ fAddress = updated.fAddress;
+ fFirstMessage = updated.fFirstMessage;
+ fCanOpen = updated.fCanOpen;
+ 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;
+ }
+
+ 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;
+ }
+}
diff --git a/src/mibewjava/org.mibew.api/src/org/mibew/api/MibewTracker.java b/src/mibewjava/org.mibew.api/src/org/mibew/api/MibewTracker.java
new file mode 100644
index 00000000..8f48957e
--- /dev/null
+++ b/src/mibewjava/org.mibew.api/src/org/mibew/api/MibewTracker.java
@@ -0,0 +1,85 @@
+package org.mibew.api;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.mibew.api.handlers.UpdateHandler;
+import org.xml.sax.SAXException;
+
+/**
+ * @author inspirer
+ */
+public class MibewTracker {
+
+ private final MibewConnection fConnection;
+ private final MibewTrackerListener fListener;
+ private long fSince = 0;
+ private long fLastUpdate = 0;
+
+ private final Map fThreads;
+
+ public MibewTracker(MibewConnection conn, MibewTrackerListener listener) {
+ this.fConnection = conn;
+ this.fListener = listener;
+ this.fThreads = new HashMap();
+ }
+
+ public void update() throws IOException, SAXException, ParserConfigurationException {
+ MibewResponse response = fConnection.request("operator/update.php", "since=" + fSince);
+ SAXParser sp = SAXParserFactory.newInstance().newSAXParser();
+ UpdateHandler handler = new UpdateHandler();
+ sp.parse(new ByteArrayInputStream(response.getResponse()), handler);
+ handleResponse(response, handler);
+ }
+
+ private void handleResponse(MibewResponse response, UpdateHandler handler) throws IOException {
+ if (handler.getResponse() == UpdateHandler.UPD_ERROR) {
+ throw new IOException("Update error: " + handler.getMessage());
+ } else if (handler.getResponse() == UpdateHandler.UPD_SUCCESS) {
+ fSince = handler.getRevision();
+ fLastUpdate = handler.getTime();
+ List threads = handler.getThreads();
+ if (threads != null && threads.size() > 0) {
+ processUpdate(threads);
+ }
+ } else {
+ throw new IOException("Update error: " + response.getResponseText());
+ }
+ }
+
+ private void processUpdate(List updated) {
+ for (MibewThread mt : updated) {
+ MibewThread existing = fThreads.get(mt.getId());
+ boolean isClosed = mt.getState().equals("closed");
+ if (existing == null) {
+ if (!isClosed) {
+ fThreads.put(mt.getId(), mt);
+ fListener.threadCreated(mt);
+ }
+ } else if (isClosed) {
+ fThreads.remove(mt.getId());
+ fListener.threadClosed(existing);
+ } else {
+ existing.updateFrom(mt);
+ fListener.threadChanged(existing);
+ }
+ }
+ }
+
+ public long getLastUpdate() {
+ return fLastUpdate;
+ }
+
+ public MibewThread[] getThreads() {
+ Collection values = fThreads.values();
+ return values.toArray(new MibewThread[values.size()]);
+ }
+}
diff --git a/src/mibewjava/org.mibew.jabber/src/org/mibew/api/MibewTrackerListener.java b/src/mibewjava/org.mibew.api/src/org/mibew/api/MibewTrackerListener.java
similarity index 100%
rename from src/mibewjava/org.mibew.jabber/src/org/mibew/api/MibewTrackerListener.java
rename to src/mibewjava/org.mibew.api/src/org/mibew/api/MibewTrackerListener.java
diff --git a/src/mibewjava/org.mibew.jabber/src/org/mibew/api/Utils.java b/src/mibewjava/org.mibew.api/src/org/mibew/api/Utils.java
similarity index 99%
rename from src/mibewjava/org.mibew.jabber/src/org/mibew/api/Utils.java
rename to src/mibewjava/org.mibew.api/src/org/mibew/api/Utils.java
index bf79cb7f..ba8595d0 100644
--- a/src/mibewjava/org.mibew.jabber/src/org/mibew/api/Utils.java
+++ b/src/mibewjava/org.mibew.api/src/org/mibew/api/Utils.java
@@ -26,6 +26,4 @@ public class Utils {
}
return sb.toString();
}
-
-
}
diff --git a/src/mibewjava/org.mibew.jabber/src/org/mibew/api/handlers/LoginHandler.java b/src/mibewjava/org.mibew.api/src/org/mibew/api/handlers/LoginHandler.java
similarity index 100%
rename from src/mibewjava/org.mibew.jabber/src/org/mibew/api/handlers/LoginHandler.java
rename to src/mibewjava/org.mibew.api/src/org/mibew/api/handlers/LoginHandler.java
diff --git a/src/mibewjava/org.mibew.jabber/src/org/mibew/api/handlers/UpdateHandler.java b/src/mibewjava/org.mibew.api/src/org/mibew/api/handlers/UpdateHandler.java
similarity index 51%
rename from src/mibewjava/org.mibew.jabber/src/org/mibew/api/handlers/UpdateHandler.java
rename to src/mibewjava/org.mibew.api/src/org/mibew/api/handlers/UpdateHandler.java
index 58dc8b44..397327a3 100644
--- a/src/mibewjava/org.mibew.jabber/src/org/mibew/api/handlers/UpdateHandler.java
+++ b/src/mibewjava/org.mibew.api/src/org/mibew/api/handlers/UpdateHandler.java
@@ -15,14 +15,18 @@ import org.xml.sax.helpers.DefaultHandler;
public class UpdateHandler extends DefaultHandler {
public static final int UPD_ERROR = 1;
- public static final int UPD_THREADS = 2;
+ public static final int UPD_SUCCESS = 2;
+
+ private static final int STATE_READING_THREADS = 1;
private int fResponse = 0;
private String fMessage = "";
private long fRevision;
private long fTime;
private List fUpdated;
-
+
+ private int state = 0;
+
private Stack fPath = new Stack();
private MibewThread fCurrentThread;
@@ -33,27 +37,34 @@ public class UpdateHandler extends DefaultHandler {
if (fPath.size() == 0) {
if (name.equals("error")) {
fResponse = UPD_ERROR;
- } else if (name.equals("threads")) {
- fResponse = UPD_THREADS;
- fTime = Long.parseLong(attributes.getValue("time"));
- fRevision = Long.parseLong(attributes.getValue("revision"));
+ } else if (name.equals("update")) {
+ fResponse = UPD_SUCCESS;
} else {
throw new SAXException("unknown root element: " + name);
}
- }
- if (fResponse == UPD_THREADS && fPath.size() == 1
- && name.equals("thread")) {
- long id = Long.parseLong(attributes.getValue("id"));
- String stateid = attributes.getValue("stateid");
- 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"));
+ } else if(fResponse == UPD_SUCCESS) {
+ if(fPath.size() == 1) {
+ if (name.equals("threads")) {
+ fTime = Long.parseLong(attributes.getValue("time"));
+ fRevision = Long.parseLong(attributes.getValue("revision"));
+ fUpdated = new ArrayList();
+ state = STATE_READING_THREADS;
+ }
+ /* ignore others for compatibility reasons */
+ }
+ if (fPath.size() == 2 && state == STATE_READING_THREADS && name.equals("thread")) {
+ long id = Long.parseLong(attributes.getValue("id"));
+ String stateid = attributes.getValue("stateid");
+ fCurrentThread = new MibewThread(id, stateid);
+
+ if(!stateid.equals("closed")) {
+ fCurrentThread.setStateText(attributes.getValue("state"));
+ fCurrentThread.setCanOpen(booleanAttribute(attributes.getValue("canopen")));
+ fCurrentThread.setCanView(booleanAttribute(attributes.getValue("canview")));
+ fCurrentThread.setCanBan(booleanAttribute(attributes.getValue("canban")));
+ }
+
}
-
}
} catch (NumberFormatException ex) {
throw new SAXException(ex.getMessage());
@@ -68,17 +79,23 @@ 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 {
fPath.pop();
- if (fResponse == UPD_THREADS && fPath.size() == 1
- && name.equals("thread")) {
- if(fUpdated == null) {
- fUpdated = new ArrayList();
- }
+ if (fResponse == UPD_SUCCESS && fPath.size() == 2 && state == STATE_READING_THREADS && name.equals("thread")) {
fUpdated.add(fCurrentThread);
fCurrentThread = null;
+ } else if(fPath.size() == 1 && state == STATE_READING_THREADS) {
+ state = 0;
}
}
@@ -91,21 +108,26 @@ public class UpdateHandler extends DefaultHandler {
throw new SAXException("unexpected characters");
}
fMessage += new String(ch, start, length);
- } else if (fResponse == UPD_THREADS) {
- if(fCurrentThread == null || fPath.size() != 3) {
+ } else if (fResponse == UPD_SUCCESS && fCurrentThread != null) {
+ if(fCurrentThread == null || fPath.size() != 4) {
throw new SAXException("unknown characters");
}
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
diff --git a/src/mibewjava/org.mibew.jabber/.classpath b/src/mibewjava/org.mibew.jabber/.classpath
index 4257a5dc..89790263 100644
--- a/src/mibewjava/org.mibew.jabber/.classpath
+++ b/src/mibewjava/org.mibew.jabber/.classpath
@@ -4,5 +4,6 @@
+
diff --git a/src/mibewjava/org.mibew.jabber/resources/Mibew Notifier.app/Contents/Info.plist b/src/mibewjava/org.mibew.jabber/resources/Mibew Notifier.app/Contents/Info.plist
new file mode 100644
index 00000000..11b4d738
--- /dev/null
+++ b/src/mibewjava/org.mibew.jabber/resources/Mibew Notifier.app/Contents/Info.plist
@@ -0,0 +1,49 @@
+
+
+
+
+ CFBundleName
+ Mibew Notifier
+ CFBundleIdentifier
+ org.mibew.notifier
+ CFBundleVersion
+ 100.0
+ CFBundleAllowMixedLocalizations
+ true
+ CFBundleExecutable
+ MibewNotifier
+ CFBundleDevelopmentRegion
+ English
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ 1.0
+ CFBundleSignature
+ ????
+ CFBundleGetInfoString
+ Mibew Notifier 1.0, build 17 Jan, 2010
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleIconFile
+ mibew.icns
+ Java
+
+ WorkingDirectory
+ $APP_PACKAGE/Contents/Resources/Java
+ VMOptions
+ -Xms16mm
+ MainClass
+ org.mibew.trayapp.NotifyApp
+ JVMVersion
+ 1.6+
+ ClassPath
+
+ $JAVAROOT/org.mibew.notifier.jar
+ $JAVAROOT/smackx.jar
+ $JAVAROOT/smackx-jingle.jar
+ $JAVAROOT/smackx-debug.jar
+ $JAVAROOT/smack.jar
+
+
+
+
diff --git a/src/mibewjava/org.mibew.jabber/resources/Mibew Notifier.app/Contents/MacOS/MibewNotifier b/src/mibewjava/org.mibew.jabber/resources/Mibew Notifier.app/Contents/MacOS/MibewNotifier
new file mode 100755
index 00000000..7035592f
Binary files /dev/null and b/src/mibewjava/org.mibew.jabber/resources/Mibew Notifier.app/Contents/MacOS/MibewNotifier differ
diff --git a/src/mibewjava/org.mibew.jabber/resources/Mibew Notifier.app/Contents/PkgInfo b/src/mibewjava/org.mibew.jabber/resources/Mibew Notifier.app/Contents/PkgInfo
new file mode 100644
index 00000000..bd04210f
--- /dev/null
+++ b/src/mibewjava/org.mibew.jabber/resources/Mibew Notifier.app/Contents/PkgInfo
@@ -0,0 +1 @@
+APPL????
\ No newline at end of file
diff --git a/src/mibewjava/org.mibew.jabber/resources/Mibew Notifier.app/Contents/Resources/mibew.icns b/src/mibewjava/org.mibew.jabber/resources/Mibew Notifier.app/Contents/Resources/mibew.icns
new file mode 100644
index 00000000..c9a253d6
Binary files /dev/null and b/src/mibewjava/org.mibew.jabber/resources/Mibew Notifier.app/Contents/Resources/mibew.icns differ
diff --git a/src/mibewjava/org.mibew.jabber/resources/build.xml b/src/mibewjava/org.mibew.jabber/resources/build.xml
new file mode 100644
index 00000000..d9312466
--- /dev/null
+++ b/src/mibewjava/org.mibew.jabber/resources/build.xml
@@ -0,0 +1,61 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/mibewjava/org.mibew.jabber/resources/images/mibew.gif b/src/mibewjava/org.mibew.jabber/resources/images/mibew.gif
new file mode 100644
index 00000000..a78219c4
Binary files /dev/null and b/src/mibewjava/org.mibew.jabber/resources/images/mibew.gif differ
diff --git a/src/mibewjava/org.mibew.jabber/resources/packdmg.sh b/src/mibewjava/org.mibew.jabber/resources/packdmg.sh
new file mode 100755
index 00000000..f9b4da50
--- /dev/null
+++ b/src/mibewjava/org.mibew.jabber/resources/packdmg.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+rm -rf *.dmg
+hdiutil create mibew-notifier-temp.dmg -volname "Mibew Notifier 1.0" -fs HFS+ -srcfolder "Mibew Notifier.app"
+hdiutil convert "mibew-notifier-temp.dmg" -format UDZO -imagekey zlib-level=9 -o "mibew-1.0.0.dmg"
+rm mibew-notifier-temp.dmg
diff --git a/src/mibewjava/org.mibew.jabber/src/org/mibew/api/MibewThread.java b/src/mibewjava/org.mibew.jabber/src/org/mibew/api/MibewThread.java
deleted file mode 100644
index f9d31280..00000000
--- a/src/mibewjava/org.mibew.jabber/src/org/mibew/api/MibewThread.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package org.mibew.api;
-
-/**
- * @author inspirer
- */
-public class 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;
-
- public MibewThread(long id, String state) {
- fId = id;
- fState = state;
- }
-
- public void updateFrom(MibewThread updated) {
- if(fId != updated.fId) {
- throw new IllegalArgumentException("different threads");
- }
- fState = updated.fState;
- fClientName = updated.fClientName;
- fAgent = updated.fAgent;
- fAddress = updated.fAddress;
- fFirstMessage = updated.fFirstMessage;
- fCanOpen = updated.fCanOpen;
- fCanView = updated.fCanView;
- fCanBan = updated.fCanBan;
- fStateText = updated.fStateText;
- }
-}
diff --git a/src/mibewjava/org.mibew.jabber/src/org/mibew/api/MibewTracker.java b/src/mibewjava/org.mibew.jabber/src/org/mibew/api/MibewTracker.java
deleted file mode 100644
index 96aa3188..00000000
--- a/src/mibewjava/org.mibew.jabber/src/org/mibew/api/MibewTracker.java
+++ /dev/null
@@ -1,85 +0,0 @@
-package org.mibew.api;
-
-import java.io.ByteArrayInputStream;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
-
-import org.mibew.api.handlers.UpdateHandler;
-
-/**
- * @author inspirer
- */
-public class MibewTracker {
-
- private final MibewConnection fConnection;
- private final MibewTrackerListener fListener;
- private long fSince = 0;
- private long fLastUpdate = 0;
-
- private final Map fThreads;
-
- public MibewTracker(MibewConnection conn, MibewTrackerListener listener) {
- this.fConnection = conn;
- this.fListener = listener;
- this.fThreads = new HashMap();
- }
-
- public void track() throws InterruptedException {
- for(int i = 0; i < 5; i++) {
- try {
- MibewResponse response = fConnection.request("operator/update.php", "since="+fSince);
- SAXParser sp = SAXParserFactory.newInstance().newSAXParser();
- UpdateHandler handler = new UpdateHandler();
- sp.parse(new ByteArrayInputStream(response.getResponse()), handler);
- handleResponse(response, handler);
- } catch(Exception e) {
- System.err.println("update exception: " + e.getMessage());
- }
- Thread.sleep(1000);
- }
- }
-
- private void handleResponse(MibewResponse response, UpdateHandler handler) {
- if(handler.getResponse() == UpdateHandler.UPD_ERROR) {
- System.out.println("Update error: " + handler.getMessage());
- } else if(handler.getResponse() == UpdateHandler.UPD_THREADS) {
- System.out.println("Updated.... " + handler.getRevision());
- fSince = handler.getRevision();
- fLastUpdate = handler.getTime();
- List threads = handler.getThreads();
- if(threads != null && threads.size() > 0) {
- processUpdate(threads);
- }
- } else {
- System.out.println("Update error");
- System.out.println(response.getResponseText());
- }
- }
-
- private void processUpdate(List updated) {
- for(MibewThread mt : updated) {
- MibewThread existing = fThreads.get(mt.fId);
- boolean isClosed = mt.fState.equals("closed");
- if(existing == null) {
- if(!isClosed) {
- fThreads.put(mt.fId, mt);
- fListener.threadCreated(mt);
- }
- } else if(isClosed) {
- fThreads.remove(mt.fId);
- fListener.threadClosed(existing);
- } else {
- existing.updateFrom(mt);
- fListener.threadChanged(existing);
- }
- }
- }
-
- public long getLastUpdate() {
- return fLastUpdate;
- }
-}
diff --git a/src/mibewjava/org.mibew.jabber/src/org/mibew/jabber/Application.java b/src/mibewjava/org.mibew.jabber/src/org/mibew/jabber/Application.java
index 961c3970..8733ddbe 100644
--- a/src/mibewjava/org.mibew.jabber/src/org/mibew/jabber/Application.java
+++ b/src/mibewjava/org.mibew.jabber/src/org/mibew/jabber/Application.java
@@ -39,7 +39,7 @@ public class Application {
}
});
- MibewConnection conn = new MibewConnection("http://localhost:8080/webim/", "admin", "");
+ MibewConnection conn = new MibewConnection("http://localhost:8080/webim/", "admin", "1");
if(!conn.connect()) {
System.err.println("Wrong server, login or password.");
return;
@@ -49,14 +49,14 @@ 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();
}
}
});
- mt.track();
+ //mt.track();
connection.disconnect();
}
diff --git a/src/mibewjava/org.mibew.notifier/.classpath b/src/mibewjava/org.mibew.notifier/.classpath
new file mode 100644
index 00000000..78fdd7f0
--- /dev/null
+++ b/src/mibewjava/org.mibew.notifier/.classpath
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/src/mibewjava/org.mibew.notifier/.project b/src/mibewjava/org.mibew.notifier/.project
new file mode 100644
index 00000000..4a130331
--- /dev/null
+++ b/src/mibewjava/org.mibew.notifier/.project
@@ -0,0 +1,17 @@
+
+
+ org.mibew.notifier
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/src/mibewjava/org.mibew.notifier/libs/src.zip b/src/mibewjava/org.mibew.notifier/libs/src.zip
new file mode 100644
index 00000000..708c8d33
Binary files /dev/null and b/src/mibewjava/org.mibew.notifier/libs/src.zip differ
diff --git a/src/mibewjava/org.mibew.notifier/libs/swt-debug.jar b/src/mibewjava/org.mibew.notifier/libs/swt-debug.jar
new file mode 100644
index 00000000..a369b688
Binary files /dev/null and b/src/mibewjava/org.mibew.notifier/libs/swt-debug.jar differ
diff --git a/src/mibewjava/org.mibew.notifier/libs/swt.jar b/src/mibewjava/org.mibew.notifier/libs/swt.jar
new file mode 100644
index 00000000..9a326dfc
Binary files /dev/null and b/src/mibewjava/org.mibew.notifier/libs/swt.jar differ
diff --git a/src/mibewjava/org.mibew.notifier/org.mibew.notifier.iml b/src/mibewjava/org.mibew.notifier/org.mibew.notifier.iml
new file mode 100644
index 00000000..5efe060c
--- /dev/null
+++ b/src/mibewjava/org.mibew.notifier/org.mibew.notifier.iml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/mibewjava/org.mibew.notifier/src/mibew.ini b/src/mibewjava/org.mibew.notifier/src/mibew.ini
new file mode 100644
index 00000000..3564fbaa
--- /dev/null
+++ b/src/mibewjava/org.mibew.notifier/src/mibew.ini
@@ -0,0 +1,5 @@
+# Mibew parameters
+
+mibew.host=http://localhost:8080/webim/
+mibew.login=admin
+mibew.password=
diff --git a/src/mibewjava/org.mibew.notifier/src/org/mibew/notifier/BrowserUtil.java b/src/mibewjava/org.mibew.notifier/src/org/mibew/notifier/BrowserUtil.java
new file mode 100644
index 00000000..6ee074bf
--- /dev/null
+++ b/src/mibewjava/org.mibew.notifier/src/org/mibew/notifier/BrowserUtil.java
@@ -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());
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/mibewjava/org.mibew.notifier/src/org/mibew/notifier/ConsoleApp.java b/src/mibewjava/org.mibew.notifier/src/org/mibew/notifier/ConsoleApp.java
new file mode 100644
index 00000000..005b52e7
--- /dev/null
+++ b/src/mibewjava/org.mibew.notifier/src/org/mibew/notifier/ConsoleApp.java
@@ -0,0 +1,28 @@
+package org.mibew.notifier;
+
+import org.mibew.api.MibewAgent;
+import org.mibew.api.MibewAgentListener;
+
+public class ConsoleApp {
+
+ public static void main(String[] args) {
+ 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"));
+ }
+ });
+ agent.launch();
+ try {
+ Thread.sleep(3500);
+ } catch (InterruptedException e) {
+ }
+
+ agent.stop();
+ }
+}
diff --git a/src/mibewjava/org.mibew.notifier/src/org/mibew/notifier/MibewTray.java b/src/mibewjava/org.mibew.notifier/src/org/mibew/notifier/MibewTray.java
new file mode 100644
index 00000000..bd408425
--- /dev/null
+++ b/src/mibewjava/org.mibew.notifier/src/org/mibew/notifier/MibewTray.java
@@ -0,0 +1,140 @@
+package org.mibew.notifier;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.*;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+import org.mibew.api.MibewAgent;
+import org.mibew.api.MibewAgentListener;
+import org.mibew.api.MibewThread;
+
+import java.awt.*;
+import java.io.IOException;
+
+public class MibewTray extends MibewAgentListener {
+
+ private volatile boolean isStopped = false;
+
+ private Image fImageOn;
+ private Image fImageOff;
+ private TrayItem fItem;
+ private Menu fMenu;
+ private MibewAgent fAgent;
+
+ void initTray(Display display, Shell shell, MibewAgent agent) {
+ fAgent = agent;
+ fImageOn = new Image(display, getClass().getClassLoader().getResourceAsStream("org/mibew/notifier/tray_on.png"));
+ fImageOff = new Image(display, getClass().getClassLoader().getResourceAsStream("org/mibew/notifier/tray_off.png"));
+
+ final Tray tray = display.getSystemTray();
+ if (tray == null) {
+ System.out.println("The system tray is not available");
+ } else {
+ fItem = new TrayItem(tray, SWT.NONE);
+ fItem.setToolTipText("SWT TrayItem");
+ fItem.addListener(SWT.Show, new Listener() {
+ public void handleEvent(Event event) {
+ System.out.println("show");
+ }
+ });
+ fItem.addListener(SWT.Hide, new Listener() {
+ public void handleEvent(Event event) {
+ System.out.println("hide");
+ }
+ });
+ fMenu = new Menu(shell, SWT.POP_UP);
+ for (int i = 0; i < 8; i++) {
+ MenuItem mi = new MenuItem(fMenu, SWT.PUSH);
+ mi.setText("Item" + i);
+ mi.addListener(SWT.Selection, new Listener() {
+ public void handleEvent(Event event) {
+ System.out.println("selection " + event.widget);
+ }
+ });
+ }
+ Listener listener = new Listener() {
+ public void handleEvent(Event event) {
+ fMenu.setVisible(true);
+ }
+ };
+ fItem.addListener(SWT.MenuDetect, listener);
+ fItem.addListener(SWT.Selection, listener);
+ fItem.setImage(fImageOff);
+ }
+ shell.setBounds(50, 50, 300, 200);
+ //shell.open();
+ }
+
+ @Override
+ protected synchronized void onlineStateChanged(final boolean isOnline) {
+ if(isStopped)
+ return;
+
+ Display.getDefault().asyncExec(new Runnable() {
+ public void run() {
+ if(isStopped)
+ return;
+
+ fItem.setImage(isOnline ? fImageOn : fImageOff);
+ }
+ });
+ }
+
+ @Override
+ protected synchronized void updated(final MibewThread[] all, final MibewThread[] created) {
+ if(isStopped)
+ return;
+
+ Display.getDefault().asyncExec(new Runnable() {
+ public void run() {
+ if(isStopped)
+ return;
+
+ for (MenuItem menuItem : fMenu.getItems()) {
+ menuItem.dispose();
+ }
+ for(MibewThread m : all) {
+ MenuItem mi = new MenuItem(fMenu, SWT.PUSH);
+ mi.setText(m.getClientName());
+ mi.addListener(SWT.Selection, new LinkActionListener(null, fAgent.getOptions().getUrl() + "operator/agent.php?thread=" + m.getId()));
+ }
+
+ if(created.length == 1) {
+ fItem.setToolTipText(created[0].getClientName() + "\n" + created[0].getFirstMessage());
+ } else if(created.length > 1) {
+ fItem.setToolTipText("New " + created.length + " visitors");
+ }
+
+ }
+ });
+ }
+
+ synchronized void dispose() {
+ isStopped = true;
+ fItem.dispose();
+ fImageOn.dispose();
+ fImageOff.dispose();
+ }
+
+ private static class LinkActionListener implements Listener {
+ private final Shell shell;
+ private final String link;
+
+ public LinkActionListener(Shell shell, String link) {
+ this.shell = shell;
+ this.link = link;
+ }
+
+ public void handleEvent(Event event) {
+ try {
+ BrowserUtil.openURL(link);
+ } catch (IOException e1) {
+ MessageBox messageBox = new MessageBox(shell, SWT.OK | SWT.ICON_ERROR);
+ messageBox.setText("Browser error"); //$NON-NLS-1$
+ messageBox.setMessage(e1.getMessage());
+ messageBox.open();
+ }
+ }
+ }}
diff --git a/src/mibewjava/org.mibew.notifier/src/org/mibew/notifier/NotifyApp.java b/src/mibewjava/org.mibew.notifier/src/org/mibew/notifier/NotifyApp.java
new file mode 100644
index 00000000..ece7777d
--- /dev/null
+++ b/src/mibewjava/org.mibew.notifier/src/org/mibew/notifier/NotifyApp.java
@@ -0,0 +1,34 @@
+package org.mibew.notifier;
+
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.mibew.api.MibewAgent;
+import org.mibew.notifier.Options.JOptions;
+
+public class NotifyApp {
+
+ public static void main(String[] args) {
+ Display display = new Display();
+ Shell shell = new Shell(display);
+
+ Options options = new JOptions(shell, args);
+ if (!options.load()) {
+ return;
+ }
+
+ MibewTray tray = new MibewTray();
+ MibewAgent agent = new MibewAgent(options.getAgentOptions(), tray);
+ agent.launch();
+
+ tray.initTray(display, shell, agent);
+
+ while (!shell.isDisposed()) {
+ if (!display.readAndDispatch())
+ display.sleep();
+ }
+ tray.dispose();
+ agent.stop();
+ display.dispose();
+ System.exit(0);
+ }
+}
diff --git a/src/mibewjava/org.mibew.notifier/src/org/mibew/notifier/Options.java b/src/mibewjava/org.mibew.notifier/src/org/mibew/notifier/Options.java
new file mode 100644
index 00000000..a190c98d
--- /dev/null
+++ b/src/mibewjava/org.mibew.notifier/src/org/mibew/notifier/Options.java
@@ -0,0 +1,62 @@
+package org.mibew.notifier;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.MessageBox;
+import org.eclipse.swt.widgets.Shell;
+import org.mibew.api.MibewAgentOptions;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+
+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 {
+
+ private final Shell fShell;
+
+ public JOptions(Shell shell, String[] args) {
+ super(args);
+ fShell = shell;
+ }
+
+ @Override
+ protected void handleError(final String message) {
+ MessageBox messageBox = new MessageBox(fShell, SWT.OK | SWT.ICON_ERROR);
+ messageBox.setText("Options error"); //$NON-NLS-1$
+ messageBox.setMessage(message);
+ messageBox.open();
+ }
+ }
+}
diff --git a/src/mibewjava/org.mibew.notifier/src/org/mibew/notifier/tray_off.png b/src/mibewjava/org.mibew.notifier/src/org/mibew/notifier/tray_off.png
new file mode 100644
index 00000000..daf8251b
Binary files /dev/null and b/src/mibewjava/org.mibew.notifier/src/org/mibew/notifier/tray_off.png differ
diff --git a/src/mibewjava/org.mibew.notifier/src/org/mibew/notifier/tray_on.png b/src/mibewjava/org.mibew.notifier/src/org/mibew/notifier/tray_on.png
new file mode 100644
index 00000000..1e8f871a
Binary files /dev/null and b/src/mibewjava/org.mibew.notifier/src/org/mibew/notifier/tray_on.png differ