package org.ovirt.engine.core.notifier;

import java.net.InetAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

import javax.mail.internet.InternetAddress;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.ovirt.engine.core.notifier.utils.NotificationProperties;

import sun.misc.Signal;
import sun.misc.SignalHandler;

/**
 * Main class of event notification service. Initiate the service and handles termination signals
 */
@SuppressWarnings("restriction")
public class Notifier {

    private static final Logger log = Logger.getLogger(Notifier.class);
    private static ScheduledExecutorService notifyScheduler = Executors.newSingleThreadScheduledExecutor();
    private static ScheduledExecutorService monitorScheduler = Executors.newSingleThreadScheduledExecutor();

    /**
     * @param args
     *            [0] configuration file absolute path
     */
    public static void main(String[] args) {
        NotifierSignalHandler handler = new NotifierSignalHandler();
        Signal.handle(new Signal("HUP"), handler);
        handler.addScheduledExecutorService(notifyScheduler);
        handler.addScheduledExecutorService(monitorScheduler);

        NotificationService notificationService = null;
        EngineMonitorService engineMonitorService = null;
        try {
            NotificationProperties prop = NotificationProperties.getInstance();

            for (String property : new String[] {
                NotificationProperties.DAYS_TO_KEEP_HISTORY,
                NotificationProperties.ENGINE_INTERVAL_IN_SECONDS,
                NotificationProperties.ENGINE_TIMEOUT_IN_SECONDS,
                NotificationProperties.INTERVAL_IN_SECONDS,
                NotificationProperties.IS_HTTPS_PROTOCOL,
                NotificationProperties.MAIL_PORT,
                NotificationProperties.MAIL_SERVER,
                NotificationProperties.REPEAT_NON_RESPONSIVE_NOTIFICATION,
            }) {
                if (StringUtils.isEmpty(prop.getProperty(property))) {
                    throw new IllegalArgumentException(
                        String.format(
                            "Check configuration file, '%s' is missing",
                            property
                        )
                    );
                }
            }

            InetAddress.getAllByName(prop.getProperty(NotificationProperties.MAIL_SERVER));

            for (String property : new String[] {
                NotificationProperties.MAIL_USER,
                NotificationProperties.MAIL_FROM,
                NotificationProperties.MAIL_REPLY_TO,
            }) {
                String candidate = prop.getProperty(property);
                if (!StringUtils.isEmpty(candidate)) {
                    try {
                        new InternetAddress(candidate);
                    }
                    catch(Exception e) {
                        throw new IllegalArgumentException(
                            String.format(
                                "Check configuration file, invalid format in '%s'",
                                property
                            ),
                            e
                        );
                    }
                }
            }

            notificationService = new NotificationService(prop);
            engineMonitorService = new EngineMonitorService(prop);

            // add notification service to scheduler with its configurable interval
            handler.addServiceHandler(notifyScheduler.scheduleWithFixedDelay(notificationService,
                    1,
                    prop.getLong(NotificationProperties.INTERVAL_IN_SECONDS),
                    TimeUnit.SECONDS));

            // add engine monitor service to scheduler with its configurable interval
            handler.addServiceHandler(monitorScheduler.scheduleWithFixedDelay(engineMonitorService,
                    1,
                    prop.getLong(NotificationProperties.ENGINE_INTERVAL_IN_SECONDS),
                    TimeUnit.SECONDS));
        } catch (Exception e) {
            log.error("Failed to run the event notification service. ", e);
            if (notifyScheduler != null) {
                notifyScheduler.shutdown();
            }
            if (monitorScheduler != null) {
                monitorScheduler.shutdown();
            }
            // flag exit code to calling script after threads shut down.
            System.exit(1);
        }
    }

    /**
     * Class designed to handle a proper shutdown in case of an external signal which was registered was caught by the
     * program.
     */
    public static class NotifierSignalHandler implements SignalHandler {

        private List<ScheduledFuture<?>> serviceHandler = new ArrayList<ScheduledFuture<?>>();
        private List<ScheduledExecutorService> scheduler = new ArrayList<ScheduledExecutorService>();

        public void handle(Signal sig) {
            log.info("Preparing for shutdown after receiving signal " + sig);
            if (serviceHandler.size() > 0) {
                for (ScheduledFuture<?> scheduled : serviceHandler) {
                    scheduled.cancel(true);
                }
            }
            if (scheduler.size() > 0) {
                for (ScheduledExecutorService executer : scheduler) {
                    executer.shutdown();
                }
            }
            log.info("Event Notification service was shutdown");
            System.exit(0);
        }

        public void addScheduledExecutorService(ScheduledExecutorService scheduler) {
            this.scheduler.add(scheduler);
        }

        public void addServiceHandler(ScheduledFuture<?> serviceHandler) {
            this.serviceHandler.add(serviceHandler);
        }
    }
}


@@ -63,16 +63,76 @@
 ddress;%0A
+import java.net.MalformedURLException;%0Aimport java.net.URL;%0A
 import j
@@ -394,16 +394,68 @@
 Address;
+%0Aimport javax.xml.parsers.FactoryConfigurationError;
 %0A%0Aimport
@@ -519,18 +519,99 @@
 og4j.Log
-ge
+Manager;%0Aimport org.apache.log4j.Logger;%0Aimport org.apache.log4j.xml.DOMConfigurato
 r;%0Aimpor
@@ -1180,24 +1180,587 @@
 xecutor();%0A%0A
+    /**%0A     * Initializes logging configuration%0A     */%0A    private static void initLogging() %7B%0A        String cfgFile = System.getProperty(%22log4j.configuration%22);%0A        if (StringUtils.isNotBlank(cfgFile)) %7B%0A            try %7B%0A                URL url = new URL(cfgFile);%0A                LogManager.resetConfiguration();%0A                DOMConfigurator.configure(url);%0A            %7D catch (FactoryConfigurationError %7C MalformedURLException ex) %7B%0A                System.out.println(%22Cannot configure logging: %22 + ex.getMessage());%0A            %7D%0A        %7D%0A    %7D%0A%0A
     /**%0A    
@@ -1878,24 +1878,47 @@
 g%5B%5D args) %7B%0A
+        initLogging();%0A
         Noti

Fix ovirt-engine-notifier logging config