Skip to content

Commit f9a76ec

Browse files
committed
initial commit, first successfull scheduled parameterized run with schedule:
7 * * * * % env=seven 8 * * * * % env=eight
1 parent e5b2015 commit f9a76ec

16 files changed

Lines changed: 1188 additions & 0 deletions

File tree

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
.classpath
2+
.settings
3+
.project
4+
target
5+
deleteme
6+
work

pom.xml

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
2+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
3+
<modelVersion>4.0.0</modelVersion>
4+
<parent>
5+
<groupId>org.jenkins-ci.plugins</groupId>
6+
<artifactId>plugin</artifactId>
7+
<version>1.509.4</version><!-- which version of Jenkins is this plugin
8+
built against? -->
9+
</parent>
10+
11+
<groupId>org.jenkins-ci.plugins</groupId>
12+
<artifactId>parameterized-scheduler</artifactId>
13+
<version>1.0-SNAPSHOT</version>
14+
<packaging>hpi</packaging>
15+
16+
<!-- get every artifact through repo.jenkins-ci.org, which proxies all the
17+
artifacts that we need -->
18+
<repositories>
19+
<repository>
20+
<id>repo.jenkins-ci.org</id>
21+
<url>http://repo.jenkins-ci.org/public/</url>
22+
</repository>
23+
</repositories>
24+
25+
<pluginRepositories>
26+
<pluginRepository>
27+
<id>repo.jenkins-ci.org</id>
28+
<url>http://repo.jenkins-ci.org/public/</url>
29+
</pluginRepository>
30+
</pluginRepositories>
31+
<build>
32+
<plugins>
33+
<plugin>
34+
<groupId>org.apache.maven.plugins</groupId>
35+
<artifactId>maven-compiler-plugin</artifactId>
36+
<version>3.1</version>
37+
<configuration>
38+
<source>1.6</source>
39+
<target>1.6</target>
40+
</configuration>
41+
</plugin>
42+
</plugins>
43+
</build>
44+
</project>
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package org.jenkinsci.plugins.parameterizedschedular;
2+
3+
import hudson.Extension;
4+
import hudson.model.PeriodicWork;
5+
import hudson.model.AbstractProject;
6+
import hudson.triggers.Trigger;
7+
8+
import java.util.Calendar;
9+
import java.util.GregorianCalendar;
10+
import java.util.concurrent.TimeUnit;
11+
import java.util.logging.Level;
12+
import java.util.logging.Logger;
13+
14+
import jenkins.model.Jenkins;
15+
16+
@Extension
17+
public class Cron extends PeriodicWork {
18+
private static final Logger LOGGER = Logger.getLogger(Cron.class.getName());
19+
20+
@Override
21+
public long getRecurrencePeriod() {
22+
long period = TimeUnit.MINUTES.toMillis(1);
23+
LOGGER.warning("period set to " + period);
24+
return period;
25+
}
26+
27+
@Override
28+
protected void doRun() throws Exception {
29+
LOGGER.warning("dorun-run");
30+
checkTriggers(new GregorianCalendar());
31+
}
32+
33+
private void checkTriggers(Calendar calendar) {
34+
Jenkins instance = Jenkins.getInstance();
35+
36+
for (AbstractProject<?, ?> project : instance.getAllItems(AbstractProject.class)) {
37+
for (Trigger<?> trigger : project.getTriggers().values()) {
38+
if (trigger instanceof ParameterizedTimerTrigger) {
39+
LOGGER.fine("cron checking " + project.getName());
40+
ParameterizedTimerTrigger ptTrigger = (ParameterizedTimerTrigger) trigger;
41+
42+
try {
43+
ptTrigger.checkCronTabsAndRun(calendar);
44+
} catch (Throwable e) {
45+
// t.run() is a plugin, and some of them throw RuntimeException and other things.
46+
// don't let that cancel the polling activity. report and move on.
47+
LOGGER.log(Level.WARNING,
48+
trigger.getClass().getName() + ".run() failed for " + project.getName(), e);
49+
}
50+
}
51+
}
52+
}
53+
}
54+
55+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package org.jenkinsci.plugins.parameterizedschedular;
2+
3+
import java.lang.reflect.Field;
4+
5+
public class FieldAccessor {
6+
7+
public static Object access(Object instance, String fieldName) {
8+
9+
try {
10+
Field field = instance.getClass().getDeclaredField(fieldName);
11+
boolean isAccessible = field.isAccessible();
12+
field.setAccessible(true);
13+
Object value = field.get(instance);
14+
field.setAccessible(isAccessible);
15+
return value;
16+
} catch (Exception e) {
17+
e.printStackTrace();
18+
}
19+
return null;
20+
}
21+
22+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package org.jenkinsci.plugins.parameterizedschedular;
2+
3+
import java.util.Map;
4+
5+
import com.google.common.collect.Maps;
6+
7+
public class ParameterParser {
8+
9+
public Map<String, String> parse(String formattedString) {
10+
Map<String, String> result = Maps.newHashMap();
11+
if (formattedString == null) {
12+
return result;
13+
}
14+
String[] parameters = formattedString.split(";");
15+
for (String parameter : parameters) {
16+
String[] keyvalue = parameter.split("=");
17+
if (keyvalue.length == 2) {
18+
result.put(keyvalue[0].trim(), keyvalue[1].trim());
19+
}
20+
}
21+
22+
return result;
23+
}
24+
}
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
package org.jenkinsci.plugins.parameterizedschedular;
2+
3+
import static java.util.Calendar.DAY_OF_MONTH;
4+
import static java.util.Calendar.HOUR_OF_DAY;
5+
import static java.util.Calendar.MINUTE;
6+
import static java.util.Calendar.MONTH;
7+
import hudson.scheduler.CronTab;
8+
import hudson.scheduler.Hash;
9+
10+
import java.lang.reflect.Method;
11+
import java.util.Calendar;
12+
import java.util.HashMap;
13+
import java.util.Map;
14+
15+
import com.google.common.collect.Maps;
16+
17+
import antlr.ANTLRException;
18+
19+
/**
20+
* this is a copy of {@link CronTab} with added parameters map support
21+
*
22+
* @author jameswilson
23+
*/
24+
public class ParameterizedCronTab {
25+
26+
private final Map<String, String> parameterValues;
27+
// private final CronTab cronTab;
28+
private long[] bits;
29+
private Integer dayOfWeek;
30+
31+
public ParameterizedCronTab(CronTab cronTab, Map<String, String> parameters) {
32+
// this.cronTab = cronTab;
33+
bits = (long[])FieldAccessor.access(cronTab, "bits");
34+
dayOfWeek = (Integer)FieldAccessor.access(cronTab, "dayOfWeek");
35+
36+
parameterValues = parameters;
37+
}
38+
39+
/**
40+
* @param hash
41+
* Used to spread out token like "@daily". Null to preserve the legacy behaviour
42+
* of not spreading it out at all.
43+
*/
44+
public static ParameterizedCronTab create(String line, int lineNumber, Hash hash) throws ANTLRException {
45+
String[] lineParts = line.split("%");
46+
CronTab cronTab = new CronTab(lineParts[0].trim(), lineNumber, hash);
47+
Map<String, String> parameters = Maps.newHashMap();
48+
if (lineParts.length == 2) {
49+
parameters = new ParameterParser().parse(lineParts[1]);
50+
}
51+
return new ParameterizedCronTab(cronTab, parameters);
52+
}
53+
54+
public Map<String, String> getParameterValues() {
55+
return parameterValues;
56+
}
57+
58+
/**
59+
* Returns true if n-th bit is on.
60+
*/
61+
private boolean checkBits(long bitMask, int n) {
62+
return (bitMask|(1L<<n))==bitMask;
63+
}
64+
65+
public boolean check(Calendar calendar) {
66+
if(!checkBits(bits[0],calendar.get(MINUTE)))
67+
return false;
68+
if(!checkBits(bits[1],calendar.get(HOUR_OF_DAY)))
69+
return false;
70+
if(!checkBits(bits[2],calendar.get(DAY_OF_MONTH)))
71+
return false;
72+
if(!checkBits(bits[3],calendar.get(MONTH)+1))
73+
return false;
74+
if(!checkBits(dayOfWeek,calendar.get(Calendar.DAY_OF_WEEK)-1))
75+
return false;
76+
77+
return true;
78+
79+
// Object result;
80+
// try {
81+
// Method method = CronTab.class.getMethod("check", Calendar.class);
82+
// result = method.invoke(cronTab, calendar);
83+
// } catch (Exception e) {
84+
// e.printStackTrace();
85+
// return false;
86+
// }
87+
// return (Boolean) result;
88+
// return cronTab.check(calendar);
89+
}
90+
91+
public String checkSanity() {
92+
// for( int i=0; i<5; i++ ) {
93+
// long bitMask = (i<4)?bits[i]:(long)dayOfWeek;
94+
// for( int j=BaseParser.LOWER_BOUNDS[i]; j<=BaseParser.UPPER_BOUNDS[i]; j++ ) {
95+
// if(!checkBits(bitMask,j)) {
96+
// // this rank has a sparse entry.
97+
// // if we have a sparse rank, one of them better be the left-most.
98+
// if(i>0)
99+
// return Messages.CronTab_do_you_really_mean_every_minute_when_you(spec, "0 " + spec.substring(spec.indexOf(' ')+1));
100+
// // once we find a sparse rank, upper ranks don't matter
101+
// return null;
102+
// }
103+
// }
104+
// }
105+
106+
return null;
107+
}
108+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package org.jenkinsci.plugins.parameterizedschedular;
2+
3+
import hudson.scheduler.CronTabList;
4+
import hudson.scheduler.Hash;
5+
import hudson.scheduler.Messages;
6+
7+
import java.util.ArrayList;
8+
import java.util.Calendar;
9+
import java.util.List;
10+
11+
import antlr.ANTLRException;
12+
13+
/**
14+
* mostly a copy of {@link CronTabList}
15+
*
16+
* @author jameswilson
17+
*
18+
*/
19+
public class ParameterizedCronTabList {
20+
21+
private final List<ParameterizedCronTab> cronTabs;
22+
23+
public ParameterizedCronTabList(List<ParameterizedCronTab> cronTabs) {
24+
this.cronTabs = cronTabs;
25+
}
26+
27+
public static ParameterizedCronTabList create(String cronTabSpecification) throws ANTLRException {
28+
return create(cronTabSpecification, null);
29+
}
30+
31+
public static ParameterizedCronTabList create(String cronTabSpecification, Hash hash) throws ANTLRException {
32+
List<ParameterizedCronTab> result = new ArrayList<ParameterizedCronTab>();
33+
int lineNumber = 0;
34+
for (String line : cronTabSpecification.split("\\r?\\n")) {
35+
lineNumber++;
36+
line = line.trim();
37+
if (line.length() == 0 || line.startsWith("#"))
38+
continue; // ignorable line
39+
try {
40+
result.add(ParameterizedCronTab.create(line, lineNumber, hash));
41+
} catch (ANTLRException e) {
42+
throw new ANTLRException(Messages.CronTabList_InvalidInput(line, e.toString()), e);
43+
}
44+
}
45+
return new ParameterizedCronTabList(result);
46+
}
47+
48+
public ParameterizedCronTab check(Calendar calendar) {
49+
for (ParameterizedCronTab tab : cronTabs) {
50+
if (tab.check(calendar))
51+
return tab;
52+
}
53+
return null;
54+
}
55+
56+
public String checkSanity() {
57+
for (ParameterizedCronTab tab : cronTabs) {
58+
String s = tab.checkSanity();
59+
if (s != null)
60+
return s;
61+
}
62+
return null;
63+
}
64+
}

0 commit comments

Comments
 (0)