Skip to content
Permalink
Browse files
[JENKINS-20972] Exception when updating a generated job
  • Loading branch information
syl20bnr committed Dec 11, 2013
1 parent 2f84fb0 commit 6d63adae1203e7e5d9e348686f71c5ec7a700164
Showing 1 changed file with 48 additions and 117 deletions.
@@ -31,6 +31,7 @@ of this software and associated documentation files (the "Software"), to deal
import hudson.model.Result;
import hudson.model.TopLevelItem;
import hudson.model.AbstractBuild;
import hudson.model.AbstractItem;
import hudson.model.AbstractProject;
import hudson.model.Cause;
import hudson.model.ParametersAction;
@@ -50,6 +51,7 @@ of this software and associated documentation files (the "Software"), to deal
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
@@ -62,8 +64,9 @@ of this software and associated documentation files (the "Software"), to deal
import java.util.Properties;
import java.util.Set;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;

import jenkins.model.Jenkins;

@@ -99,10 +102,6 @@ public class GeneratorRun extends Build<JobGenerator, GeneratorRun> {
'>', '|'};
private List<DownstreamGenerator> downstreamGenerators =
new ArrayList<DownstreamGenerator>();
private enum ReplaceType{
NORMAL, SPECIAL_CHARS, REG_EXP;
}
private static final ReplaceType[] replaceTypes = ReplaceType.values();

