diff --git a/src/main/java/org/jenkinsci/plugins/scripttrigger/groovy/GroovyScriptTrigger.java b/src/main/java/org/jenkinsci/plugins/scripttrigger/groovy/GroovyScriptTrigger.java index 0ccec79..0bc5f55 100644 --- a/src/main/java/org/jenkinsci/plugins/scripttrigger/groovy/GroovyScriptTrigger.java +++ b/src/main/java/org/jenkinsci/plugins/scripttrigger/groovy/GroovyScriptTrigger.java @@ -112,6 +112,8 @@ protected String getDefaultMessageCause() { @Override protected Action[] getScheduledActions(Node pollingNode, final XTriggerLog log) throws ScriptTriggerException { + Action[] fileParametersActions = new Action[0]; + Action[] cronTabParametersActions = new Action[0]; if (propertiesFilePath != null) { try { @@ -127,7 +129,7 @@ protected Action[] getScheduledActions(Node pollingNode, final XTriggerLog log) if (rootPath == null) { throw new ScriptTriggerException("The node is offline."); } - return rootPath.act(new FilePath.FileCallable() { + fileParametersActions = rootPath.act(new FilePath.FileCallable() { public Action[] invoke(File f, VirtualChannel channel) throws IOException, InterruptedException { File propFile = new File(propertiesFilePath); @@ -141,23 +143,7 @@ public Action[] invoke(File f, VirtualChannel channel) throws IOException, Inter properties.load(fis); fis.close(); - assert job != null : "job must not be null if this was 'started'"; - ParametersDefinitionProperty paramDefProp = (ParametersDefinitionProperty) ((Job) job) - .getProperty(ParametersDefinitionProperty.class); - List parameterValueList = new ArrayList(); - - /* Scan for all parameter with an associated default values */ - for (ParameterDefinition paramDefinition : paramDefProp.getParameterDefinitions()) { - ParameterValue defaultValue = paramDefinition.getDefaultParameterValue(); - - if (properties.containsKey(paramDefinition.getName())) { - ParameterizedStaplerRequest request = new ParameterizedStaplerRequest( - String.valueOf(properties.get(paramDefinition.getName()))); - parameterValueList.add(paramDefinition.createValue(request)); - } else if (defaultValue != null) - parameterValueList.add(defaultValue); - } - return new Action[]{new ParametersAction(parameterValueList)}; + return getParametersActions(properties); } }); } catch (IOException ioe) { @@ -166,6 +152,30 @@ public Action[] invoke(File f, VirtualChannel channel) throws IOException, Inter throw new ScriptTriggerException(ie); } } + + Properties cronTabParameters = new Properties(); + try { + cronTabParameters.putAll( + new ParameterParser().findParameters(getSpec(), new GregorianCalendar())); + } catch (ANTLRException e) { + throw new ScriptTriggerException(e); + } + + if (! cronTabParameters.isEmpty()) { + cronTabParametersActions = getParametersActions(cronTabParameters); + } + + if (fileParametersActions.length > 0 && cronTabParametersActions.length > 0) { + ParametersAction fileParametersAction = (ParametersAction) fileParametersActions[0]; + ParametersAction cronTabParametersAction = (ParametersAction) cronTabParametersActions[0]; + // Cron Tab parameters overrides File parameters. + return new Action[]{fileParametersAction.merge(cronTabParametersAction)}; + } else if (fileParametersActions.length > 0) { + return fileParametersActions; + } else if (cronTabParametersActions.length > 0) { + return cronTabParametersActions; + } + return new Action[0]; } @@ -175,6 +185,10 @@ protected boolean checkIfModified(Node pollingNode, XTriggerLog log) throws Scri SecurityContextHolder.getContext().setAuthentication(ACL.SYSTEM); try { + Properties parameters = + new ParameterParser().findParameters(getSpec(), new GregorianCalendar()); + log.info("[debug] Parameters: " + parameters); + GroovyScriptTriggerExecutor executor = getGroovyScriptTriggerExecutor(log); final AbstractProject proj = (AbstractProject) job; @@ -187,25 +201,46 @@ protected boolean checkIfModified(Node pollingNode, XTriggerLog log) throws Scri } if (groovyExpression != null) { - boolean evaluationSucceed = executor.evaluateGroovyScript(pollingNode, proj, getGroovyExpression(), envVars, groovySystemScript); + boolean evaluationSucceed = executor.evaluateGroovyScript(pollingNode, proj, getGroovyExpression(), envVars, parameters, groovySystemScript); if (evaluationSucceed) { return true; } } if (groovyFilePath != null) { - boolean evaluationSucceed = executor.evaluateGroovyScriptFilePath(pollingNode, proj, Util.replaceMacro(groovyFilePath, envVars), envVars, groovySystemScript); + boolean evaluationSucceed = executor.evaluateGroovyScriptFilePath(pollingNode, proj, Util.replaceMacro(groovyFilePath, envVars), envVars, parameters, groovySystemScript); if (evaluationSucceed) { return true; } } return false; + } catch (ANTLRException e) { + throw new ScriptTriggerException(e); } finally { SecurityContextHolder.getContext().setAuthentication(existingAuth); } } + protected Action[] getParametersActions(Properties properties) { + assert job != null : "job must not be null if this was 'started'"; + ParametersDefinitionProperty paramDefProp = (ParametersDefinitionProperty) ((Job) job) + .getProperty(ParametersDefinitionProperty.class); + List parameterValueList = new ArrayList(); + /* Scan for all parameter with an associated default values */ + for (ParameterDefinition paramDefinition : paramDefProp.getParameterDefinitions()) { + ParameterValue defaultValue = paramDefinition.getDefaultParameterValue(); + + if (properties.containsKey(paramDefinition.getName())) { + ParameterizedStaplerRequest request = new ParameterizedStaplerRequest( + String.valueOf(properties.get(paramDefinition.getName()))); + parameterValueList.add(paramDefinition.createValue(request)); + } else if (defaultValue != null) + parameterValueList.add(defaultValue); + } + return new Action[]{new ParametersAction(parameterValueList)}; + } + private GroovyScriptTriggerExecutor getGroovyScriptTriggerExecutor(XTriggerLog log) throws ScriptTriggerException { return new GroovyScriptTriggerExecutor(log); } diff --git a/src/main/java/org/jenkinsci/plugins/scripttrigger/groovy/GroovyScriptTriggerExecutor.java b/src/main/java/org/jenkinsci/plugins/scripttrigger/groovy/GroovyScriptTriggerExecutor.java index 84c0776..4e4ea62 100644 --- a/src/main/java/org/jenkinsci/plugins/scripttrigger/groovy/GroovyScriptTriggerExecutor.java +++ b/src/main/java/org/jenkinsci/plugins/scripttrigger/groovy/GroovyScriptTriggerExecutor.java @@ -38,6 +38,7 @@ import java.io.FileInputStream; import java.io.IOException; import java.util.Map; +import java.util.Properties; /** * @author Gregory Boissinot @@ -48,7 +49,7 @@ public GroovyScriptTriggerExecutor(XTriggerLog log) { super(log); } - public boolean evaluateGroovyScript(Node executingNode, final AbstractProject proj, final String scriptContent, final Map envVars, boolean groovySystemScript) throws ScriptTriggerException { + public boolean evaluateGroovyScript(Node executingNode, final AbstractProject proj, final String scriptContent, final Map envVars, final Properties parameters, boolean groovySystemScript) throws ScriptTriggerException { if (scriptContent == null) { throw new NullPointerException("The script content object must be set."); @@ -56,13 +57,13 @@ public boolean evaluateGroovyScript(Node executingNode, final AbstractProject pr try { if (groovySystemScript) { log.info("Running as system script"); - return evaluateGroovyScript(proj, scriptContent, envVars); + return evaluateGroovyScript(proj, scriptContent, envVars, parameters); } return executingNode.getRootPath().act(new Callable() { public Boolean call() throws ScriptTriggerException { log.info("Running as node script"); - return evaluateGroovyScript(null, scriptContent, envVars); + return evaluateGroovyScript(null, scriptContent, envVars, parameters); } }); } catch (IOException ioe) { @@ -80,7 +81,7 @@ public Boolean call() throws ScriptTriggerException { } } - private boolean evaluateGroovyScript(final AbstractProject proj, final String scriptContent, final Map envVars) { + private boolean evaluateGroovyScript(final AbstractProject proj, final String scriptContent, final Map envVars, final Properties parameters) { if (envVars != null) { final StringBuilder envDebug = new StringBuilder("Replacing script vars using:"); for (final Map.Entry envEntry : envVars.entrySet()) { @@ -108,6 +109,7 @@ private boolean evaluateGroovyScript(final AbstractProject proj, final String sc shell.setVariable("log", log); shell.setVariable("out", log.getListener().getLogger()); + shell.setVariable("parameters", parameters); if (proj != null) { shell.setVariable("project", proj); } @@ -148,7 +150,7 @@ protected ClassLoader getClassLoader() { return cl; } - public boolean evaluateGroovyScriptFilePath(Node executingNode, AbstractProject proj, String scriptFilePath, Map envVars, boolean groovySystemScript) throws ScriptTriggerException { + public boolean evaluateGroovyScriptFilePath(Node executingNode, AbstractProject proj, String scriptFilePath, Map envVars, final Properties parameters, boolean groovySystemScript) throws ScriptTriggerException { if (scriptFilePath == null) { throw new NullPointerException("The scriptFilePath object must be set."); @@ -189,7 +191,7 @@ public boolean evaluateGroovyScriptFilePath(Node executingNode, AbstractProject scriptContent = getStringContent(executingNode, scriptFilePath); } - return evaluateGroovyScript(executingNode, proj, scriptContent, envVars, groovySystemScript); + return evaluateGroovyScript(executingNode, proj, scriptContent, envVars, parameters, groovySystemScript); } } diff --git a/src/main/java/org/jenkinsci/plugins/scripttrigger/groovy/ParameterParser.java b/src/main/java/org/jenkinsci/plugins/scripttrigger/groovy/ParameterParser.java new file mode 100644 index 0000000..cdd2b27 --- /dev/null +++ b/src/main/java/org/jenkinsci/plugins/scripttrigger/groovy/ParameterParser.java @@ -0,0 +1,48 @@ +package org.jenkinsci.plugins.scripttrigger.groovy; + +import antlr.ANTLRException; +import hudson.scheduler.CronTabList; +import org.apache.commons.lang.StringUtils; + +import java.util.Calendar; +import java.util.Properties; + +public class ParameterParser { + + private static final String PARAMETER_ANNOTATION = "@param"; + + public Properties findParameters(String cronTabSpec, Calendar calendar) throws ANTLRException { + Properties parameters = new Properties(); + for (String line : cronTabSpec.split(System.lineSeparator())) { + if (line.length() == 0) { + continue; + } + if (line.startsWith("#")) { + if (line.substring(1).startsWith(PARAMETER_ANNOTATION)) { + parameters.putAll(parseParameters(line.substring(1 + PARAMETER_ANNOTATION.length()))); + } + } else { + if (CronTabList.create(line).check(calendar)) { + break; + } + parameters.clear(); + } + } + return parameters; + } + + private Properties parseParameters(String parameterStr) { + Properties parameters = new Properties(); + if (StringUtils.isBlank(parameterStr)) { + return parameters; + } + parameterStr = parameterStr.trim(); + int separatorInd = parameterStr.indexOf(' '); + if (separatorInd < 0) { + parameters.setProperty(parameterStr, ""); + } else { + parameters.setProperty(parameterStr.substring(0, separatorInd), parameterStr.substring(separatorInd).trim()); + } + return parameters; + } +} diff --git a/src/main/resources/org/jenkinsci/plugins/scripttrigger/groovy/GroovyScriptTrigger/help-groovyExpression.html b/src/main/resources/org/jenkinsci/plugins/scripttrigger/groovy/GroovyScriptTrigger/help-groovyExpression.html index b2b4591..64757a3 100644 --- a/src/main/resources/org/jenkinsci/plugins/scripttrigger/groovy/GroovyScriptTrigger/help-groovyExpression.html +++ b/src/main/resources/org/jenkinsci/plugins/scripttrigger/groovy/GroovyScriptTrigger/help-groovyExpression.html @@ -9,4 +9,19 @@ f.exists()

+

+ Scheduler field supports parameters in format:
+ #@param <name> [value]
+
+ Parameters are applied to a cron item above which they are listed.
+ These parameters values override ones of default job parameters.
+ No quotes are needed in case a parameter value contains whitespaces.
+ A parameter value may be omitted. In this case it will be assumed as an empty one. +

+

+ Predefined variables: +

+
+
parameters
Parameters defined in Scheduler.
+
diff --git a/src/main/resources/org/jenkinsci/plugins/scripttrigger/groovy/GroovyScriptTrigger/help-groovyFilePath.html b/src/main/resources/org/jenkinsci/plugins/scripttrigger/groovy/GroovyScriptTrigger/help-groovyFilePath.html index 4fdde54..a5bff61 100644 --- a/src/main/resources/org/jenkinsci/plugins/scripttrigger/groovy/GroovyScriptTrigger/help-groovyFilePath.html +++ b/src/main/resources/org/jenkinsci/plugins/scripttrigger/groovy/GroovyScriptTrigger/help-groovyFilePath.html @@ -2,4 +2,19 @@

Give a groovy script path.

+

+ Scheduler field supports parameters in format:
+ #@param <name> [value]
+
+ Parameters are applied to a cron item above which they are listed.
+ These parameters values override ones of default job parameters.
+ No quotes are needed in case a parameter value contains whitespaces.
+ A parameter value may be omitted. In this case it will be assumed as an empty one. +

+

+ Predefined variables: +

+
+
parameters
Parameters defined in Scheduler.
+