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(); }