private class DownstreamGenerator{
private final AbstractProject job;
@@ -132,87 +131,42 @@ public JobGenerator getJobGenerator() {

public static String expand(String s, List<ParametersAction> params) {
// check existenz of variables to replace
boolean proceed = false;
for (ParametersAction p : params) {
List<ParameterValue> values = p.getParameters();
ParameterValue value = null;
ReplaceType replType = ReplaceType.NORMAL;
for (ParameterValue v : values) {
String decorated = "${" + v.getName() + "}";
if (s.contains(decorated)) {
value = v;
break;
}
decorated = "${" + v.getName() + "*}";
if (s.contains(decorated)) {
replType = ReplaceType.SPECIAL_CHARS;
value = v;
break;
}
Pattern pattern = Pattern.compile(
".*?\\$\\{" + v.getName() + "/(.*?)/(.*?)\\}.*");
Matcher matcher = pattern.matcher(s);
if (matcher.find()) {
replType = ReplaceType.REG_EXP;
value = v;
proceed = true;
break;
}
}
if (value != null){
s = GeneratorRun.expand(
s, value.getName(),
((GeneratorKeyValueParameterValue) value).value,
replType);
// replace nested variables
s = expand(s, params);
}
if (proceed){
for (ParametersAction p : params) {
List<ParameterValue> values = p.getParameters();
for (ParameterValue v : values) {
s = GeneratorRun.expand(s, v.getName(),
((GeneratorKeyValueParameterValue) v).value);
}
}
// replace nested variables
s = expand(s, params);
}
return s;
}

private static String expand(String s, String n, String v, ReplaceType r){
if(r == ReplaceType.NORMAL) {
String decorated = "${" + n + "}";
while (s.contains(decorated)) {
s = s.replace(decorated, v);
}
}
else if(r == ReplaceType.SPECIAL_CHARS) {
for(char c: GeneratorRun.specialChars){
v = v.replace(c, '_');
}
String decorated = "${" + n + "*}";
while (s.contains(decorated)) {
s = s.replace(decorated, v);
}
}
else if (r == ReplaceType.REG_EXP){
// fetch regexps and expression to replace in s
Pattern pattern = Pattern.compile(
".*?\\$\\{" + n + "/(.+?)/(.*?)\\}.*");
Matcher regexps = pattern.matcher(s);
if (regexps.find()){
pattern = Pattern.compile(
".*?(\\$\\{" + n + "/.*?/.*?\\}).*");
Matcher toReplace = pattern.matcher(s);
if (toReplace.find()) {
// apply regexp replacement to value v
pattern = Pattern.compile(regexps.group(1));
Matcher vmatcher = pattern.matcher(v);
if (vmatcher.find()) {
v = vmatcher.replaceAll(regexps.group(2));
}
// finally replace the whole expression by the new value
s = s.replace(toReplace.group(1), v);
}
}
private static String expand(String s, String n, String v){
String decorated = "${" + n + "}";
while (s.contains(decorated)) {
s = s.replace(decorated, v);
}
return s;
}

public static String getExpandedJobName(JobGenerator p,
List<ParametersAction> params){
String n = expand(p.getGeneratedJobName(), params);
// force replacement of special characters
for(char c: GeneratorRun.specialChars){
n = n.replace(c, '_');
}
@@ -243,7 +197,6 @@ public static boolean isEvaluationSupported(Element root){
// expression for a given conditional class
List<String> notSupportedClasses = new ArrayList<String>();
notSupportedClasses.add("AlwaysRun");
notSupportedClasses.add("BooleanCondition");
notSupportedClasses.add("NeverRun");
notSupportedClasses.add("CauseCondition");
notSupportedClasses.add("StatusCondition");
@@ -331,8 +284,7 @@ protected Result doRun(BuildListener listener) throws Exception {
}
}
// Expand Vars
Visitor v = new ExpandVarsVisitor(
params, downstreamGenerators, job.getDisableJobs());
Visitor v = new ExpandVarsVisitor(params, downstreamGenerators);
doc.accept(v);
// Remove info specific to Job Generator
v = new GatherElementsToRemoveVisitor();
@@ -412,19 +364,21 @@ protected Result doRun(BuildListener listener) throws Exception {
InputStream is = new ByteArrayInputStream(
doc.asXML().getBytes("UTF-8"));
// System.out.println(doc.asXML());
boolean created =
Jenkins.getInstance().getItem(expName) == null;
if(created){
LOGGER.info(String.format("Created job %s", expName));
}
else{
AbstractItem item =
(AbstractItem) Jenkins.getInstance().getItem(expName);
if(item != null){
StreamSource ss = new StreamSource(is);
item.updateByXml((Source)ss);
LOGGER.info(String.format("Updated configuration of " +
"job %s", expName));
}
Jenkins.getInstance().createProjectFromXML(expName, is);
else{
Jenkins.getInstance().createProjectFromXML(expName, is);
LOGGER.info(String.format("Created job %s", expName));
}
// save generated job name
GeneratedJobBuildAction action =
new GeneratedJobBuildAction(expName, created);
new GeneratedJobBuildAction(expName, item!=null);
getBuild().addAction(action);
}
return Result.SUCCESS;
@@ -481,12 +435,10 @@ private void gatherDownstreamGenerators(BuildListener listener)
bp.getAction(GeneratorRun.this, listener));
}
}
if (JobGenerator.class.isInstance(p)){
job.copyOptions((JobGenerator) p);
downstreamGenerators.add(
new DownstreamGenerator(p, importParams));
processedProjects.add(p);
}
job.copyOptions((JobGenerator) p);
downstreamGenerators.add(
new DownstreamGenerator(p, importParams));
processedProjects.add(p);
}
}
}
@@ -512,15 +464,13 @@ private void gatherDownstreamGenerators(BuildListener listener)
// standard Jenkins dependencies
for(AbstractProject dp: job.getDownstreamProjects()){
if(!processedProjects.contains(dp)){
if (JobGenerator.class.isInstance(dp)){
job.copyOptions((JobGenerator) dp);
List<List<ParametersAction>> importParams =
new ArrayList<List<ParametersAction>>();
importParams.add(new ArrayList<ParametersAction>());
importParams.get(0).addAll(lpa);
downstreamGenerators.add(
new DownstreamGenerator(dp, importParams));
}
job.copyOptions((JobGenerator) dp);
List<List<ParametersAction>> importParams =
new ArrayList<List<ParametersAction>>();
importParams.add(new ArrayList<ParametersAction>());
importParams.get(0).addAll(lpa);
downstreamGenerators.add(
new DownstreamGenerator(dp, importParams));
}
}
}
@@ -572,11 +522,9 @@ private void gatherDownstreamGeneratorsFromTriggerBuilder(
importIndex += 1;
}
}
if (JobGenerator.class.isInstance(p)){
job.copyOptions((JobGenerator) p);
downstreamGenerators.add(
new DownstreamGenerator(p, importParams));
}
job.copyOptions((JobGenerator) p);
downstreamGenerators.add(
new DownstreamGenerator(p, importParams));
}
}
}
@@ -750,16 +698,13 @@ else if(job.getName().equals(expName)){

class ExpandVarsVisitor extends VisitorSupport {
private final List<ParametersAction> params;
private final boolean disableJob;
private List<DownstreamGenerator> downGenerators;

public ExpandVarsVisitor(
List<ParametersAction> params,
List<DownstreamGenerator> downGenerators,
boolean disableJob){
List<DownstreamGenerator> downGenerators){
this.params = params;
this.downGenerators = downGenerators;
this.disableJob = disableJob;
}

@Override
@@ -769,15 +714,6 @@ public void visit(Element node) {
// force trigger without any parameter
node.setText("true");
}
else if(n.equals("disabled") &&
node.getParent().getName().equals("project")){
if(this.disableJob){
node.setText("true");
}
else{
node.setText("false");
}
}
}

@Override
@@ -797,13 +733,8 @@ private String updateProjectReference(Text node){
if(result.length() > 0){
result += ",";
}
if (JobGenerator.class.isInstance(dg.job)){
result += GeneratorRun.getExpandedJobName(
result += GeneratorRun.getExpandedJobName(
(JobGenerator)dg.job, lpa);
}
else {
result += dg.job.getName();
}
}
dg.processed = true;
break;

0 comments on commit 6d63ada

Please sign in to comment.