Committing Romain's contribution - an implementation of a Growl notifier for Mac OS X

cusax-fix
Emil Ivov 19 years ago
parent 79e06d7d5b
commit 30a05992c7

@ -8,6 +8,9 @@
<property name="jdk.home" value="/usr/java/java"/>
<property name="dest" value="classes"/>
<property name="bundles.dest" value="sc-bundles"/>
<property name="bundles.dest.macosx" value="${bundles.dest}/os/macosx"/>
<property name="bundles.dest.windows" value="${bundles.dest}/os/windows"/>
<property name="bundles.dest.linux" value="${bundles.dest}/os/linux"/>
<property name="doc" value="doc"/>
<property name="java.doc" value="${doc}/api"/>
<property name="lib" value="lib"/>
@ -120,6 +123,9 @@
<pathelement location="${dest}"/>
<pathelement location="${lib}"/>
<!-- for mac specific plugins -->
<pathelement location="/System/Library/Java"/>
<!-- Include all JAR files found in lib and any of its subdirectories. -->
<fileset dir="${lib}">
<include name="*.jar"/>
@ -293,6 +299,13 @@
<mkdir dir="${doc}"/>
<mkdir dir="${java.doc}"/>
<mkdir dir="${bundles.dest}"/>
<!-- create dirs for os specific bundles -->
<mkdir dir="${bundles.dest}/os"/>
<mkdir dir="${bundles.dest.macosx}"/>
<mkdir dir="${bundles.dest.linux}"/>
<mkdir dir="${bundles.dest.windows}"/>
<mkdir dir="${test.reports.dir}"/>
<mkdir dir="${test.reports.dir}/html"/>
<mkdir dir="${release}"/>
@ -335,6 +348,7 @@
infostring="SIP Communicator"
bundleid="org.sip-communicator"
stubfile="${macosx.stubfile}"
extraclasspath="/System/Library/Java"
workingdirectory="$APP_PACKAGE/Contents/Resources/Java">
<javaproperty name="apple.laf.useScreenMenuBar" value="true"/>
@ -353,14 +367,18 @@
<include name="${lib}/felix.jar" />
<include name="${lib}/BrowserLauncher2.jar" />
<include name="${lib}/servicebinder.jar" />
<include name="${lib}/growl.jar" />
<include name="${lib}/bundle/*.jar" />
<exclude name="${lib}/bundle/junit.jar" />
<include name="${jmf.home}/*.jar" />
<include name="${bundles.dest}/*.jar" />
<include name="${bundles.dest.macosx}/*.jar" />
<exclude name="${bundles.dest}/*-slick.jar" />
</jarfileset>
<javafilelist dir="${lib}"
files="logging.properties, felix.client.run.properties"/>
<javafilelist dir="${lib}" files="logging.properties"/>
<javafilelist dir="resources/install/macosx"
files="felix.client.run.properties"/>
</jarbundler>
</target>
@ -650,7 +668,8 @@
bundle-contactlist,meta-contactlist,meta-contactlist-slick,
bundle-plugin-icqaccregwizz,bundle-plugin-jabberaccregwizz,
bundle-plugin-msnaccregwizz,bundle-plugin-sipaccregwizz,
bundle-version,bundle-version-impl,bundle-shutdown"/>
bundle-version,bundle-version-impl,bundle-shutdown,
bundle-growlnotification"/>
<!--BUNDLE-HISTORY-->
<target name="bundle-history">
@ -1116,4 +1135,14 @@ javax.swing.event, javax.swing.border"/>
prefix="net/java/sip/communicator/impl/shutdown"/>
</jar>
</target>
<!--BUNDLE-GROWLNOTIFICATION-->
<target name="bundle-growlnotification">
<!-- Creates a bundle for the growlnotification plugin.-->
<jar compress="false" destfile="${bundles.dest.macosx}/growlnotification.jar"
manifest="src/net/java/sip/communicator/impl/growlnotification/growlnotification.manifest.mf">
<zipfileset dir="${dest}/net/java/sip/communicator/impl/growlnotification"
prefix="net/java/sip/communicator/impl/growlnotification" />
</jar>
</target>
</project>

Binary file not shown.

