<commit_before>
/* 
 * Copyright (c) 2011 Stiftung Deutsches Elektronen-Synchroton, 
 * Member of the Helmholtz Association, (DESY), HAMBURG, GERMANY.
 *
 * THIS SOFTWARE IS PROVIDED UNDER THIS LICENSE ON AN "../AS IS" BASIS. 
 * WITHOUT WARRANTY OF ANY KIND, EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED 
 * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR PARTICULAR PURPOSE AND 
 * NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE 
 * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 
 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. SHOULD THE SOFTWARE PROVE DEFECTIVE 
 * IN ANY RESPECT, THE USER ASSUMES THE COST OF ANY NECESSARY SERVICING, REPAIR OR 
 * CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. 
 * NO USE OF ANY SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
 * DESY HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, 
 * OR MODIFICATIONS.
 * THE FULL LICENSE SPECIFYING FOR THE SOFTWARE THE REDISTRIBUTION, MODIFICATION, 
 * USAGE AND OTHER RIGHTS AND OBLIGATIONS IS INCLUDED WITH THE DISTRIBUTION OF THIS 
 * PROJECT IN THE FILE LICENSE.HTML. IF THE LICENSE IS NOT INCLUDED YOU MAY FIND A COPY 
 * AT HTTP://WWW.DESY.DE/LEGAL/LICENSE.HTM
 */

package org.csstudio.ams.application.deliverysystem;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Hashtable;
import org.csstudio.ams.AmsActivator;
import org.csstudio.ams.application.deliverysystem.internal.DeliverySystemPreference;
import org.csstudio.ams.application.deliverysystem.management.ListWorker;
import org.csstudio.ams.application.deliverysystem.management.Restart;
import org.csstudio.ams.application.deliverysystem.management.RestartWorker;
import org.csstudio.ams.application.deliverysystem.management.Stop;
import org.csstudio.ams.application.deliverysystem.management.StopWorker;
import org.csstudio.ams.application.deliverysystem.util.CommonMailer;
import org.csstudio.ams.application.deliverysystem.util.Environment;
import org.csstudio.ams.delivery.AbstractDeliveryWorker;
import org.csstudio.ams.internal.AmsPreferenceKey;
import org.csstudio.utility.jms.sharedconnection.SharedJmsConnections;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.preferences.IPreferencesService;
import org.eclipse.equinox.app.IApplication;
import org.eclipse.equinox.app.IApplicationContext;
import org.remotercp.common.tracker.IGenericServiceListener;
import org.remotercp.service.connection.session.ISessionService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * This class controls all aspects of the application's execution
 */
