package hudson.model;

import hudson.security.ACL;
import hudson.util.StreamTaskListener;
import jenkins.model.Jenkins;
import org.acegisecurity.context.SecurityContext;
import org.acegisecurity.context.SecurityContextHolder;

import java.io.File;
import java.io.IOException;
import java.util.logging.Level;

/**
 * {@link PeriodicWork} that takes a long time to run.
 *
 * <p>
 * Subclasses will implement the {@link #execute(TaskListener)} method and can carry out a long-running task.
 * This runs in a separate thread so as not to block the timer thread, and this class handles
 * all those details.
 *
 * @author Kohsuke Kawaguchi
 */
public abstract class AsyncPeriodicWork extends PeriodicWork {
    /**
     * Human readable name of the work.
     */
    public final String name;

    private Thread thread;

    protected AsyncPeriodicWork(String name) {
        this.name = name;
    }

    /**
     * Schedules this periodic work now in a new thread, if one isn't already running.
     */
    public final void doRun() {
        try {
            if(thread!=null && thread.isAlive()) {
                logger.log(this.getNormalLoggingLevel(), name+" thread is still running. Execution aborted.");
                return;
            }
            thread = new Thread(new Runnable() {
                public void run() {
                    logger.log(getNormalLoggingLevel(), "Started "+name);
                    long startTime = System.currentTimeMillis();

                    StreamTaskListener l = createListener();
                    try {
                        ACL.impersonate(ACL.SYSTEM);

                        execute(l);
                    } catch (IOException e) {
                        e.printStackTrace(l.fatalError(e.getMessage()));
                    } catch (InterruptedException e) {
                        e.printStackTrace(l.fatalError("aborted"));
                    } finally {
                        l.closeQuietly();
                    }

                    logger.log(getNormalLoggingLevel(), "Finished "+name+". "+
                        (System.currentTimeMillis()-startTime)+" ms");
                }
            },name+" thread");
            thread.start();
        } catch (Throwable t) {
            logger.log(this.getErrorLoggingLevel(), name+" thread failed with error", t);
        }
    }

    protected StreamTaskListener createListener() {
        try {
            return new StreamTaskListener(getLogFile());
        } catch (IOException e) {
            throw new Error(e);
        }
    }

    /**
     * Determines the log file that records the result of this task.
     */
    protected File getLogFile() {
        return new File(Jenkins.getInstance().getRootDir(),name+".log");
    }
    
    /**
     * Returns the logging level at which normal messages are displayed.
     * 
     * @return 
     *      The logging level as @Level.
     *
     * @since 1.551
     */
    protected Level getNormalLoggingLevel() {
        return Level.INFO;
    }
    
    /**
     * Returns the logging level at which error messages are displayed.
     * 
     * @return 
     *      The logging level as @Level.
     *
     * @since 1.551
     */
    protected Level getErrorLoggingLevel() {
        return Level.SEVERE;
    }
    
    /**
     * Executes the task.
     *
     * @param listener
     *      Output sent will be reported to the users. (this work is TBD.)
     * @throws InterruptedException
     *      The caller will record the exception and moves on.
     * @throws IOException
     *      The caller will record the exception and moves on.
     */
    protected abstract void execute(TaskListener listener) throws IOException, InterruptedException;
}

@@ -300,16 +300,52 @@
 g.Level;
+%0Aimport java.util.logging.LogRecord;
 %0A%0A/**%0A *
@@ -1162,22 +1162,20 @@
 this.get
-Normal
+Slow
 LoggingL
@@ -1174,38 +1174,36 @@
 LoggingLevel(), 
-name+%22
+%22%7B0%7D
  thread is still
@@ -1231,16 +1231,22 @@
 borted.%22
+, name
 );%0A     
@@ -1428,18 +1428,22 @@
 Started 
-%22+
+%7B0%7D%22, 
 name);%0A 
@@ -2093,21 +2093,31 @@
 hed 
-%22+name+%22. %22+%0A
+%7B0%7D. %7B1,number%7D ms%22,%0A  
     
@@ -2135,16 +2135,37 @@
         
+   new Object%5B%5D%7Bname,
  (System
@@ -2199,14 +2199,9 @@
 ime)
-+%22 ms%22
+%7D
 );%0A 
@@ -2316,34 +2316,52 @@
             
-logger.log
+LogRecord lr = new LogRecord
 (this.getErr
@@ -2378,22 +2378,20 @@
 evel(), 
-name+%22
+%22%7B0%7D
  thread 
@@ -2412,11 +2412,115 @@
 ror%22
-, t
+);%0A            lr.setThrown(t);%0A            lr.setParameters(new Object%5B%5D%7Bname%7D);%0A            logger.log(lr
 );%0A 
@@ -3201,32 +3201,324 @@
 NFO;%0A    %7D%0A    %0A
+    /**%0A     * Returns the logging level at which previous task still executing messages is displayed.%0A     *%0A     * @return%0A     *      The logging level as @Level.%0A     *%0A     * @since 1.565%0A     */%0A    protected Level getSlowLoggingLevel() %7B%0A        return getNormalLoggingLevel();%0A    %7D%0A%0A
     /**%0A     * R

Use logging API correctly and introduce the ability to differentiate between the logging level for task execution taking too long