@ -0,0 +1,98 @@
#
# Framework config properties.
#
org.osgi.framework.system.packages= org.osgi.framework; \
javax.swing; \
javax.swing.event; \
javax.swing.table; \
javax.swing.text; \
javax.swing.text.html; \
javax.accessibility; \
javax.swing.plaf; \
javax.swing.plaf.metal; \
javax.swing.plaf.basic; \
javax.imageio; \
javax.swing.tree; \
javax.swing.undo; \
javax.swing.event; \
javax.swing.border; \
javax.swing.filechooser; \
org.w3c.dom; \
org.xml.sax; \
javax.xml.parsers;\
org.apache.xml.serializer; \
javax.xml.transform; \
javax.xml.transform.dom; \
javax.xml.transform.stream; \
sun.security.action; \
javax.net.ssl; \
javax.naming; \
javax.naming.directory; \
javax.sound;\
javax.sound.sampled; \
edu.stanford.ejalbert; \
edu.stanford.ejalbert.exception; \
edu.stanford.ejalbert.exceptionhandler; \
com.growl;
felix.auto.start.1= reference:file:lib/bundle/org.apache.felix.servicebinder-0.8.0-SNAPSHOT.jar
#reference:file:lib/bundle/org.apache.felix.bundlerepository-0.8.0-SNAPSHOT.jar
#\
# file:lib/bundle/shell.jar \
# \
# file:lib/bundle/servicebinder.jar \
# file:lib/bundle/tablelayout.jar
felix.auto.start.2= \
reference:file:sc-bundles/util.jar
felix.auto.start.3= \
reference:file:sc-bundles/configuration.jar \
reference:file:sc-bundles/version.jar \
reference:file:sc-bundles/version-impl.jar \
reference:file:sc-bundles/fileaccess.jar \
reference:file:sc-bundles/protocol.jar \
reference:file:sc-bundles/contactlist.jar \
reference:file:sc-bundles/media.jar \
reference:file:sc-bundles/protocol-icq.jar \
reference:file:sc-bundles/protocol-sip.jar \
reference:file:sc-bundles/protocol-jabber.jar \
reference:file:sc-bundles/protocol-msn.jar \
reference:file:sc-bundles/netaddr.jar \
reference:file:sc-bundles/meta-cl.jar
felix.auto.start.4= \
reference:file:sc-bundles/history.jar \
reference:file:sc-bundles/msghistory.jar \
reference:file:sc-bundles/callhistory.jar
felix.auto.start.66= \
reference:file:sc-bundles/swing-ui.jar \
reference:file:sc-bundles/growlnotification.jar
felix.auto.start.67= \
reference:file:sc-bundles/icqaccregwizz.jar \
reference:file:sc-bundles/sipaccregwizz.jar \
reference:file:sc-bundles/jabberaccregwizz.jar \
reference:file:sc-bundles/msnaccregwizz.jar \
reference:file:sc-bundles/shutdown.jar
# Uncomment the following lines if you want to run the architect viewer
# bundle.
#oscar.auto.start.100= \
# file:lib/bundle/architectureviewer1.1.jar
#Specify the directory where oscar should deploy its bundles
felix.cache.profiledir=sip-communicator.bin
felix.startlevel.framework=100
felix.startlevel.bundle=100
#
# Bundle config properties.
#
#org.osgi.service.http.port=8080
#osgi.shell.telnet=on
#oscar.repository.url=file:/home/rickhall/projects/noscar/repository.xml
oscar.embedded.execution=false

@ -0,0 +1,44 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.impl.growlnotification;
import org.osgi.framework.*;
import net.java.sip.communicator.util.*;
/**
* Activates the GrowlNotificationService
*
* @author Romain Kuntz
*/
public class GrowlNotificationActivator
implements BundleActivator
{
private static Logger logger =
Logger.getLogger(GrowlNotificationActivator.class);
private GrowlNotificationServiceImpl growlNotificationService = null;
/**
* Initialize and start Growl Notifications Service
*
* @param bundleContext BundleContext
* @throws Exception
*/
public void start(BundleContext bundleContext) throws Exception
{
/* Create and start the Growl Notification service. */
growlNotificationService = new GrowlNotificationServiceImpl();
growlNotificationService.start(bundleContext);
logger.info("Growl Notification Plugin ...[Started]");
}
public void stop(BundleContext bundleContext) throws Exception
{
logger.info("Growl Notification Service ...[Stopped]");
}
}

