diff --git a/src/net/java/sip/communicator/impl/growlnotification/GrowlNotificationActivator.java b/src/net/java/sip/communicator/impl/growlnotification/GrowlNotificationActivator.java
index e4670ad96..8892ea6b9 100644
--- a/src/net/java/sip/communicator/impl/growlnotification/GrowlNotificationActivator.java
+++ b/src/net/java/sip/communicator/impl/growlnotification/GrowlNotificationActivator.java
@@ -6,7 +6,10 @@
*/
package net.java.sip.communicator.impl.growlnotification;
+import net.java.sip.communicator.service.configuration.*;
import net.java.sip.communicator.service.resources.*;
+import net.java.sip.communicator.service.systray.*;
+
import org.osgi.framework.*;
import net.java.sip.communicator.util.*;
@@ -15,6 +18,7 @@
* Activates the GrowlNotificationService
*
* @author Romain Kuntz
+ * @author Egidijus Jankauskas
*/
public class GrowlNotificationActivator
implements BundleActivator
@@ -27,11 +31,21 @@ public class GrowlNotificationActivator
private static final Logger logger =
Logger.getLogger(GrowlNotificationActivator.class);
+ /**
+ * A reference to the configuration service.
+ */
+ private static ConfigurationService configService;
+
/**
* A reference to the resource management service.
*/
private static ResourceManagementService resourcesService;
+ /**
+ * A reference to the Growl notification service
+ */
+ private static GrowlNotificationServiceImpl handler;
+
/**
* Initialize and start Growl Notifications Service
*
@@ -40,32 +54,51 @@ public class GrowlNotificationActivator
*/
public void start(BundleContext bc) throws Exception
{
- /* Check Java version: do not start if Java 6 */
- /* Actually, this plugin uses the Growl Java bindings which
- * in turn uses the Cocoa Java bridge. Java 6 on Mac OS X is
- * 64-bit only (as of 01/2008), and the Cocoa-Java bridge
- * will certainly never get any 64-bit support (it has been
- * deprecated).
- */
- String version = System.getProperty("java.version");
- char minor = version.charAt(2);
- if(minor > '5') {
- logger.info("Growl Notification Plugin cannot be started " +
- "on JDK version " + version);
- } else {
- bundleContext = bc;
- /* Create and start the Growl Notification service. */
- new GrowlNotificationServiceImpl().start(bc);
+ logger.info("Growl Notification ...[Starting]");
+ bundleContext = bc;
+
+ getConfigurationService();
- logger.info("Growl Notification Plugin ...[Started]");
+ handler = new GrowlNotificationServiceImpl();
+
+ if (handler.isGrowlInstalled())
+ {
+ handler.start(bc);
+ bc.registerService(PopupMessageHandler.class.getName(), handler, null);
+ } else
+ {
+ logger.info("Growl Notification ...[Aborted]");
+ return;
}
+
+ logger.info("Growl Notification ...[Started]");
}
public void stop(BundleContext bContext) throws Exception
{
+ handler.stop(bContext);
logger.info("Growl Notification Service ...[Stopped]");
}
+ /**
+ * Returns the ConfigurationService obtained from the bundle
+ * context.
+ * @return the ConfigurationService obtained from the bundle
+ * context
+ */
+ public static ConfigurationService getConfigurationService()
+ {
+ if(configService == null) {
+ ServiceReference configReference = bundleContext
+ .getServiceReference(ConfigurationService.class.getName());
+
+ configService = (ConfigurationService) bundleContext
+ .getService(configReference);
+ }
+
+ return configService;
+ }
+
/**
* Returns the ResourceManagementService obtained from the bundle
* context.
@@ -78,6 +111,5 @@ public static ResourceManagementService getResources()
resourcesService =
ResourceManagementServiceUtils.getService(bundleContext);
return resourcesService;
-
}
-}
+}
\ No newline at end of file
diff --git a/src/net/java/sip/communicator/impl/growlnotification/GrowlNotificationServiceImpl.java b/src/net/java/sip/communicator/impl/growlnotification/GrowlNotificationServiceImpl.java
index 8751393ad..78f2ebd83 100644
--- a/src/net/java/sip/communicator/impl/growlnotification/GrowlNotificationServiceImpl.java
+++ b/src/net/java/sip/communicator/impl/growlnotification/GrowlNotificationServiceImpl.java
@@ -6,182 +6,104 @@
*/
package net.java.sip.communicator.impl.growlnotification;
-import java.lang.reflect.*;
import java.util.*;
-
import org.osgi.framework.*;
-import com.growl.*;
-
import net.java.sip.communicator.service.systray.*;
import net.java.sip.communicator.service.systray.event.*;
import net.java.sip.communicator.util.*;
+import org.growl4j.*;
+
+// TO-DO: use a better icon in registration.
/**
* The Growl Notification Service displays on-screen information such as
* messages or call received, etc.
*
* @author Romain Kuntz
+ * @author Egidijus Jankauskas
*/
public class GrowlNotificationServiceImpl
- implements PopupMessageHandler
+ implements PopupMessageHandler,
+ GrowlCallbacksListener
{
/**
* The logger for this class.
*/
private static Logger logger =
Logger.getLogger(GrowlNotificationServiceImpl.class);
-
+
/**
- * The Growl notifier
+ * A variable that acts as a buffer to temporarily keep all PopupMessages
+ * that were sent to Growl Daemon.
*/
- private Growl notifier;
+ private static final HashMap shownPopups =
+ new HashMap(10);
+
+ private Growl growl = null;
- /**
- * The notifyGrowlOf/setAllowedNotifications/setDefaultNotifications
- * methods of the growl class. We use reflection to access them
- * in order to avoid compilation errors on non mac platforms.
- */
- private Method notifyMethod = null;
- private Method setAllowedNotifMethod = null;
- private Method setDefaultNotifMethod = null;
-
- /* All Growl Notifications and the default ones */
- private String [] allNotif =
- new String[] { "SIP Communicator Started",
- "Protocol events",
- "Message Received",
- "Message Sent"};
-
- private String [] defaultNotif =
- new String[] { "SIP Communicator Started",
- "Message Received" };
-
- /**
- * The path to the SIP Communicator icon used in Growl's configuration
- * menu and protocol events messages
- */
- private String sipIconPath = "resources/images/logo/sc_logo_128x128.icns";
/** The list of all added popup listeners */
private final List popupMessageListeners =
new Vector();
+
/**
- * starts the service. Creates a Growl notifier, and check the current
- * registerd protocol providers which supports BasicIM and adds message
+ * Starts the service. Creates a Growl notifier, and check the current
+ * registered protocol providers which supports BasicIM and adds message
* listener to them.
*
* @param bc a currently valid bundle context
* @throws java.lang.Exception if we fail initializing the growl notifier.
*/
public void start(BundleContext bc)
- throws Exception
{
logger.debug("Starting the Growl Notification implementation.");
-
- /* Register to Growl */
- try
- {
- Constructor constructor = Growl.class.getConstructor(
- new Class[] { String.class, String.class });
- notifier = constructor.newInstance(
- new Object[]{"SIP Communicator", sipIconPath});
-
- //init the setAllowedNotifications method
- setAllowedNotifMethod = Growl.class.getMethod(
- "setAllowedNotifications"
- , new Class[]{String[].class});
-
- //init the setDefaultNotifications method
- setDefaultNotifMethod = Growl.class.getMethod(
- "setDefaultNotifications"
- , new Class[]{String[].class});
-
- //init the notifyGrowlOf method
- notifyMethod = Growl.class.getMethod(
- "notifyGrowlOf"
- , new Class[]{String.class, String.class,
- String.class, String.class});
-
- setAllowedNotifications(allNotif);
- setDefaultNotifications(defaultNotif);
- notifier.register();
-
- notifyGrowlOf("SIP Communicator Started"
- , sipIconPath
- , "Welcome to SIP Communicator"
- , "http://www.sip-communicator.org");
- }
- catch (Exception ex)
+
+ if(Growl.isGrowlRunning())
{
- logger.error("Could not send the message to Growl", ex);
- throw ex;
- }
-
- bc.registerService(PopupMessageHandler.class.getName(), this, null);
+ String[] dict = { "Default", "Welcome message" };
+ byte[] sipIcon = GrowlNotificationActivator.getResources().
+ getImageInBytes("service.gui.SIP_COMMUNICATOR_LOGO_45x45");
+ growl = new Growl ("SIP Communicator", "net.sip-communicator", sipIcon, dict, dict);
+ growl.addClickedNotificationsListener(this);
+
+ growl.notifyGrowlOf("SIP Communicator",
+ "http://www.sip-communicator.org/",
+ "Welcome message",
+ null, null);
+ }
}
/**
- * stops the service.
+ * Stops the service.
*
* @param bc BundleContext
*/
public void stop(BundleContext bc)
{
- }
-
- /**
- * Convenience method that defers to notifier.notifyGrowlOf() using
- * reflection without referencing it directly. The purpose of this method
- * is to allow the class to compile on non-mac systems.
- *
- * @param inNotificationName The name of one of the notifications we told
- * growl about.
- * @param inTitle The Title of our Notification as Growl will show it
- * @param inDescription The Description of our Notification as Growl will
- * display it
- *
- * @throws Exception When a notification is not known
- */
- public void notifyGrowlOf(String inNotificationName,
- String inImagePath,
- String inTitle,
- String inDescription)
- throws Exception
- {
- // remove eventual html code before showing the popup message
- inDescription = inDescription.replaceAll("?\\w++[^>]*+>", "");
-
- notifyMethod.invoke(
- notifier, new Object[]{inNotificationName, inImagePath,
- inTitle, inDescription});
+ if (growl != null)
+ {
+ growl.doFinalCleanUp();
+ }
}
/**
- * Convenience method that defers to notifier.setAllowedNotifications()
- * using reflection without referencing it directly. The purpose of this
- * method is to allow the class to compile on non-mac systems.
- *
- * @param inAllNotes The list of allowed Notifications
+ * Checks if Growl is present on the system
+ * @return true if Growl is installed and false otherwise
*/
- public void setAllowedNotifications(String [] inAllNotes)
- throws Exception
+ public boolean isGrowlInstalled()
{
- setAllowedNotifMethod.invoke(notifier, new Object[]{inAllNotes});
+ return Growl.isGrowlInstalled();
}
-
+
/**
- * Convenience method that defers to notifier.setDefaultNotifications()
- * using reflection without referencing it directly. The purpose of this
- * method is to allow the class to compile on non-mac systems.
- *
- * @param inDefNotes The list of default Notifications
+ * Checks if Growl is running
+ * @return true if Growl is running and false otherwise
*/
- public void setDefaultNotifications(String [] inDefNotes)
- throws Exception
+ public boolean isGrowlRunning()
{
- setDefaultNotifMethod.invoke(notifier, new Object[]{inDefNotes});
+ return Growl.isGrowlRunning();
}
public void addPopupMessageListener(SystrayPopupMessageListener listener)
@@ -208,19 +130,82 @@ public void removePopupMessageListener(SystrayPopupMessageListener listener)
*/
public void showPopupMessage(PopupMessage popupMessage)
{
- try
- {
- notifyGrowlOf("Message Received"
- , sipIconPath
- , popupMessage.getMessageTitle()
- , popupMessage.getMessage());
+ long timestamp = System.currentTimeMillis();
+ synchronized(shownPopups) {
+ shownPopups.put(timestamp, popupMessage);
}
- catch (Exception ex)
+
+ String messageBody = popupMessage.getMessage();
+ String messageTitle = popupMessage.getMessageTitle();
+
+ // remove eventual HTML code before showing the pop-up message
+ messageBody = messageBody.replaceAll("?\\w++[^>]*+>", "");
+ messageTitle = messageTitle.replaceAll("?\\w++[^>]*+>", "");
+
+ growl.notifyGrowlOf(messageTitle,
+ messageBody,
+ "Default",
+ popupMessage.getIcon(),
+ timestamp);
+ }
+
+ /**
+ * Notifies all interested listeners that a SystrayPopupMessageEvent
+ * occured.
+ *
+ * @param SystrayPopupMessageEvent the evt to send to listener.
+ */
+ private void firePopupMessageClicked(SystrayPopupMessageEvent evt)
+ {
+ logger.trace("Will dispatch the following popup event: " + evt);
+
+ List listeners;
+ synchronized (popupMessageListeners)
{
- logger.error("Could not notify the received message to Growl", ex);
+ listeners =
+ new ArrayList(
+ popupMessageListeners);
+ }
+
+ for (SystrayPopupMessageListener listener : listeners)
+ listener.popupMessageClicked(evt);
+ }
+
+ /**
+ * This method is called by Growl when the Growl notification is not clicked
+ * @param context is an object that is used to identify sent notification
+ */
+ public void growlNotificationTimedOut(Object context)
+ {
+ PopupMessage m = (PopupMessage)shownPopups.get(context);
+ if (m != null) {
+ synchronized(shownPopups) {
+ shownPopups.remove(context);
+ }
+ logger.trace("Growl notification timed-out :" +
+ m.getMessageTitle() + ": " + m.getMessage());
}
+
}
+ /**
+ * This method is called by Growl when the Growl notification is clicked
+ * @param context is an object that is used to identify sent notification
+ */
+ public void growlNotificationWasClicked(Object context)
+ {
+ PopupMessage m = (PopupMessage)shownPopups.get(context);
+ if (m != null) {
+ synchronized(shownPopups) {
+ shownPopups.remove(context);
+ }
+
+ firePopupMessageClicked(new SystrayPopupMessageEvent(this, m.getTag()));
+ logger.trace("Growl message clicked :" +
+ m.getMessageTitle() + ": " + m.getMessage());
+ }
+ }
+
/**
* Implements toString from PopupMessageHandler
* @return a description of this handler
@@ -230,4 +215,15 @@ public String toString()
return GrowlNotificationActivator.getResources()
.getI18NString("impl.growlnotification.POPUP_MESSAGE_HANDLER");
}
+
+ /**
+ * Implements getPreferenceIndex from PopupMessageHandler.
+ * This handler is able to show images, detect clicks, match a click to a
+ * message, and use a native popup mechanism, thus the index is 4.
+ * @return a preference index
+ */
+ public int getPreferenceIndex()
+ {
+ return 4;
+ }
}
diff --git a/src/net/java/sip/communicator/impl/growlnotification/growlnotification.manifest.mf b/src/net/java/sip/communicator/impl/growlnotification/growlnotification.manifest.mf
index fb78f334b..a707c6410 100644
--- a/src/net/java/sip/communicator/impl/growlnotification/growlnotification.manifest.mf
+++ b/src/net/java/sip/communicator/impl/growlnotification/growlnotification.manifest.mf
@@ -5,8 +5,11 @@ Bundle-Vendor: sip-communicator.org
Bundle-Version: 0.0.1
System-Bundle: yes
Import-Package: org.osgi.framework,
+ net.java.sip.communicator.service.configuration,
+ net.java.sip.communicator.service.protocol,
net.java.sip.communicator.util,
net.java.sip.communicator.service.resources,
net.java.sip.communicator.service.systray,
net.java.sip.communicator.service.systray.event,
- com.growl
+ net.java.sip.communicator.util.swing,
+ org.growl4j