diff --git a/src/java/org/jivesoftware/sparkimpl/settings/JiveInfo.java b/src/java/org/jivesoftware/sparkimpl/settings/JiveInfo.java
index 0be766143..dc075770a 100644
--- a/src/java/org/jivesoftware/sparkimpl/settings/JiveInfo.java
+++ b/src/java/org/jivesoftware/sparkimpl/settings/JiveInfo.java
@@ -17,7 +17,7 @@ public class JiveInfo {
}
public static String getVersion() {
- return "1.1.9.7";
+ return "2.0.0.1";
}
public static String getOS() {
diff --git a/src/plugins/growl/build.xml b/src/plugins/growl/build.xml
new file mode 100644
index 000000000..a92ba317c
--- /dev/null
+++ b/src/plugins/growl/build.xml
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/plugins/growl/growl.iml b/src/plugins/growl/growl.iml
new file mode 100644
index 000000000..fc8cf1dd8
--- /dev/null
+++ b/src/plugins/growl/growl.iml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/plugins/growl/src/com/growl/Growl.java b/src/plugins/growl/src/com/growl/Growl.java
new file mode 100644
index 000000000..556273a49
--- /dev/null
+++ b/src/plugins/growl/src/com/growl/Growl.java
@@ -0,0 +1,465 @@
+/**
+ * Growl.java
+ *
+ * Version:
+ * $Id:$
+ *
+ * Revisions:
+ * $Log:$
+ *
+ */
+
+package com.growl;
+
+import com.apple.cocoa.foundation.NSDistributedNotificationCenter;
+import com.apple.cocoa.foundation.NSArray;
+import com.apple.cocoa.foundation.NSDictionary;
+import com.apple.cocoa.foundation.NSMutableDictionary;
+import com.apple.cocoa.foundation.NSData;
+import com.apple.cocoa.application.NSImage;
+
+/**
+ * A class that encapsulates the "work" of talking to growl
+ *
+ * @author Karl Adam
+ */
+public class Growl {
+
+ // defines
+ /** The name of the growl registration notification for DNC. */
+ public static final String GROWL_APP_REGISTRATION = "GrowlApplicationRegistrationNotification";
+
+ // Ticket Defines
+ /** Ticket key for the application name. */
+ public static final String GROWL_APP_NAME = "ApplicationName";
+ /** Ticket key for the application icon. */
+ public static final String GROWL_APP_ICON = "ApplicationIcon";
+ /** Ticket key for the default notifactions. */
+ public static final String GROWL_NOTIFICATIONS_DEFAULT = "DefaultNotifications";
+ /** Ticket key for all notifactions. */
+ public static final String GROWL_NOTIFICATIONS_ALL = "AllNotifications";
+
+ // Notification Defines
+ /** The name of the growl notification for DNC. */
+ public static final String GROWL_NOTIFICATION = "GrowlNotification";
+ /** Notification key for the name. */
+ public static final String GROWL_NOTIFICATION_NAME = "NotificationName";
+ /** Notification key for the title. */
+ public static final String GROWL_NOTIFICATION_TITLE = "NotificationTitle";
+ /** Notification key for the description. */
+ public static final String GROWL_NOTIFICATION_DESCRIPTION = "NotificationDescription";
+ /** Notification key for the icon. */
+ public static final String GROWL_NOTIFICATION_ICON = "NotificationIcon";
+ /** Notification key for the application icon. */
+ public static final String GROWL_NOTIFICATION_APP_ICON = "NotificationAppIcon";
+ /** Notification key for the sticky flag. */
+ public static final String GROWL_NOTIFICATION_STICKY = "NotificationSticky";
+
+ // Actual instance data
+ private boolean registered; // We should only register once
+ private String appName; // "Application" Name
+ private NSData appImageData; // "application" Icon
+ private NSDictionary regDict; // Registration Dictionary
+ private NSArray allNotes; // All notifications
+ private NSArray defNotes; // Default Notifications
+ private NSDistributedNotificationCenter theCenter;
+
+ //************ Constructors **************//
+
+ /**
+ * Convenience method to contruct a growl instance, defers to Growl(String
+ * inAppName, NSData inImageData, NSArray inAllNotes, NSArray inDefNotes,
+ * boolean registerNow) with empty arrays for your notifications.
+ *
+ *
+ * @param inAppName - The Name of your "application"
+ * @param inImage - The NSImage Icon for your Application
+ *
+ */
+ public Growl(String inAppName, NSImage inImage) {
+
+ this(inAppName,
+ inImage.TIFFRepresentation(),
+ new NSArray(),
+ new NSArray(),
+ false);
+ }
+
+ /**
+ * Convenience method to contruct a growl instance, defers to Growl(String
+ * inAppName, NSData inImageData, NSArray inAllNotes, NSArray inDefNotes,
+ * boolean registerNow) with empty arrays for your notifications.
+ *
+ * @param inAppName - The Name of your "Application"
+ * @param inImageData - The NSData for your NSImage
+ */
+ public Growl(String inAppName, NSData inImageData) {
+
+ this(inAppName,
+ inImageData,
+ new NSArray(),
+ new NSArray(),
+ false);
+ }
+
+ /**
+ * Convenience method to contruct a growl instance, defers to Growl(String
+ * inAppName, NSData inImageData, NSArray inAllNotes, NSArray inDefNotes,
+ * boolean registerNow) with empty arrays for your notifications.
+ *
+ * @param inAppName - The Name of your "Application"
+ * @param inImagePath - The path to your icon
+ *
+ */
+ public Growl(String inAppName, String inImagePath) {
+
+ this(inAppName,
+ new NSImage(inImagePath, false).TIFFRepresentation(),
+ new NSArray(),
+ new NSArray(),
+ false);
+ }
+
+ /**
+ * Convenience method to contruct a growl instance, defers to Growl(String
+ * inAppName, NSData inImageData, NSArray inAllNotes, NSArray inDefNotes,
+ * boolean registerNow) with the arrays passed here and empty Data for the icon.
+ *
+ * @param inAppName - The Name of your "Application"
+ * @param inAllNotes - A String Array with the name of all your notifications
+ * @param inDefNotes - A String Array with the na,es of the Notifications on
+ * by default
+ */
+ public Growl(String inAppName, String [] inAllNotes, String [] inDefNotes) {
+
+ this(inAppName,
+ new NSData(),
+ new NSArray(inAllNotes),
+ new NSArray(inDefNotes),
+ false);
+ }
+
+ /**
+ * Convenience method to contruct a growl instance, defers to Growl(String
+ * inAppName, NSData inImageData, NSArray inAllNotes, NSArray inDefNotes,
+ * boolean registerNow) with empty arrays for your notifications.
+ *
+ * @param inAppName - The Name of your "Application"
+ * @param inImageData - The Data of your "Application"'s icon
+ * @param inAllNotes - The NSArray of Strings of all your Notifications
+ * @param inDefNotes - The NSArray of Strings of your default Notifications
+ * @param registerNow - Since we have all the necessary info we can go ahead
+ * and register
+ */
+ public Growl(String inAppName, NSData inImageData, NSArray inAllNotes,
+ NSArray inDefNotes, boolean registerNow) {
+ appName = inAppName;
+ appImageData = inImageData;
+ allNotes = inAllNotes;
+ defNotes = inDefNotes;
+
+ theCenter = (NSDistributedNotificationCenter)NSDistributedNotificationCenter.defaultCenter();
+
+ if (registerNow) {
+ register();
+ }
+ }
+
+ //************ Commonly Used Methods **************//
+
+ /**
+ * Register all our notifications with Growl, this should only be called
+ * once.
+ * @return true.
+ */
+ public boolean register() {
+ if (!registered) {
+
+ // Construct our dictionary
+ // Make the arrays of objects then keys
+ Object [] objects = { appName, allNotes, defNotes, appImageData };
+ String [] keys = { GROWL_APP_NAME,
+ GROWL_NOTIFICATIONS_ALL,
+ GROWL_NOTIFICATIONS_DEFAULT,
+ GROWL_APP_ICON};
+
+ // Make the Dictionary
+ regDict = new NSDictionary(objects, keys);
+
+ theCenter.postNotification(GROWL_APP_REGISTRATION, // notificationName
+ (String)null, // anObject
+ regDict, // userInfoDictionary
+ true); // deliverImmediately
+ }
+
+ return true;
+ }
+
+ /**
+ * The fun part is actually sending those notifications we worked so hard for
+ * so here we let growl know about things we think the user would like, and growl
+ * decides if that is the case.
+ *
+ * @param inNotificationName - The name of one of the notifications we told growl
+ * about.
+ * @param inIconData - The NSData for the icon for this notification, can be null
+ * @param inTitle - The Title of our Notification as Growl will show it
+ * @param inDescription - The Description of our Notification as Growl will
+ * display it
+ * @param inExtraInfo - Growl is flexible and allows Display Plugins to do as they
+ * please with thier own special keys and values, you may use
+ * them here. These may be ignored by either the user's
+ * preferences or the current Display Plugin. This can be null
+ * @param inSticky - Whether the Growl notification should be sticky
+ *
+ * @throws Exception When a notification is not known
+ */
+ public void notifyGrowlOf(String inNotificationName, NSData inIconData,
+ String inTitle, String inDescription,
+ NSDictionary inExtraInfo, boolean inSticky) throws Exception {
+ NSMutableDictionary noteDict = new NSMutableDictionary();
+
+ if (!allNotes.containsObject(inNotificationName)) {
+ throw new Exception("Undefined Notification attempted");
+ }
+
+ noteDict.setObjectForKey(inNotificationName, GROWL_NOTIFICATION_NAME);
+ noteDict.setObjectForKey(inTitle, GROWL_NOTIFICATION_TITLE);
+ noteDict.setObjectForKey(inDescription, GROWL_NOTIFICATION_DESCRIPTION);
+ noteDict.setObjectForKey(appName, GROWL_APP_NAME);
+ if (inIconData != null) {
+ noteDict.setObjectForKey(inIconData, GROWL_NOTIFICATION_ICON);
+ }
+
+ if (inSticky) {
+ noteDict.setObjectForKey(new Integer(1), GROWL_NOTIFICATION_STICKY);
+ }
+
+ if (inExtraInfo != null) {
+ noteDict.addEntriesFromDictionary(inExtraInfo);
+ }
+
+ theCenter.postNotification(GROWL_NOTIFICATION,
+ (String)null,
+ noteDict,
+ true);
+ }
+
+ /**
+ * Convenience method that defers to notifyGrowlOf(String inNotificationName,
+ * NSData inIconData, String inTitle, String inDescription,
+ * NSDictionary inExtraInfo, boolean inSticky)
+ * This is primarily for compatibility with older code
+ *
+ * @param inNotificationName - The name of one of the notifications we told growl
+ * about.
+ * @param inIconData - The NSData for the icon for this notification, can be null
+ * @param inTitle - The Title of our Notification as Growl will show it
+ * @param inDescription - The Description of our Notification as Growl will
+ * display it
+ * @param inExtraInfo - Growl is flexible and allows Display Plugins to do as
+ * they please with their own special keys and values, you
+ * may use them here. These may be ignored by either the
+ * user's preferences or the current Display Plugin. This
+ * can be null.
+ *
+ * @throws Exception When a notification is not known
+ *
+ */
+ public void notifyGrowlOf(String inNotificationName, NSData inIconData,
+ String inTitle, String inDescription,
+ NSDictionary inExtraInfo) throws Exception {
+
+ notifyGrowlOf(inNotificationName, inIconData, inTitle, inDescription,
+ inExtraInfo, false);
+ }
+
+ /**
+ * Convenienve method that defers to notifyGrowlOf(String inNotificationName,
+ * NSData inIconData, String inTitle, String inDescription,
+ * NSDictionary inExtraInfo) with null passed for icon and extraInfo arguments
+ *
+ * @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 inTitle,
+ String inDescription) throws Exception {
+ notifyGrowlOf(inNotificationName, (NSData)null,
+ inTitle, inDescription, (NSDictionary)null, false);
+ }
+
+ /**
+ * Convenience method that defers to notifyGrowlOf(String inNotificationName,
+ * NSData inIconData, String inTitle, String inDescription,
+ * NSDictionary inExtraInfo, boolean inSticky)
+ * with null passed for icon and extraInfo arguments
+ *
+ * @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
+ * @param inSticky - Whether our notification should be sticky
+ *
+ * @throws Exception When a notification is not known
+ *
+ */
+ public void notifyGrowlOf(String inNotificationName, String inTitle,
+ String inDescription, boolean inSticky) throws Exception {
+ notifyGrowlOf(inNotificationName, (NSData)null,
+ inTitle, inDescription, (NSDictionary)null, inSticky);
+ }
+
+ /**
+ * Defers to notifyGrowlOf(String inNotificationName, NSData inIconData,
+ * String inTitle, String inDescription, NSDictionary inExtraInfo) with null
+ * passed for icon and extraInfo arguments
+ *
+ * @param inNotificationName - The name of one of the notifications we told growl
+ * about.
+ * @param inImage - The notification image.
+ * @param inTitle - The Title of our Notification as Growl will show it
+ * @param inDescription - The Description of our Notification as Growl will
+ * display it
+ * @param inExtraInfo - Look above for info
+ *
+ * @throws Exception When a notification is not known
+ *
+ */
+ public void notifyGrowlOf(String inNotificationName, NSImage inImage,
+ String inTitle, String inDescription,
+ NSDictionary inExtraInfo) throws Exception {
+
+ notifyGrowlOf(inNotificationName, inImage.TIFFRepresentation(),
+ inTitle, inDescription, inExtraInfo, false);
+ }
+
+ /**
+ * Convenienve method that defers to notifyGrowlOf(String inNotificationName,
+ * NSData inIconData, String inTitle, String inDescription,
+ * NSDictionary inExtraInfo) with null passed for extraInfo
+ *
+ * @param inNotificationName - The name of one of the notifications we told growl
+ * about.
+ * @param inImagePath - Path to the image for this notification
+ * @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 {
+
+ notifyGrowlOf(inNotificationName,
+ new NSImage(inImagePath, false).TIFFRepresentation(),
+ inTitle, inDescription, (NSDictionary)null, false);
+ }
+
+ //************ Accessors **************//
+
+ /**
+ * Accessor for The currently set "Application" Name
+ *
+ * @return String - Application Name
+ */
+ public String applicationName() {
+ return appName;
+ }
+
+ /**
+ * Accessor for the Array of allowed Notifications returned an NSArray
+ *
+ * @return the array of allowed notifications.
+ */
+ public NSArray allowedNotifications() {
+ return allNotes;
+ }
+
+ /**
+ * Accessor for the Array of default Notifications returned as an NSArray
+ *
+ * @return the array of default notifications.
+ */
+ public NSArray defaultNotifications() {
+ return defNotes;
+ }
+
+ //************ Mutators **************//
+
+ /**
+ * Sets The name of the Application talking to growl
+ *
+ * @param inAppName - The Application Name
+ */
+ public void setApplicationName(String inAppName) {
+ appName = inAppName;
+ }
+
+ /**
+ * Set the list of allowed Notifications
+ *
+ * @param inAllNotes - The array of allowed Notifications
+ */
+ public void setAllowedNotifications(NSArray inAllNotes) {
+ allNotes = inAllNotes;
+ }
+
+ /**
+ * Set the list of allowed Notifications
+ *
+ * @param inAllNotes - The array of allowed Notifications
+ *
+ */
+ public void setAllowedNotifications(String[] inAllNotes) {
+ allNotes = new NSArray(inAllNotes);
+ }
+
+ /**
+ * Set the list of Default Notfiications
+ *
+ * @param inDefNotes - The default Notifications
+ *
+ * @throws Exception when an element of the array is not in the
+ * allowedNotifications
+ */
+ public void setDefaultNotifications(NSArray inDefNotes) throws Exception {
+ int stop = inDefNotes.count();
+ int i = 0;
+
+ for(i = 0; i < stop; i++) {
+ if (!allNotes.containsObject(inDefNotes.objectAtIndex(i))) {
+ throw new Exception("Array Element not in Allowed Notifications");
+ }
+ }
+
+ defNotes = inDefNotes;
+ }
+
+ /**
+ * Set the list of Default Notfiications
+ *
+ * @param inDefNotes - The default Notifications
+ *
+ * @throws Exception when an element of the array is not in the
+ * allowedNotifications
+ *
+ */
+ public void setDefaultNotifications(String [] inDefNotes) throws Exception {
+ int stop = inDefNotes.length;
+ int i = 0;
+
+ for(i = 0; i < stop; i++) {
+ if (! allNotes.containsObject(inDefNotes[i])) {
+ throw new Exception("Array Element not in Allowed Notifications");
+ }
+ }
+
+ defNotes = new NSArray(inDefNotes);
+ }
+}
diff --git a/src/plugins/growl/src/com/jivesoftware/spark/plugin/growl/GrowlMessageListener.java b/src/plugins/growl/src/com/jivesoftware/spark/plugin/growl/GrowlMessageListener.java
new file mode 100644
index 000000000..965013bcf
--- /dev/null
+++ b/src/plugins/growl/src/com/jivesoftware/spark/plugin/growl/GrowlMessageListener.java
@@ -0,0 +1,123 @@
+/**
+ * $Revision: 22540 $
+ * $Date: 2005-10-10 08:44:25 -0700 (Mon, 10 Oct 2005) $
+ *
+ * Copyright (C) 1999-2005 Jive Software. All rights reserved.
+ *
+ * This software is the proprietary information of Jive Software.
+ * Use is subject to license terms.
+ */
+package com.jivesoftware.spark.plugin.growl;
+
+import com.apple.cocoa.application.NSImage;
+import com.apple.cocoa.foundation.NSData;
+import com.growl.Growl;
+import org.jivesoftware.smack.packet.Message;
+import org.jivesoftware.smack.util.StringUtils;
+import org.jivesoftware.smackx.packet.VCard;
+import org.jivesoftware.spark.ui.MessageListener;
+import org.jivesoftware.spark.ui.ChatRoom;
+import org.jivesoftware.spark.SparkManager;
+
+import javax.swing.*;
+import java.io.InputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+/**
+ * @author Andrew Wright
+ */
+public class GrowlMessageListener implements MessageListener {
+
+ private Growl growl;
+
+ public GrowlMessageListener() {
+ String[] notes = {"Message Received"};
+ growl = new Growl("Spark", notes, notes);
+ growl.register();
+ }
+
+ public void messageReceived(final ChatRoom room, final Message message) {
+ if (!SparkManager.getMainWindow().isFocused()) {
+
+ SwingUtilities.invokeLater(new Runnable() {
+
+ public void run() {
+ try {
+ String name = SparkManager.getUserManager().getUserNicknameFromJID(message.getFrom());
+
+ // Since it looks the method can return null do this in case
+ if (name == null) {
+ name = StringUtils.parseName(message.getFrom());
+ }
+
+ VCard vCard = null;
+
+ try {
+ vCard = SparkManager.getVCardManager().getVCard(
+ StringUtils.parseBareAddress(message.getFrom()));
+ }
+ catch (Exception e) {
+ // vcard can time out so ignore
+ }
+
+ NSImage image = null;
+ if (vCard != null) {
+ byte[] bytes = vCard.getAvatar();
+ if (bytes != null) {
+ try {
+ NSData data = new NSData(bytes);
+ image = new NSImage(data);
+ }
+ catch (Exception e) {
+ // just incase there is an error i didn't intend
+ }
+ }
+ }
+
+ if (image == null) {
+ image = getImage("/images/message-32x32.png");
+ }
+
+ growl.notifyGrowlOf("Message Received", image, name, message.getBody(), null);
+
+ }
+ catch (Exception e) {
+ Logger.logError(e.getMessage(), e);
+ }
+
+ }
+ });
+ }
+ }
+
+ public void messageSent(ChatRoom room, Message message) {
+ // Ignore
+ }
+
+ /**
+ * Creates a {@link com.apple.cocoa.application.NSImage} from a string that points to an image in the class
+ *
+ * @param image classpath path of an image
+ * @return an cocoa image object
+ */
+ private NSImage getImage(String image) {
+ InputStream in = this.getClass().getResourceAsStream(image);
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+
+ byte[] buff = new byte[10 * 1024];
+ int len;
+ try {
+ while ((len = in.read(buff)) != -1) {
+ out.write(buff, 0, len);
+ }
+ in.close();
+ out.close();
+ } catch (IOException e) {
+ Logger.logError(e.getMessage(), e);
+ }
+
+ NSData data = new NSData(out.toByteArray());
+ return new NSImage(data);
+ }
+}
diff --git a/src/plugins/growl/src/com/jivesoftware/spark/plugin/growl/GrowlPlugin.java b/src/plugins/growl/src/com/jivesoftware/spark/plugin/growl/GrowlPlugin.java
new file mode 100644
index 000000000..009264e20
--- /dev/null
+++ b/src/plugins/growl/src/com/jivesoftware/spark/plugin/growl/GrowlPlugin.java
@@ -0,0 +1,45 @@
+/**
+ * $Revision: 22540 $
+ * $Date: 2005-10-10 08:44:25 -0700 (Mon, 10 Oct 2005) $
+ *
+ * Copyright (C) 1999-2005 Jive Software. All rights reserved.
+ *
+ * This software is the proprietary information of Jive Software.
+ * Use is subject to license terms.
+ */
+package com.jivesoftware.spark.plugin.growl;
+
+import org.jivesoftware.spark.SparkManager;
+import org.jivesoftware.spark.plugin.Plugin;
+
+
+/**
+ * Provides support for Growl Notifications on Mac OS X. Growl can be acquired at
+ * http://growl.info
+ *
+ *
+ * @author Andrew Wright
+ */
+public class GrowlPlugin implements Plugin {
+
+ private GrowlRoomListener growlListener;
+
+
+ public void initialize() {
+ growlListener = new GrowlRoomListener();
+ SparkManager.getChatManager().addChatRoomListener(growlListener);
+ }
+
+ public void shutdown() {
+ SparkManager.getChatManager().removeChatRoomListener(growlListener);
+ }
+
+ public boolean canShutDown() {
+ return true;
+ }
+
+ public void uninstall() {
+ SparkManager.getChatManager().removeChatRoomListener(growlListener);
+ }
+
+}
diff --git a/src/plugins/growl/src/com/jivesoftware/spark/plugin/growl/GrowlRoomListener.java b/src/plugins/growl/src/com/jivesoftware/spark/plugin/growl/GrowlRoomListener.java
new file mode 100644
index 000000000..2b8820983
--- /dev/null
+++ b/src/plugins/growl/src/com/jivesoftware/spark/plugin/growl/GrowlRoomListener.java
@@ -0,0 +1,50 @@
+/**
+ * $Revision: 22540 $
+ * $Date: 2005-10-10 08:44:25 -0700 (Mon, 10 Oct 2005) $
+ *
+ * Copyright (C) 1999-2005 Jive Software. All rights reserved.
+ *
+ * This software is the proprietary information of Jive Software.
+ * Use is subject to license terms.
+ */
+package com.jivesoftware.spark.plugin.growl;
+
+import org.jivesoftware.spark.ui.ChatRoom;
+import org.jivesoftware.spark.ui.ChatRoomListener;
+
+
+/**
+ * @author Andrew Wright
+ */
+public class GrowlRoomListener implements ChatRoomListener {
+
+ private GrowlMessageListener growlMessageListener;
+
+ public GrowlRoomListener() {
+ growlMessageListener = new GrowlMessageListener();
+ }
+
+ public void chatRoomOpened(ChatRoom room) {
+ room.addMessageListener(growlMessageListener);
+ }
+
+ public void chatRoomLeft(ChatRoom room) {
+ // Do nothing
+ }
+
+ public void chatRoomClosed(ChatRoom room) {
+ // Do nothing
+ }
+
+ public void chatRoomActivated(ChatRoom room) {
+ // Do nothing
+ }
+
+ public void userHasJoined(ChatRoom room, String userid) {
+ // Do nothing
+ }
+
+ public void userHasLeft(ChatRoom room, String userid) {
+ // Do nothing
+ }
+}
diff --git a/src/plugins/growl/src/plugin.xml b/src/plugins/growl/src/plugin.xml
new file mode 100644
index 000000000..035e49cbc
--- /dev/null
+++ b/src/plugins/growl/src/plugin.xml
@@ -0,0 +1,10 @@
+
+ Growl Plugin
+ 1.0
+ Andrew Wright
+ http://www.jivesoftware.com
+ andrew@jivesoftware.com
+ Provides Growl notifications on Mac OS X.(http://growl.info)
+ org.jivesoftware.spark.plugin.growl.GrowlPlugin
+ 2.0.0.1
+
\ No newline at end of file