mirror of https://github.com/sipwise/jitsi.git
Updates sysactivity handling QUERY_ENDSESSION and ENDSESSION events. Adds bundle that listens for the new events to handle clean shutdown.
parent
19d2276dd4
commit
21c7757e23
Binary file not shown.
Binary file not shown.
@ -0,0 +1,224 @@
|
||||
/*
|
||||
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.plugin.windowscleanshutdown;
|
||||
|
||||
import net.java.sip.communicator.service.shutdown.*;
|
||||
import net.java.sip.communicator.service.sysactivity.*;
|
||||
import net.java.sip.communicator.service.sysactivity.event.*;
|
||||
import net.java.sip.communicator.util.*;
|
||||
import org.osgi.framework.*;
|
||||
|
||||
import java.util.concurrent.*;
|
||||
|
||||
/**
|
||||
* Tries to cleanly close the application on shutdown/logoff. The events used
|
||||
* here are only available on windows.
|
||||
*
|
||||
* If the application is still running once end session event is received
|
||||
* and we have give it time (currently 3 sec.) we System.exit() the application.
|
||||
*
|
||||
* @author Emil Ivov
|
||||
*/
|
||||
public class CleanShutdownActivator
|
||||
implements BundleActivator, ServiceListener
|
||||
{
|
||||
private static final Logger logger
|
||||
= Logger.getLogger(CleanShutdownActivator.class);
|
||||
|
||||
/**
|
||||
* Used to wait for stop.
|
||||
*/
|
||||
final CountDownLatch synchShutdown = new CountDownLatch(1);
|
||||
|
||||
/**
|
||||
* Our context.
|
||||
*/
|
||||
private BundleContext context;
|
||||
|
||||
/**
|
||||
* The system activity service.
|
||||
*/
|
||||
SystemActivityNotificationsService sysActivityService = null;
|
||||
|
||||
/**
|
||||
* Bundle activator start method.
|
||||
*
|
||||
* @throws Exception If this method throws an exception
|
||||
* (which won't happen).
|
||||
*/
|
||||
public void start(final BundleContext context)
|
||||
throws Exception
|
||||
{
|
||||
this.context = context;
|
||||
|
||||
logger.info("Starting the CleanShutdown service.");
|
||||
|
||||
handleNewSystemActivityNotificationsService(
|
||||
getSystemActivityNotificationsService(context));
|
||||
|
||||
// if missing will wait for it
|
||||
if(sysActivityService == null)
|
||||
context.addServiceListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when this bundle is stopped so the Framework can perform the
|
||||
* bundle-specific activities necessary to stop the bundle.
|
||||
*
|
||||
* @param context The execution context of the bundle being stopped.
|
||||
* @throws Exception If this method throws an exception, the bundle is
|
||||
* still marked as stopped, and the Framework will remove the bundle's
|
||||
* listeners, unregister all services registered by the bundle, and
|
||||
* release all services used by the bundle.
|
||||
*/
|
||||
public void stop(BundleContext context)
|
||||
throws Exception
|
||||
{
|
||||
// stop received.
|
||||
synchShutdown.countDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a reference to a <code>ShutdownService</code> implementation
|
||||
* currently registered in the bundle context of the active
|
||||
* <code>OsDependentActivator</code> instance.
|
||||
* <p>
|
||||
* The returned reference to <code>ShutdownService</code> is not being
|
||||
* cached.
|
||||
* </p>
|
||||
*
|
||||
* @return reference to a <code>ShutdownService</code> implementation
|
||||
* currently registered in the bundle context of the active
|
||||
* <code>OsDependentActivator</code> instance
|
||||
*/
|
||||
private ShutdownService getShutdownService()
|
||||
{
|
||||
return(ShutdownService)context.getService(
|
||||
context.getServiceReference(ShutdownService.class.getName()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a reference to a <code>SystemActivityNotificationsService</code>
|
||||
* implementation currently registered in the bundle context.
|
||||
* <p>
|
||||
* The returned reference to <code>SystemActivityNotificationsService</code>
|
||||
* is not being cached.
|
||||
* </p>
|
||||
*
|
||||
* @param context the bundle context.
|
||||
* @return reference to a <code>SystemActivityNotificationsService</code>
|
||||
* implementation currently registered in the bundle context.
|
||||
*/
|
||||
public static SystemActivityNotificationsService
|
||||
getSystemActivityNotificationsService(BundleContext context)
|
||||
{
|
||||
ServiceReference ref =
|
||||
context.getServiceReference(
|
||||
SystemActivityNotificationsService.class.getName());
|
||||
|
||||
if(ref == null)
|
||||
return null;
|
||||
else
|
||||
return
|
||||
(SystemActivityNotificationsService)
|
||||
context.getService(ref);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Saves the reference for the service and
|
||||
* add a listener if the desired events are supported. Or start
|
||||
* the checking thread otherwise.
|
||||
* @param newService the service
|
||||
*/
|
||||
private void handleNewSystemActivityNotificationsService
|
||||
(SystemActivityNotificationsService newService)
|
||||
{
|
||||
sysActivityService = newService;
|
||||
|
||||
if(newService != null)
|
||||
newService.addSystemActivityChangeListener(
|
||||
new SystemActivityChangeListener()
|
||||
{
|
||||
public void activityChanged(SystemActivityEvent event)
|
||||
{
|
||||
if(event.getEventID()
|
||||
== SystemActivityEvent.EVENT_QUERY_ENDSESSION)
|
||||
{
|
||||
// instruct the shutdown timeout to
|
||||
// wait only 3 secs.
|
||||
System.setProperty(
|
||||
"org.jitsi.shutdown.SHUTDOWN_TIMEOUT",
|
||||
"3000");
|
||||
|
||||
getShutdownService().beginShutdown();
|
||||
|
||||
// just wait a moment, or till we are stopped
|
||||
try
|
||||
{
|
||||
synchronized(this)
|
||||
{
|
||||
synchShutdown.await(1500,
|
||||
TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
catch(Throwable t)
|
||||
{}
|
||||
}
|
||||
else if(event.getEventID()
|
||||
== SystemActivityEvent.EVENT_ENDSESSION)
|
||||
{
|
||||
try
|
||||
{
|
||||
// wait till we are stopped or forced stopped
|
||||
synchShutdown.await();
|
||||
}
|
||||
catch(Throwable t)
|
||||
{}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* When new SystemActivityNotificationsService
|
||||
* is registered we add needed listeners.
|
||||
*
|
||||
* @param serviceEvent ServiceEvent
|
||||
*/
|
||||
public void serviceChanged(ServiceEvent serviceEvent)
|
||||
{
|
||||
ServiceReference serviceRef = serviceEvent.getServiceReference();
|
||||
|
||||
// if the event is caused by a bundle being stopped, we don't want to
|
||||
// know we are shutting down
|
||||
if (serviceRef.getBundle().getState() == Bundle.STOPPING)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Object sService = context
|
||||
.getService(serviceRef);
|
||||
|
||||
if(sService instanceof SystemActivityNotificationsService)
|
||||
{
|
||||
switch (serviceEvent.getType())
|
||||
{
|
||||
case ServiceEvent.REGISTERED:
|
||||
handleNewSystemActivityNotificationsService(
|
||||
(SystemActivityNotificationsService)sService);
|
||||
break;
|
||||
case ServiceEvent.UNREGISTERING:
|
||||
//((SystemActivityNotificationsService)sService)
|
||||
// .removeSystemActivityChangeListener(this);
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
Bundle-Activator: net.java.sip.communicator.plugin.windowscleanshutdown.CleanShutdownActivator
|
||||
Bundle-Name: CleanShutdownBundle
|
||||
Bundle-Description: A bundle that makes sure that when closed Jitsi will exit cleanly.
|
||||
Bundle-Vendor: jitsi.org
|
||||
Bundle-Version: 0.0.1
|
||||
System-Bundle: yes
|
||||
Import-Package: org.osgi.framework,
|
||||
org.jitsi.service.configuration,
|
||||
net.java.sip.communicator.service.shutdown,
|
||||
net.java.sip.communicator.service.sysactivity,
|
||||
net.java.sip.communicator.service.sysactivity.event,
|
||||
net.java.sip.communicator.util
|
||||
Loading…
Reference in new issue