package hudson.util;
import hudson.WebAppMain;
import jenkins.util.groovy.GroovyHookScript;
import org.kohsuke.stapler.WebApp;
import javax.annotation.CheckForNull;
import javax.servlet.ServletContext;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Indicates a fatal boot problem, among {@link ErrorObject}
*
* @author Kohsuke Kawaguchi
* @see WebAppMain#recordBootAttempt(File)
*/
public abstract class BootFailure extends ErrorObject {
protected BootFailure() {
}
protected BootFailure(Throwable cause) {
super(cause);
}
/**
* Exposes this failure to UI and invoke the hook.
*
* @param home
* JENKINS_HOME if it's already known.
*/
public void publish(ServletContext context, @CheckForNull File home) {
LOGGER.log(Level.SEVERE, "Failed to initialize Jenkins",this);
WebApp.get(context).setApp(this);
if (home == null) {
return;
}
new GroovyHookScript("boot-failure", context, home, BootFailure.class.getClassLoader())
.bind("exception",this)
.bind("home",home)
.bind("servletContext", context)
.bind("attempts",loadAttempts(home))
.run();
}
/**
* Parses the boot attempt file carefully so as not to cause the entire hook script to fail to execute.
*/
protected List<Date> loadAttempts(File home) {
List<Date> dates = new ArrayList<Date>();
if (home!=null) {
File f = getBootFailureFile(home);
try {
if (f.exists()) {
BufferedReader failureFileReader = new BufferedReader(new FileReader(f));
try {
String line;
while ((line=failureFileReader.readLine())!=null) {
try {
dates.add(new Date(line));
} catch (Exception e) {
// ignore any parse error
}
}
} finally {
failureFileReader.close();
}
}
} catch (IOException e) {
LOGGER.log(Level.WARNING,"Failed to parse "+f,e);
}
}
return dates;
}
private static final Logger LOGGER = Logger.getLogger(BootFailure.class.getName());
/**
* This file captures failed boot attempts.
* Every time we try to boot, we add the timestamp to this file,
* then when we boot, the file gets deleted.
*/
public static File getBootFailureFile(File home) {
return new File(home, "failed-boot-attempts.txt");
}
}