/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.java.sip.communicator.plugin.update; import java.util.*; import java.util.concurrent.*; import net.java.sip.communicator.service.browserlauncher.*; import net.java.sip.communicator.service.gui.*; import net.java.sip.communicator.service.shutdown.*; import net.java.sip.communicator.service.update.*; import net.java.sip.communicator.util.*; import net.java.sip.communicator.util.Logger; import org.jitsi.service.configuration.*; import org.jitsi.util.*; import org.osgi.framework.*; /** * Implements <tt>BundleActivator</tt> for the update plug-in. * * @author Damian Minkov * @author Lyubomir Marinov */ public class UpdateActivator extends AbstractServiceDependentActivator { /** * The <tt>Logger</tt> used by the <tt>UpdateActivator</tt> class and its * instances for logging output. */ private static final Logger logger = Logger.getLogger(UpdateActivator.class); /** * The name of the configuration property which indicates whether the * checking for updates on application startup is enabled. */ private static final String UPDATE_ENABLED = "net.java.sip.communicator.plugin.updatechecker.ENABLED"; /** * The name of the configuration property which indicates whether the * "checking for updates" menu entry is disabled. */ private static final String CHECK_FOR_UPDATES_MENU_DISABLED_PROP = "net.java.sip.communicator.plugin.update.checkforupdatesmenu.DISABLED"; /** * The name of the configuration property which indicates whether the client * should automatically check for updates each day or not. */ private static final String CHECK_FOR_UPDATES_DAILY_ENABLED_PROP = "net.java.sip.communicator.plugin.update.checkforupdatesmenu.daily.ENABLED"; /** * The name of the configuration property which indicates the hour that * the client should check for updates (if daily update checking is enabled) */ private static final String CHECK_FOR_UPDATES_DAILY_TIME_PROP = "net.java.sip.communicator.plugin.update.checkforupdatesmenu.daily.HOUR"; /** * Reference to the <tt>BrowserLauncherService</tt>. */ private static BrowserLauncherService browserLauncher; /** * The <tt>BundleContext</tt> in which the one and only * <tt>UpdateActivator</tt> instance of the update plug-in has been started. */ static BundleContext bundleContext; /** * Reference to the <tt>ConfigurationService</tt>. */ private static ConfigurationService configuration; /** * Reference to the <tt>UIService</tt>. */ private static UIService uiService; /** * The update service. */ private static UpdateService updateService; /** * A scheduler to check for updates once a day */ private ScheduledExecutorService mUpdateExecutor = null; /** * Returns the <tt>BrowserLauncherService</tt> obtained from the bundle * context. * @return the <tt>BrowserLauncherService</tt> obtained from the bundle * context */ static BrowserLauncherService getBrowserLauncher() { if (browserLauncher == null) { browserLauncher = ServiceUtils.getService( bundleContext, BrowserLauncherService.class); } return browserLauncher; } /** * Returns the <tt>ConfigurationService</tt> obtained from the bundle * context. * * @return the <tt>ConfigurationService</tt> obtained from the bundle * context */ static ConfigurationService getConfiguration() { if (configuration == null) { configuration = ServiceUtils.getService( bundleContext, ConfigurationService.class); } return configuration; } /** * Gets a reference to a <code>ShutdownService</code> implementation * currently registered in the bundle context of the active * <code>UpdateCheckActivator</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>UpdateCheckActivator</code> instance */ static ShutdownService getShutdownService() { return ServiceUtils.getService(bundleContext, ShutdownService.class); } /** * Returns a reference to the UIService implementation currently registered * in the bundle context or null if no such implementation was found. * * @return a reference to a UIService implementation currently registered * in the bundle context or null if no such implementation was found. */ static UIService getUIService() { if(uiService == null) uiService = ServiceUtils.getService(bundleContext, UIService.class); return uiService; } /** * The dependent service is available and the bundle will start. * @param dependentService the UIService this activator is waiting. */ @Override public void start(Object dependentService) { if (logger.isDebugEnabled()) logger.debug("Update checker [STARTED]"); ConfigurationService cfg = getConfiguration(); if (OSUtils.IS_WINDOWS) { updateService = new UpdateServiceImpl(); bundleContext.registerService( UpdateService.class.getName(), updateService, null); // Register the "Check for Updates" menu item if // the "Check for Updates" property isn't disabled. if(!cfg.getBoolean(CHECK_FOR_UPDATES_MENU_DISABLED_PROP, false)) { // Register the "Check for Updates" menu item. Hashtable<String, String> toolsMenuFilter = new Hashtable<String, String>(); toolsMenuFilter.put( Container.CONTAINER_ID, Container.CONTAINER_HELP_MENU.getID()); bundleContext.registerService( PluginComponentFactory.class.getName(), new PluginComponentFactory(Container.CONTAINER_HELP_MENU) { @Override protected PluginComponent getPluginInstance() { return new CheckForUpdatesMenuItemComponent( getContainer(), this); } }, toolsMenuFilter); } // Check for software update upon startup if enabled. if(cfg.getBoolean(UPDATE_ENABLED, true)) updateService.checkForUpdates(false); } if (cfg.getBoolean(CHECK_FOR_UPDATES_DAILY_ENABLED_PROP, false)) { logger.info("Scheduled update checking enabled"); // Schedule a "check for updates" task that will run once a day int hoursToWait = calcHoursToWait(); Runnable updateRunnable = new Runnable() { public void run() { logger.debug("Performing scheduled update check"); getUpdateService().checkForUpdates(false); } }; mUpdateExecutor = Executors.newSingleThreadScheduledExecutor(); mUpdateExecutor.scheduleAtFixedRate(updateRunnable, hoursToWait, 24*60*60, TimeUnit.SECONDS); } if (logger.isDebugEnabled()) logger.debug("Update checker [REGISTERED]"); } /** * This activator depends on UIService. * @return the class name of uiService. */ @Override public Class<?> getDependentServiceClass() { return UIService.class; } /** * Setting context to the activator, as soon as we have one. * * @param context the context to set. */ @Override public void setBundleContext(BundleContext context) { bundleContext = context; } /** * Calculate the number of hour to wait until the first scheduled update * check. This will only be called if daily checking for config updates * is enabled * * @return The number of hours to wait */ private int calcHoursToWait() { // The hours to wait is the number of hours until midnight tonight (24 // minus the current hour) plus the hour that the config says updates // should be return 24 - Calendar.getInstance().get(Calendar.HOUR_OF_DAY) + configuration.getInt(CHECK_FOR_UPDATES_DAILY_TIME_PROP, 0); } /** * Stop the bundle. Nothing to stop for now. * @param bundleContext <tt>BundleContext</tt> provided by OSGi framework * @throws Exception if something goes wrong during stop */ public void stop(BundleContext bundleContext) throws Exception { if (logger.isDebugEnabled()) logger.debug("Update checker [STOPPED]"); if (mUpdateExecutor != null) { mUpdateExecutor.shutdown(); mUpdateExecutor = null; } } /** * Returns the update service instance. * * @return the update service instance */ static UpdateService getUpdateService() { return updateService; } }