Skip to content

Commit

Permalink
[JENKINS-20609] refactored script hook
Browse files Browse the repository at this point in the history
in preparation of introducing other hooks
  • Loading branch information
kohsuke committed Nov 16, 2013
1 parent df858ab commit f35696b
Show file tree
Hide file tree
Showing 2 changed files with 116 additions and 52 deletions.
57 changes: 5 additions & 52 deletions core/src/main/java/hudson/init/impl/GroovyInitScript.java
Expand Up @@ -23,20 +23,13 @@
*/
package hudson.init.impl;

import groovy.lang.GroovyCodeSource;
import groovy.lang.GroovyShell;
import hudson.init.Initializer;
import jenkins.model.Jenkins;
import jenkins.util.groovy.GroovyHookScript;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.net.URL;
import java.util.Arrays;
import java.util.logging.Logger;

import jenkins.model.Jenkins;
import static hudson.init.InitMilestone.JOB_LOADED;
import hudson.init.Initializer;
import java.util.logging.Level;
import static hudson.init.InitMilestone.*;

/**
* Run the initialization script, if it exists.
Expand All @@ -46,46 +39,6 @@
public class GroovyInitScript {
@Initializer(after=JOB_LOADED)
public static void init(Jenkins j) throws IOException {
URL bundledInitScript = j.servletContext.getResource("/WEB-INF/init.groovy");
if (bundledInitScript!=null) {
LOGGER.info("Executing bundled init script: "+bundledInitScript);
execute(new GroovyCodeSource(bundledInitScript));
}

File initScript = new File(j.getRootDir(),"init.groovy");
if(initScript.exists()) {
execute(initScript);
}

File initScriptD = new File(j.getRootDir(),"init.groovy.d");
if (initScriptD.isDirectory()) {
File[] scripts = initScriptD.listFiles(new FileFilter() {
public boolean accept(File f) {
return f.getName().endsWith(".groovy");
}
});
if (scripts!=null) {
// sort to run them in a deterministic order
Arrays.sort(scripts);
for (File f : scripts)
execute(f);
}
}
new GroovyHookScript("init").run();
}

private static void execute(File initScript) throws IOException {
LOGGER.info("Executing "+initScript);
execute(new GroovyCodeSource(initScript));
}

private static void execute(GroovyCodeSource initScript) {
GroovyShell shell = new GroovyShell(Jenkins.getInstance().getPluginManager().uberClassLoader);
try {
shell.evaluate(initScript);
} catch (RuntimeException x) {
LOGGER.log(Level.WARNING, "Failed to run script " + initScript.getName(), x);
}
}

private static final Logger LOGGER = Logger.getLogger(GroovyInitScript.class.getName());
}
111 changes: 111 additions & 0 deletions core/src/main/java/jenkins/util/groovy/GroovyHookScript.java
@@ -0,0 +1,111 @@
package jenkins.util.groovy;

import groovy.lang.GroovyCodeSource;
import groovy.lang.GroovyShell;
import jenkins.model.Jenkins;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.net.URL;
import java.util.Arrays;
import java.util.Set;
import java.util.TreeSet;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
* A collection of Groovy scripts that are executed as various hooks.
*
* <p>
* For a given hook name, like "init", the following locations are searched for hook scripts,
* and then they are executed in turn.
*
* <ol>
* <li>/WEB-INF/<i>HOOK</i>.groovy in the war file
* <li>/WEB-INF/<i>HOOK</i>.groovy.d/*.groovy in the war file
* <li>$JENKINS_HOME/<i>HOOK</i>.groovy
* <il>$JENKINS_HOME/<i>HOOK</i>.groovy.d/*.groovy
* </ol>
*
* <p>
* Scripts inside <tt>/WEB-INF</tt> is meant for OEM distributions of Jenkins. Files inside
* <tt>$JENKINS_HOME</tt> are for installation local settings. Use of <tt>HOOK.groovy.d</tt>
* allows configuration management tools to control scripts easily.
*
* @author Kohsuke Kawaguchi
*/
public class GroovyHookScript {
private final String hook;

public GroovyHookScript(String hook) {
this.hook = hook;
}

public void run() throws IOException {
Jenkins j = Jenkins.getInstance();
final String hookGroovy = hook+".groovy";
final String hookGroovyD = hook+".groovy.d";

URL bundled = j.servletContext.getResource("/WEB-INF/"+ hookGroovy);
execute(bundled);

Set<String> resources = j.servletContext.getResourcePaths("/WEB-INF/"+ hookGroovyD +"/");
if (resources!=null) {
// sort to execute them in a deterministic order
for (String res : new TreeSet<String>(resources)) {
bundled = j.servletContext.getResource(res);
execute(bundled);
}
}

File script = new File(j.getRootDir(), hookGroovy);
execute(script);

File scriptD = new File(j.getRootDir(), hookGroovyD);
if (scriptD.isDirectory()) {
File[] scripts = scriptD.listFiles(new FileFilter() {
public boolean accept(File f) {
return f.getName().endsWith(".groovy");
}
});
if (scripts!=null) {
// sort to run them in a deterministic order
Arrays.sort(scripts);
for (File f : scripts)
execute(f);
}
}
}

protected void execute(URL bundled) throws IOException {
if (bundled!=null) {
LOGGER.info("Executing bundled script: "+bundled);
execute(new GroovyCodeSource(bundled));
}
}

protected void execute(File f) throws IOException {
if (f.exists()) {
LOGGER.info("Executing "+f);
execute(new GroovyCodeSource(f));
}
}

protected void execute(GroovyCodeSource s) {
try {
createShell().evaluate(s);
} catch (RuntimeException x) {
LOGGER.log(Level.WARNING, "Failed to run script " + s.getName(), x);
}
}

/**
* Can be used to customize the environment in which the script runs.
*/
protected GroovyShell createShell() {
return new GroovyShell(Jenkins.getInstance().getPluginManager().uberClassLoader);
}

private static final Logger LOGGER = Logger.getLogger(GroovyHookScript.class.getName());
}

0 comments on commit f35696b

Please sign in to comment.