diff --git a/build.xml b/build.xml
index d1f0575c5..078e979c5 100644
--- a/build.xml
+++ b/build.xml
@@ -606,7 +606,7 @@
bundle-pluginmanager,bundle-notification,
bundle-ssh,bundle-plugin-sshaccregwizz,
bundle-contacteventhandler,bundle-plugin-contactinfo,
- bundle-plugin-accountinfo"/>
+ bundle-plugin-accountinfo,bundle-plugin-chatalerter"/>
@@ -1530,6 +1530,17 @@ javax.swing.event, javax.swing.border"/>
prefix="net/java/sip/communicator/plugin/contactinfo"/>
+
+
+
+
+
+
+
+
+
diff --git a/lib/felix.client.run.properties b/lib/felix.client.run.properties
index 6e988a795..1b288adcc 100644
--- a/lib/felix.client.run.properties
+++ b/lib/felix.client.run.properties
@@ -36,6 +36,7 @@ org.osgi.framework.system.packages= org.osgi.framework; ; version=1.3.0, \
org.jdesktop.jdic.tray; \
org.jdesktop.jdic.desktop; \
com.apple.eio; \
+ com.apple.cocoa.application; \
org.xml.sax.helpers; \
javax.crypto; \
javax.crypto.spec; \
@@ -112,6 +113,7 @@ felix.auto.start.60= \
reference:file:sc-bundles/contacteventhandler.jar \
reference:file:sc-bundles/contactinfo.jar \
reference:file:sc-bundles/accountinfo.jar \
+ reference:file:sc-bundles/chatalerter.jar \
reference:file:sc-bundles/shutdown.jar
# Uncomment the following lines if you want to run the architect viewer
diff --git a/lib/installer-exclude/jdic_misc.jar b/lib/installer-exclude/jdic_misc.jar
new file mode 100644
index 000000000..2f53c56a6
Binary files /dev/null and b/lib/installer-exclude/jdic_misc.jar differ
diff --git a/lib/native/linux/libjdic_misc.so b/lib/native/linux/libjdic_misc.so
new file mode 100755
index 000000000..816229dbb
Binary files /dev/null and b/lib/native/linux/libjdic_misc.so differ
diff --git a/lib/native/windows/jdic_misc.dll b/lib/native/windows/jdic_misc.dll
new file mode 100755
index 000000000..c0cbd412c
Binary files /dev/null and b/lib/native/windows/jdic_misc.dll differ
diff --git a/src/net/java/sip/communicator/impl/gui/PopupDialogImpl.java b/src/net/java/sip/communicator/impl/gui/PopupDialogImpl.java
index b58416bca..78993cfb5 100644
--- a/src/net/java/sip/communicator/impl/gui/PopupDialogImpl.java
+++ b/src/net/java/sip/communicator/impl/gui/PopupDialogImpl.java
@@ -254,4 +254,13 @@ public void minimize()
public void maximize()
{
}
+
+ /**
+ * The source of the window
+ * @return the source of the window
+ */
+ public Object getSource()
+ {
+ return this;
+ }
}
diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/ChatWindow.java b/src/net/java/sip/communicator/impl/gui/main/chat/ChatWindow.java
index 20d5c7db7..6671d2a44 100755
--- a/src/net/java/sip/communicator/impl/gui/main/chat/ChatWindow.java
+++ b/src/net/java/sip/communicator/impl/gui/main/chat/ChatWindow.java
@@ -671,4 +671,12 @@ public void pluginComponentRemoved(PluginComponentEvent event)
}
}
+ /**
+ * The source of the window
+ * @return the source of the window
+ */
+ public Object getSource()
+ {
+ return this;
+ }
}
diff --git a/src/net/java/sip/communicator/impl/gui/main/configforms/ConfigurationFrame.java b/src/net/java/sip/communicator/impl/gui/main/configforms/ConfigurationFrame.java
index 561b25685..7a2bf2612 100644
--- a/src/net/java/sip/communicator/impl/gui/main/configforms/ConfigurationFrame.java
+++ b/src/net/java/sip/communicator/impl/gui/main/configforms/ConfigurationFrame.java
@@ -221,4 +221,13 @@ public void bringToFront()
{
this.toFront();
}
+
+ /**
+ * The source of the window
+ * @return the source of the window
+ */
+ public Object getSource()
+ {
+ return this;
+ }
}
diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/addcontact/AddContactWizard.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/addcontact/AddContactWizard.java
index 593c3e760..1c19aefbd 100644
--- a/src/net/java/sip/communicator/impl/gui/main/contactlist/addcontact/AddContactWizard.java
+++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/addcontact/AddContactWizard.java
@@ -213,4 +213,13 @@ public MainFrame getMainFrame()
{
return mainFrame;
}
+
+ /**
+ * The source of the window
+ * @return the source of the window
+ */
+ public Object getSource()
+ {
+ return this;
+ }
}
diff --git a/src/net/java/sip/communicator/impl/gui/main/login/AuthenticationWindow.java b/src/net/java/sip/communicator/impl/gui/main/login/AuthenticationWindow.java
index a0e1fd641..b75d5e58a 100644
--- a/src/net/java/sip/communicator/impl/gui/main/login/AuthenticationWindow.java
+++ b/src/net/java/sip/communicator/impl/gui/main/login/AuthenticationWindow.java
@@ -339,4 +339,13 @@ public void bringToFront()
{
this.toFront();
}
+
+ /**
+ * The source of the window
+ * @return the source of the window
+ */
+ public Object getSource()
+ {
+ return this;
+ }
}
diff --git a/src/net/java/sip/communicator/plugin/branding/AboutWindow.java b/src/net/java/sip/communicator/plugin/branding/AboutWindow.java
index e36f86097..ee3f39525 100644
--- a/src/net/java/sip/communicator/plugin/branding/AboutWindow.java
+++ b/src/net/java/sip/communicator/plugin/branding/AboutWindow.java
@@ -239,5 +239,13 @@ public static void activateAntialiasing(Graphics g)
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
}
-
+
+ /**
+ * The source of the window
+ * @return the source of the window
+ */
+ public Object getSource()
+ {
+ return this;
+ }
}
diff --git a/src/net/java/sip/communicator/plugin/contactinfo/ChatAlerterActivator.java b/src/net/java/sip/communicator/plugin/contactinfo/ChatAlerterActivator.java
new file mode 100644
index 000000000..3b014f430
--- /dev/null
+++ b/src/net/java/sip/communicator/plugin/contactinfo/ChatAlerterActivator.java
@@ -0,0 +1,353 @@
+package net.java.sip.communicator.plugin.chatalerter;
+
+import java.util.*;
+import javax.swing.*;
+import org.osgi.framework.*;
+
+import net.java.sip.communicator.service.gui.*;
+import net.java.sip.communicator.service.protocol.*;
+import net.java.sip.communicator.service.protocol.event.*;
+import net.java.sip.communicator.util.*;
+
+import org.jdesktop.jdic.misc.*;
+
+/**
+ * The Activator of the Chat Alerter bundle.
+ *
+ * @author Damian Minkov
+ */
+public class ChatAlerterActivator
+ implements BundleActivator,
+ ServiceListener,
+ MessageListener,
+ ChatRoomMessageListener,
+ LocalUserChatRoomPresenceListener
+{
+ /**
+ * The logger for this class.
+ */
+ private static Logger logger = Logger
+ .getLogger(ChatAlerterActivator.class);
+
+ /**
+ * The BundleContext that we got from the OSGI bus.
+ */
+ private BundleContext bundleContext = null;
+
+ /**
+ * UIService reference.
+ */
+ private UIService uiService;
+
+ /**
+ * Starts this bundle.
+ */
+ public void start(BundleContext bc) throws Exception
+ {
+ try
+ {
+ // try to load native libs, if it fails don't do anything
+ Alerter.newInstance();
+ }
+ catch (Exception exception)
+ {
+ logger.info("The Alerter not supported or problem loading it!",
+ exception);
+ return;
+ }
+
+ ServiceReference uiServiceRef
+ = bc.getServiceReference(UIService.class.getName());
+
+ uiService = (UIService) bc.getService(uiServiceRef);
+
+ this.bundleContext = bc;
+
+ // start listening for newly register or removed protocol providers
+ bc.addServiceListener(this);
+
+ ServiceReference[] protocolProviderRefs = null;
+ try
+ {
+ protocolProviderRefs = bc.getServiceReferences(
+ ProtocolProviderService.class.getName(),
+ null);
+ }
+ catch (InvalidSyntaxException ex)
+ {
+ // this shouldn't happen since we're providing no parameter string
+ // but let's log just in case.
+ logger.error(
+ "Error while retrieving service refs", ex);
+ return;
+ }
+
+ // in case we found any
+ if (protocolProviderRefs != null)
+ {
+ logger.debug("Found "
+ + protocolProviderRefs.length
+ + " already installed providers.");
+ for (int i = 0; i < protocolProviderRefs.length; i++)
+ {
+ ProtocolProviderService provider = (ProtocolProviderService) bc
+ .getService(protocolProviderRefs[i]);
+
+ this.handleProviderAdded(provider);
+ }
+ }
+ }
+
+ public void stop(BundleContext bc) throws Exception
+ {
+ // start listening for newly register or removed protocol providers
+ bc.removeServiceListener(this);
+
+ ServiceReference[] protocolProviderRefs = null;
+ try
+ {
+ protocolProviderRefs = bc.getServiceReferences(
+ ProtocolProviderService.class.getName(),
+ null);
+ }
+ catch (InvalidSyntaxException ex)
+ {
+ // this shouldn't happen since we're providing no parameter string
+ // but let's log just in case.
+ logger.error(
+ "Error while retrieving service refs", ex);
+ return;
+ }
+
+ // in case we found any
+ if (protocolProviderRefs != null)
+ {
+ for (int i = 0; i < protocolProviderRefs.length; i++)
+ {
+ ProtocolProviderService provider = (ProtocolProviderService) bc
+ .getService(protocolProviderRefs[i]);
+
+ this.handleProviderRemoved(provider);
+ }
+ }
+ }
+
+ /**
+ * Used to attach the Alerter plugin to existing or
+ * just registered protocol provider. Checks if the provider has implementation
+ * of OperationSetBasicInstantMessaging
+ *
+ * @param provider ProtocolProviderService
+ */
+ private void handleProviderAdded(ProtocolProviderService provider)
+ {
+ logger.debug("Adding protocol provider " + provider.getProtocolName());
+
+ // check whether the provider has a basic im operation set
+ OperationSetBasicInstantMessaging opSetIm
+ = (OperationSetBasicInstantMessaging) provider
+ .getSupportedOperationSets().get(
+ OperationSetBasicInstantMessaging.class.getName());
+
+ if (opSetIm != null)
+ {
+ opSetIm.addMessageListener(this);
+ }
+ else
+ {
+ logger.trace("Service did not have a im op. set.");
+ }
+
+ // check whether the provider has a sms operation set
+ OperationSetSmsMessaging opSetSms
+ = (OperationSetSmsMessaging) provider
+ .getSupportedOperationSets().get(
+ OperationSetSmsMessaging.class.getName());
+
+ if (opSetSms != null)
+ {
+ opSetSms.addMessageListener(this);
+ }
+ else
+ {
+ logger.trace("Service did not have a sms op. set.");
+ }
+
+ OperationSetMultiUserChat opSetMultiUChat
+ = (OperationSetMultiUserChat) provider
+ .getSupportedOperationSets().get(
+ OperationSetMultiUserChat.class.getName());
+
+ if (opSetMultiUChat != null)
+ {
+ Iterator iter =
+ opSetMultiUChat.getCurrentlyJoinedChatRooms().iterator();
+
+ while(iter.hasNext())
+ {
+ ChatRoom room = (ChatRoom)iter.next();
+ room.addMessageListener(this);
+ }
+
+ opSetMultiUChat.addPresenceListener(this);
+ }
+ else
+ {
+ logger.trace("Service did not have a multi im op. set.");
+ }
+ }
+
+ /**
+ * Removes the specified provider from the list of currently known providers
+ * and ignores all the messages exchanged by it
+ *
+ * @param provider the ProtocolProviderService that has been unregistered.
+ */
+ private void handleProviderRemoved(ProtocolProviderService provider)
+ {
+ OperationSetBasicInstantMessaging opSetIm
+ = (OperationSetBasicInstantMessaging) provider
+ .getSupportedOperationSets().get(
+ OperationSetBasicInstantMessaging.class.getName());
+
+ if (opSetIm != null)
+ {
+ opSetIm.removeMessageListener(this);
+ }
+
+ OperationSetMultiUserChat opSetMultiUChat
+ = (OperationSetMultiUserChat) provider
+ .getSupportedOperationSets().get(
+ OperationSetMultiUserChat.class.getName());
+
+ if (opSetMultiUChat != null)
+ {
+ Iterator iter =
+ opSetMultiUChat.getCurrentlyJoinedChatRooms().iterator();
+
+ while(iter.hasNext())
+ {
+ ChatRoom room = (ChatRoom)iter.next();
+ room.removeMessageListener(this);
+ }
+ }
+ }
+
+ /**
+ * Called to notify interested parties that a change in our presence in
+ * a chat room has occurred. Changes may include us being kicked, join,
+ * left.
+ * @param evt the LocalUserChatRoomPresenceChangeEvent instance
+ * containing the chat room and the type, and reason of the change
+ */
+ public void localUserPresenceChanged(LocalUserChatRoomPresenceChangeEvent evt)
+ {
+ if(evt.getEventType() ==
+ LocalUserChatRoomPresenceChangeEvent.LOCAL_USER_JOINED)
+ {
+ if (!evt.getChatRoom().isSystem())
+ evt.getChatRoom().addMessageListener(this);
+ }
+ else
+ {
+ evt.getChatRoom().removeMessageListener(this);
+ }
+ }
+
+ public void messageReceived(MessageReceivedEvent evt)
+ {
+ try
+ {
+ ExportedWindow win =
+ uiService.getExportedWindow(ExportedWindow.CHAT_WINDOW);
+
+ if(win == null || win.getSource() == null ||
+ !(win.getSource() instanceof JFrame))
+ return;
+
+ JFrame fr = (JFrame)win.getSource();
+
+ if(fr != null)
+ Alerter.newInstance().alert(fr);
+ }
+ catch (Exception ex)
+ {
+ logger.error("Cannot alert chat window!");
+ }
+ }
+
+ public void messageDelivered(MessageDeliveredEvent evt)
+ {
+ // do nothing
+ }
+
+ public void messageDeliveryFailed(MessageDeliveryFailedEvent evt)
+ {
+ // do nothing
+ }
+
+ public void messageReceived(ChatRoomMessageReceivedEvent evt)
+ {
+ try
+ {
+ ExportedWindow win =
+ uiService.getExportedWindow(ExportedWindow.CHAT_WINDOW);
+
+ if(win == null || win.getSource() == null ||
+ !(win.getSource() instanceof JFrame))
+ return;
+
+ JFrame fr = (JFrame)win.getSource();
+
+ if(fr != null)
+ Alerter.newInstance().alert(fr);
+ }
+ catch (Exception ex)
+ {
+ logger.error("Cannot alert chat window!");
+ }
+ }
+
+ public void messageDelivered(ChatRoomMessageDeliveredEvent evt)
+ {
+ // do nothing
+ }
+
+ public void messageDeliveryFailed(ChatRoomMessageDeliveryFailedEvent evt)
+ {
+ // do nothing
+ }
+
+ /**
+ * When new protocol provider is registered we check
+ * does it supports needed Op. Sets and if so add a listener to it
+ *
+ * @param serviceEvent ServiceEvent
+ */
+ public void serviceChanged(ServiceEvent serviceEvent)
+ {
+ Object sService =
+ bundleContext.getService(serviceEvent.getServiceReference());
+
+ logger.trace("Received a service event for: " +
+ sService.getClass().getName());
+
+ // we don't care if the source service is not a protocol provider
+ if (! (sService instanceof ProtocolProviderService))
+ {
+ return;
+ }
+
+ logger.debug("Service is a protocol provider.");
+ if (serviceEvent.getType() == ServiceEvent.REGISTERED)
+ {
+ logger.debug("Handling registration of a new Protocol Provider.");
+
+ this.handleProviderAdded((ProtocolProviderService)sService);
+ }
+ else if (serviceEvent.getType() == ServiceEvent.UNREGISTERING)
+ {
+ this.handleProviderRemoved( (ProtocolProviderService) sService);
+ }
+ }
+}
diff --git a/src/net/java/sip/communicator/plugin/contactinfo/chatalerter.manifest.mf b/src/net/java/sip/communicator/plugin/contactinfo/chatalerter.manifest.mf
new file mode 100644
index 000000000..a98d4d107
--- /dev/null
+++ b/src/net/java/sip/communicator/plugin/contactinfo/chatalerter.manifest.mf
@@ -0,0 +1,12 @@
+Bundle-Activator: net.java.sip.communicator.plugin.chatalerter.ChatAlerterActivator
+Bundle-Name: Chat Alerter
+Bundle-Description: A plug-in that alerts for new messages by flashing the window in the taskbar.
+Bundle-Vendor: sip-communicator.org
+Bundle-Version: 0.0.1
+Import-Package: org.osgi.framework,
+ net.java.sip.communicator.util,
+ net.java.sip.communicator.service.gui,
+ net.java.sip.communicator.service.protocol,
+ net.java.sip.communicator.service.protocol.event,
+ com.apple.cocoa.application,
+ javax.swing
\ No newline at end of file
diff --git a/src/net/java/sip/communicator/service/gui/ExportedWindow.java b/src/net/java/sip/communicator/service/gui/ExportedWindow.java
index 4e68a9f6b..2dcb34111 100644
--- a/src/net/java/sip/communicator/service/gui/ExportedWindow.java
+++ b/src/net/java/sip/communicator/service/gui/ExportedWindow.java
@@ -92,4 +92,10 @@ public interface ExportedWindow
* Maximizes the window.
*/
public void maximize();
+
+ /**
+ * The source of the window
+ * @return the source of the window
+ */
+ public Object getSource();
}