@ -0,0 +1,344 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.impl.growlnotification;
import java.util.*;
import org.osgi.framework.*;
import com.growl.*;
import net.java.sip.communicator.util.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.service.protocol.event.*;
import java.lang.reflect.*;
/**
* The Growl Notification Service displays on-screen information such as
* messages or call received, etc.
*
* @author Romain Kuntz
*/
public class GrowlNotificationServiceImpl
implements MessageListener,
ServiceListener
{
/**
* The logger for this class.
*/
private static Logger logger =
Logger.getLogger(GrowlNotificationServiceImpl.class);
/**
* The BundleContext that we got from the OSGI bus.
*/
private BundleContext bundleContext = null;
/**
* The Growl notifier
*/
private Growl notifier;
/**
* The noifyGrowlOf method of the growl class. We use reflection to access
* it in order to avoid compilation errors on non mac platforms.
*/
private Method notifyMethod = 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" };
/**
* starts the service. Creates a Growl notifier, and check the current
* registerd 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.");
this.bundleContext = bc;
/* Register to Growl */
try
{
Constructor constructor = Growl.class.getConstructor(new Class[]
{String.class, String.class, String.class});
notifier = (Growl)constructor.newInstance(
new Object[]{"SIP Communicator", allNotif, defaultNotif});
notifier.register();
//init the notifyGrowlOf method
notifyMethod = Growl.class.getMethod(
"notifyGrowlOf"
, new Class[]{String.class, String.class, String.class});
notifyGrowlOf("SIP Communicator Started"
, "Welcome to SIP Communicator"
, "http://www.sip-communicator.org");
}
catch (Exception ex)
{
logger.error("Could not send the message to Growl", ex);
throw ex;
}
/* 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);
}
}
}
/**
* stops the service.
*
* @param bc BundleContext
*/
public void stop(BundleContext bc)
{
// 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);
}
}
}
// ////////////////////////////////////////////////////////////////////////
// MessageListener implementation methods
/**
* Passes the newly received message to growl.
* @param evt MessageReceivedEvent the vent containing the new message.
*/
public void messageReceived(MessageReceivedEvent evt)
{
try
{
notifyGrowlOf("Message Received"
, evt.getSourceContact().getDisplayName()
, evt.getSourceMessage().getContent());
}
catch (Exception ex)
{
logger.error("Could not notify the received message to Growl", ex);
}
}
/**
* Notify growl that a message has been sent.
* @param evt the event containing the message that has just been sent.
*/
public void messageDelivered(MessageDeliveredEvent evt)
{
try
{
notifyGrowlOf("Message Sent"
, "Me"
, evt.getSourceMessage().getContent());
}
catch (Exception ex)
{
logger.error("Could not pass the sent message to Growl", ex);
}
}
/**
* Currently unused
* @param evt ignored
*/
public void messageDeliveryFailed(MessageDeliveryFailedEvent evt)
{
}
// //////////////////////////////////////////////////////////////////////////
/**
* When new protocol provider is registered we check
* does it supports BasicIM 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);
}
}
/**
* Used to attach the Growl Notification Service 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);
try
{
notifyGrowlOf("Protocol events"
, "New Protocol Registered"
, provider.getProtocolName() + " registered");
}
catch (Exception ex)
{
logger.error("Could not notify the message to Growl", ex);
}
}
else
{
logger.trace("Service did not have a 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);
try
{
notifyGrowlOf("Protocol events"
, "Protocol deregistered"
, provider.getProtocolName()
+ " deregistered");
}
catch (Exception ex)
{
logger.error("Could not notify the message to Growl", ex);
}
}
}
/**
* 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 inTitle,
String inDescription)
throws Exception
{
notifyMethod.invoke(
notifier, new Object[]{inNotificationName, inTitle, inDescription});
}
}

@ -0,0 +1,9 @@
Bundle-Activator: net.java.sip.communicator.impl.growlnotification.GrowlNotificationActivator
Bundle-Name: Growl Notification Service Provider
Bundle-Description: A bundle that implements the Growl notification package.
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.protocol,
net.java.sip.communicator.service.protocol.event
Loading…
Cancel
Save