public class DeliverySystemApplication implements IApplication,
                                                  RemotelyManageable,
                                                  IGenericServiceListener<ISessionService> {
    
    private static Logger LOG = LoggerFactory.getLogger(DeliverySystemApplication.class);
	
    // 6 minutes
    private final static long WORKER_WATCH_INTERVAL = 360000L;
    
    /** The ECF service */
    private ISessionService xmppService;

    private Hashtable<AbstractDeliveryWorker, Thread> deliveryWorker;
    
    private long workerStopTimeout;
    
    private Object lock;
    
    private boolean running;
    
    private boolean restart;
    
    public DeliverySystemApplication() {
        deliveryWorker = new Hashtable<AbstractDeliveryWorker, Thread>();
        workerStopTimeout = DeliverySystemPreference.WORKER_STOP_TIMEOUT.getValue();
        LOG.info("Timeout for worker shutdown: {}", workerStopTimeout);
        lock = new Object();
        running = true;
        restart = false;
    }
    
    /**
	 * @see org.eclipse.equinox.app.IApplication#start(org.eclipse.equinox.app.IApplicationContext)
	 */
	@Override
    public Object start(IApplicationContext context) throws Exception {
		
	    Activator.getPlugin().addSessionServiceListener(this);
	    
	    IPreferencesService prefs = Platform.getPreferencesService();
	    
	    // FIRST read the JMS preferences and prepare the SharedJmsConnection class
        String url1 = prefs.getString(AmsActivator.PLUGIN_ID,
                                      AmsPreferenceKey.P_JMS_AMS_PROVIDER_URL_1,
                                      "tcp://localhost:62616",
                                      null);
        String url2 = prefs.getString(AmsActivator.PLUGIN_ID,
                                      AmsPreferenceKey.P_JMS_AMS_PROVIDER_URL_2,
                                      "tcp://localhost:64616",
                                      null);
        LOG.debug("JMS Consumer URL 1: {}", url1);
        LOG.debug("JMS Consumer URL 2: {}", url2);
        SharedJmsConnections.staticInjectConsumerUrlAndClientId(url1, url2, "AmsDeliverySystemConsumer");
        
        url1 = prefs.getString(AmsActivator.PLUGIN_ID,
                               AmsPreferenceKey.P_JMS_AMS_SENDER_PROVIDER_URL,
                               "tcp://localhost:62616",
                               null);
        LOG.debug("JMS Publisher URL: {}", url1);
        SharedJmsConnections.staticInjectPublisherUrlAndClientId(url1, "AmsDeliverySystemPublisher");

        running = startDeliveryWorker();
	    
        context.applicationRunning();
        LOG.info("Initialization finished. Start working.");
        
        while (running) {
            
            synchronized (lock) {
                try {
                    lock.wait(WORKER_WATCH_INTERVAL);
                } catch (InterruptedException ie) {
                    LOG.warn("Application was interrupted.");
                }
            }
            
            boolean restartWorker = false;
            String badWorker = "";
            if (running) {
                
                // Check all delivery worker
                Enumeration<AbstractDeliveryWorker> worker = deliveryWorker.keys();
                while (worker.hasMoreElements()) {
                    AbstractDeliveryWorker w = worker.nextElement();
                    if (!w.isWorking()) {
                        badWorker = w.getWorkerName();
                        LOG.warn("{} seemed not to be working.", badWorker);
                        restartWorker = true;<commit_msg>o.c.ams.application.deliverysystem: Added check of the XMPP connection.<commit_after>
/* 
 * Copyright (c) 2011 Stiftung Deutsches Elektronen-Synchroton, 
 * Member of the Helmholtz Association, (DESY), HAMBURG, GERMANY.
 *
 * THIS SOFTWARE IS PROVIDED UNDER THIS LICENSE ON AN "../AS IS" BASIS. 
 * WITHOUT WARRANTY OF ANY KIND, EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED 
 * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR PARTICULAR PURPOSE AND 
 * NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE 
 * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 
 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. SHOULD THE SOFTWARE PROVE DEFECTIVE 
 * IN ANY RESPECT, THE USER ASSUMES THE COST OF ANY NECESSARY SERVICING, REPAIR OR 
 * CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. 
 * NO USE OF ANY SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
 * DESY HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, 
 * OR MODIFICATIONS.
 * THE FULL LICENSE SPECIFYING FOR THE SOFTWARE THE REDISTRIBUTION, MODIFICATION, 
 * USAGE AND OTHER RIGHTS AND OBLIGATIONS IS INCLUDED WITH THE DISTRIBUTION OF THIS 
 * PROJECT IN THE FILE LICENSE.HTML. IF THE LICENSE IS NOT INCLUDED YOU MAY FIND A COPY 
 * AT HTTP://WWW.DESY.DE/LEGAL/LICENSE.HTM
 */

package org.csstudio.ams.application.deliverysystem;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Hashtable;
import org.csstudio.ams.AmsActivator;
import org.csstudio.ams.application.deliverysystem.internal.DeliverySystemPreference;
import org.csstudio.ams.application.deliverysystem.management.ListWorker;
import org.csstudio.ams.application.deliverysystem.management.Restart;
import org.csstudio.ams.application.deliverysystem.management.RestartWorker;
import org.csstudio.ams.application.deliverysystem.management.Stop;
import org.csstudio.ams.application.deliverysystem.management.StopWorker;
import org.csstudio.ams.application.deliverysystem.util.CommonMailer;
import org.csstudio.ams.application.deliverysystem.util.Environment;
import org.csstudio.ams.delivery.AbstractDeliveryWorker;
import org.csstudio.ams.internal.AmsPreferenceKey;
import org.csstudio.utility.jms.sharedconnection.SharedJmsConnections;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.preferences.IPreferencesService;
import org.eclipse.ecf.core.identity.ID;
import org.eclipse.equinox.app.IApplication;
import org.eclipse.equinox.app.IApplicationContext;
import org.remotercp.common.tracker.IGenericServiceListener;
import org.remotercp.service.connection.session.ISessionService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * This class controls all aspects of the application's execution
 */
public class DeliverySystemApplication implements IApplication,
                                                  RemotelyManageable,
                                                  IGenericServiceListener<ISessionService> {
    
    private static Logger LOG = LoggerFactory.getLogger(DeliverySystemApplication.class);
	
    // 6 minutes
    private final static long WORKER_WATCH_INTERVAL = 360000L;
    
    /** The ECF service */
    private ISessionService xmppService;

    private Hashtable<AbstractDeliveryWorker, Thread> deliveryWorker;
    
    private long workerStopTimeout;
    
    private Object lock;
    
    private boolean running;
    
    private boolean restart;
    
    public DeliverySystemApplication() {
        deliveryWorker = new Hashtable<AbstractDeliveryWorker, Thread>();
        workerStopTimeout = DeliverySystemPreference.WORKER_STOP_TIMEOUT.getValue();
        LOG.info("Timeout for worker shutdown: {}", workerStopTimeout);
        lock = new Object();
        running = true;
        restart = false;
    }
    
    /**
	 * @see org.eclipse.equinox.app.IApplication#start(org.eclipse.equinox.app.IApplicationContext)
	 */
	@Override
    public Object start(IApplicationContext context) throws Exception {
		
	    Activator.getPlugin().addSessionServiceListener(this);
	    
	    IPreferencesService prefs = Platform.getPreferencesService();
	    
	    // FIRST read the JMS preferences and prepare the SharedJmsConnection class
        String url1 = prefs.getString(AmsActivator.PLUGIN_ID,
                                      AmsPreferenceKey.P_JMS_AMS_PROVIDER_URL_1,
                                      "tcp://localhost:62616",
                                      null);
        String url2 = prefs.getString(AmsActivator.PLUGIN_ID,
                                      AmsPreferenceKey.P_JMS_AMS_PROVIDER_URL_2,
                                      "tcp://localhost:64616",
                                      null);
        LOG.debug("JMS Consumer URL 1: {}", url1);
        LOG.debug("JMS Consumer URL 2: {}", url2);
        SharedJmsConnections.staticInjectConsumerUrlAndClientId(url1, url2, "AmsDeliverySystemConsumer");
        
        url1 = prefs.getString(AmsActivator.PLUGIN_ID,
                               AmsPreferenceKey.P_JMS_AMS_SENDER_PROVIDER_URL,
                               "tcp://localhost:62616",
                               null);
        LOG.debug("JMS Publisher URL: {}", url1);
        SharedJmsConnections.staticInjectPublisherUrlAndClientId(url1, "AmsDeliverySystemPublisher");

        running = startDeliveryWorker();
	    
        context.applicationRunning();
        LOG.info("Initialization finished. Start working.");
        
        while (running) {
            
            synchronized (lock) {
                try {
                    lock.wait(WORKER_WATCH_INTERVAL);
                } catch (InterruptedException ie) {
                    LOG.warn("Application was interrupted.");
                }
            }
            
            // Check XMPP connection
            ID connectedId = xmppService.getConnectedID();
            if (connectedId != null) {
                LOG.debug("XMPP connection is working.");
            } else {
                LOG.warn("XMPP connection is broken! Try to re-connect.");
                Activator.getPlugin().addSessionServiceListener(this);
            }
            
            boolean restartWorker = false;
            String badWorker = "";
            if (running) {
                
                // Check all delivery worker
                Enumeration<AbstractDeliveryWorker> worker = deliveryWorker.keys();
                while (worker.hasMoreElements()) {
                    AbstractDeliveryWorker w = worker.nextElement();
                    if (!w.isWorking()) {
                        badWorker = w.getWorkerName();
                        LOG.warn("{} seemed not to be working.", badWorker);
                        restartWorker = true;
{'fraction_non_alphanumeric': 0.07872060756535709, 'fraction_numerical': 0.005988023952095809, 'mean_word_length': 2.5935450013119916, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 20, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5223476', 'n_tokens_mistral': 3838, 'n_tokens_neox': 3602, 'n_words': 887}