/* * Copyright (c) 2013 Hudson. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Hudson - initial API and implementation and/or initial documentation */ package hudson.lifecycle; import hudson.FilePath; import hudson.model.Hudson; import java.io.BufferedReader; import java.io.File; import java.io.FileFilter; import java.io.IOException; import java.io.InputStreamReader; import java.io.Reader; import java.util.ArrayList; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import static java.util.logging.Level.INFO; import static java.util.logging.Level.WARNING; import java.util.logging.Logger; /** * Allow restart by means of a <code>--restartCommand</code> command line option * or a <code>hudson-restart[.extension]</code> file in <code>HUDSON_HOME</code>. * @author Bob Foster */ public class RestartCommandLifecycle extends Lifecycle { private static final Logger LOGGER = Logger.getLogger(RestartCommandLifecycle.class.getName()); private static final String HUDSON_RESTART_SCRIPT_NAME = "hudson-restart"; private static final String HUDSON_RESTART_COMMAND_KEY = "hudson.restart"; private static String restartCommand = null; private static File restartScript = null; private static String getExtension(String name) { int ext = name.lastIndexOf('.'); if (ext > 0) { return name.substring(ext); } return ""; } private static class RestartFilter implements FileFilter { @Override public boolean accept(File pathname) { String name = pathname.getName(); String extension = getExtension(name); return HUDSON_RESTART_SCRIPT_NAME.equals(name.substring(0, name.length()-extension.length())); } } private static boolean checkReturn() { String hl = System.getProperty("hudson.lifecycle"); if (hl != null) { LOGGER.log(WARNING, "hudson.lifecycle specified, "+(restartCommand != null ? HUDSON_RESTART_COMMAND_KEY : HUDSON_RESTART_SCRIPT_NAME+" script")+" ignored"); return false; } return true; } public static boolean isConfigured() { String p = System.getProperty(HUDSON_RESTART_COMMAND_KEY); if (p != null) { restartCommand = p; return checkReturn(); } else { File home = Hudson.getInstance().getRootDir(); File[] restartScripts = home.listFiles(new RestartFilter()); int numScripts = restartScripts.length; if (numScripts == 0) { return false; } restartScript = restartScripts[0]; if (numScripts > 1) { LOGGER.log(WARNING, "More than one "+HUDSON_RESTART_SCRIPT_NAME+" script, using " + restartScript.getName()); } return checkReturn(); } } public void restart() throws IOException, InterruptedException { // Keep it simple // Try to avoid broken pipe exception by not opening any streams String cmd = restartCommand; if (cmd == null) { cmd = restartScript.getCanonicalPath(); } LOGGER.log(INFO, "Executing restart command: "+cmd); ProcessBuilder pb = new ProcessBuilder(cmd); Process process = pb.start(); int ret = process.waitFor(); if (ret != 0) { throw new IOException("Restart command '"+restartCommand+"' failed with return code "+ret); } } /** * Can the {@link #restart()} method restart Hudson? * * @throws RestartNotSupportedException If the restart is not supported, * throw this exception and explain the cause. */ public void verifyRestartable() throws RestartNotSupportedException { } /** * The same as {@link #verifyRestartable()} except the status is indicated * by the return value, not by an exception. */ public boolean canRestart() { return true; } }