-
\ No newline at end of file
diff --git a/core/src/main/resources/lib/form/rowSet.jelly b/core/src/main/resources/lib/form/rowSet.jelly
index 6276b0aa84..0f7b21b399 100644
--- a/core/src/main/resources/lib/form/rowSet.jelly
+++ b/core/src/main/resources/lib/form/rowSet.jelly
@@ -42,16 +42,9 @@ THE SOFTWARE.
-
-
-
-
-
+
-
-
+
\ No newline at end of file
diff --git a/core/src/main/resources/lib/layout/layout.jelly b/core/src/main/resources/lib/layout/layout.jelly
index e992673215..9d332b23a3 100644
--- a/core/src/main/resources/lib/layout/layout.jelly
+++ b/core/src/main/resources/lib/layout/layout.jelly
@@ -209,6 +209,17 @@ THE SOFTWARE.
diff --git a/maven-plugin/src/main/java/hudson/maven/MavenBuild.java b/maven-plugin/src/main/java/hudson/maven/MavenBuild.java
index 24df91fefa..a0c9ede834 100644
--- a/maven-plugin/src/main/java/hudson/maven/MavenBuild.java
+++ b/maven-plugin/src/main/java/hudson/maven/MavenBuild.java
@@ -473,7 +473,7 @@ public class MavenBuild extends AbstractBuild {
buildEnvironments.add(e);
}
- EnvVars envVars = getEnvironment(); // buildEnvironments should be set up first
+ EnvVars envVars = getEnvironment(listener); // buildEnvironments should be set up first
ProcessCache.MavenProcess process = mavenProcessCache.get(launcher.getChannel(), listener,
new MavenProcessFactory(getParent().getParent(),launcher,envVars,null));
diff --git a/maven-plugin/src/main/java/hudson/maven/MavenModuleSetBuild.java b/maven-plugin/src/main/java/hudson/maven/MavenModuleSetBuild.java
index 13ed0aca14..6b476a7403 100644
--- a/maven-plugin/src/main/java/hudson/maven/MavenModuleSetBuild.java
+++ b/maven-plugin/src/main/java/hudson/maven/MavenModuleSetBuild.java
@@ -311,7 +311,7 @@ public final class MavenModuleSetBuild extends AbstractBuild poms;
try {
diff --git a/maven-plugin/src/main/java/hudson/maven/MavenProcessFactory.java b/maven-plugin/src/main/java/hudson/maven/MavenProcessFactory.java
index a0eadcbd08..178e52393e 100644
--- a/maven-plugin/src/main/java/hudson/maven/MavenProcessFactory.java
+++ b/maven-plugin/src/main/java/hudson/maven/MavenProcessFactory.java
@@ -62,6 +62,7 @@ import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.util.Arrays;
+import java.util.jar.JarFile;
import java.util.logging.Logger;
@@ -228,7 +229,7 @@ final class MavenProcessFactory implements ProcessCache.Factory {
* UGLY.
*/
private ArgumentListBuilder buildMavenCmdLine(BuildListener listener,int tcpPort) throws IOException, InterruptedException {
- MavenInstallation mvn = getMavenInstallation();
+ MavenInstallation mvn = getMavenInstallation(listener);
if(mvn==null) {
listener.error("Maven version is not configured for this project. Can't determine which Maven to run");
throw new RunnerAbortedException();
@@ -247,7 +248,7 @@ final class MavenProcessFactory implements ProcessCache.Factory {
slaveRoot = getCurrentNode().getRootPath();
ArgumentListBuilder args = new ArgumentListBuilder();
- JDK jdk = getJava();
+ JDK jdk = getJava(listener);
if(jdk==null) {
args.add("java");
} else {
@@ -290,16 +291,16 @@ final class MavenProcessFactory implements ProcessCache.Factory {
return envVars.expand(mms.getMavenOpts());
}
- public MavenInstallation getMavenInstallation() {
+ public MavenInstallation getMavenInstallation(TaskListener log) throws IOException, InterruptedException {
MavenInstallation mi = mms.getMaven();
- if (mi != null) mi = mi.forNode(getCurrentNode()).forEnvironment(envVars);
+ if (mi != null) mi = mi.forNode(getCurrentNode(), log).forEnvironment(envVars);
return mi;
}
- public JDK getJava() {
+ public JDK getJava(TaskListener log) throws IOException, InterruptedException {
JDK jdk = mms.getJDK();
- if (jdk != null) jdk = jdk.forNode(getCurrentNode()).forEnvironment(envVars);
+ if (jdk != null) jdk = jdk.forNode(getCurrentNode(), log).forEnvironment(envVars);
return jdk;
}
diff --git a/maven-plugin/src/main/java/hudson/maven/ProcessCache.java b/maven-plugin/src/main/java/hudson/maven/ProcessCache.java
index 44f1090592..64f3cf1b00 100644
--- a/maven-plugin/src/main/java/hudson/maven/ProcessCache.java
+++ b/maven-plugin/src/main/java/hudson/maven/ProcessCache.java
@@ -26,6 +26,7 @@ package hudson.maven;
import hudson.Util;
import hudson.model.BuildListener;
import hudson.model.JDK;
+import hudson.model.TaskListener;
import hudson.remoting.Callable;
import hudson.remoting.Channel;
import hudson.remoting.VirtualChannel;
@@ -61,8 +62,8 @@ public final class ProcessCache {
*/
Channel newProcess(BuildListener listener,OutputStream out) throws IOException, InterruptedException;
String getMavenOpts();
- MavenInstallation getMavenInstallation();
- JDK getJava();
+ MavenInstallation getMavenInstallation(TaskListener listener) throws IOException, InterruptedException;
+ JDK getJava(TaskListener listener) throws IOException, InterruptedException;
}
class MavenProcess {
@@ -161,8 +162,8 @@ public final class ProcessCache {
*/
public MavenProcess get(VirtualChannel owner, BuildListener listener, Factory factory) throws InterruptedException, IOException {
String mavenOpts = factory.getMavenOpts();
- MavenInstallation installation = factory.getMavenInstallation();
- JDK jdk = factory.getJava();
+ MavenInstallation installation = factory.getMavenInstallation(listener);
+ JDK jdk = factory.getJava(listener);
PerChannel list = get(owner);
synchronized(list.processes) {
diff --git a/test/src/main/java/org/jvnet/hudson/test/CaptureEnvironmentBuilder.java b/test/src/main/java/org/jvnet/hudson/test/CaptureEnvironmentBuilder.java
index 411c2f883f..c5997864a9 100644
--- a/test/src/main/java/org/jvnet/hudson/test/CaptureEnvironmentBuilder.java
+++ b/test/src/main/java/org/jvnet/hudson/test/CaptureEnvironmentBuilder.java
@@ -50,7 +50,7 @@ public class CaptureEnvironmentBuilder extends Builder {
}
public boolean perform(AbstractBuild, ?> build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException {
- envVars = build.getEnvironment();
+ envVars = build.getEnvironment(listener);
return true;
}
diff --git a/test/src/test/java/hudson/model/HudsonTest.java b/test/src/test/java/hudson/model/HudsonTest.java
index 98d9d1e359..60bf9e6a11 100644
--- a/test/src/test/java/hudson/model/HudsonTest.java
+++ b/test/src/test/java/hudson/model/HudsonTest.java
@@ -88,7 +88,7 @@ public class HudsonTest extends HudsonTestCase {
private void assertJDK(JDK jdk, String name, String home) {
assertEquals(jdk.getName(),name);
- assertEquals(jdk.getJavaHome(),home);
+ assertEquals(jdk.getHome(),home);
}
/**
diff --git a/test/src/test/java/hudson/tasks/EnvVarsInConfigTasksTest.java b/test/src/test/java/hudson/tasks/EnvVarsInConfigTasksTest.java
index bbd5eea642..ab7890c7f4 100644
--- a/test/src/test/java/hudson/tasks/EnvVarsInConfigTasksTest.java
+++ b/test/src/test/java/hudson/tasks/EnvVarsInConfigTasksTest.java
@@ -28,7 +28,7 @@ public class EnvVarsInConfigTasksTest extends HudsonTestCase {
super.setUp();
JDK defaultJDK = hudson.getJDK(null);
- JDK varJDK = new JDK("varJDK", withVariable(defaultJDK.getJavaHome()));
+ JDK varJDK = new JDK("varJDK", withVariable(defaultJDK.getHome()));
hudson.getJDKs().add(varJDK);
// Maven with a variable in its path
diff --git a/test/src/test/java/hudson/tasks/MavenTest.java b/test/src/test/java/hudson/tasks/MavenTest.java
index 93b340c979..6b3c6f16b1 100644
--- a/test/src/test/java/hudson/tasks/MavenTest.java
+++ b/test/src/test/java/hudson/tasks/MavenTest.java
@@ -95,7 +95,7 @@ public class MavenTest extends HudsonTestCase {
hudson.getDescriptorByType(Maven.DescriptorImpl.class).setInstallations(maven, varMaven);
JDK jdk = hudson.getJDK("default");
- String javaHome = jdk.getJavaHome();
+ String javaHome = jdk.getHome();
String javaHomeVar = "${VAR_JAVA}" + javaHome.substring(3);
String javaVar = javaHome.substring(0, 3);
JDK varJDK = new JDK("varJDK", javaHomeVar);
diff --git a/test/src/test/java/hudson/tools/JDKInstallerTest.java b/test/src/test/java/hudson/tools/JDKInstallerTest.java
new file mode 100644
index 0000000000..aff5d864aa
--- /dev/null
+++ b/test/src/test/java/hudson/tools/JDKInstallerTest.java
@@ -0,0 +1,59 @@
+package hudson.tools;
+
+import org.jvnet.hudson.test.HudsonTestCase;
+import hudson.model.JDK;
+import hudson.model.FreeStyleProject;
+import hudson.model.FreeStyleBuild;
+import hudson.tasks.Shell;
+
+import java.io.File;
+import java.util.Arrays;
+
+/**
+ * @author Kohsuke Kawaguchi
+ */
+public class JDKInstallerTest extends HudsonTestCase {
+ /**
+ * Tests the configuration round trip.
+ */
+ public void testConfigRoundtrip() throws Exception {
+ File tmp = env.temporaryDirectoryAllocator.allocate();
+ JDKInstaller installer = new JDKInstaller("jdk-6u13-oth-JPR@CDS-CDS_Developer", true);
+
+ hudson.getJDKs().add(new JDK("test",tmp.getAbsolutePath(), Arrays.asList(
+ new InstallSourceProperty(Arrays.asList(installer)))));
+
+ submit(new WebClient().goTo("configure").getFormByName("config"));
+
+ JDK jdk = hudson.getJDK("test");
+ InstallSourceProperty isp = jdk.getProperties().get(InstallSourceProperty.class);
+ assertEquals(1,isp.installers.size());
+ assertEqualBeans(installer,isp.installers.get(JDKInstaller.class),"id,acceptLicense");
+ }
+
+ /**
+ * Tests the auto installation.
+ */
+ public void testAutoInstallation() throws Exception {
+ // this is a really time consuming test, so only run it when we really want
+ if(!Boolean.getBoolean("hudson.sunTests"))
+ return;
+
+ File tmp = env.temporaryDirectoryAllocator.allocate();
+ JDKInstaller installer = new JDKInstaller("jdk-6u13-oth-JPR@CDS-CDS_Developer", true);
+
+ JDK jdk = new JDK("test", tmp.getAbsolutePath(), Arrays.asList(
+ new InstallSourceProperty(Arrays.asList(installer))));
+
+ hudson.getJDKs().add(jdk);
+
+ FreeStyleProject p = createFreeStyleProject();
+ p.setJDK(jdk);
+ p.getBuildersList().add(new Shell("java -fullversion\necho $JAVA_HOME"));
+ FreeStyleBuild b = assertBuildStatusSuccess(p.scheduleBuild2(0).get());
+ System.out.println(b.getLog());
+ // make sure it runs with the JDK that just got installed
+ assertTrue(b.getLog().contains("1.6.0_13-b03"));
+ assertTrue(b.getLog().contains(tmp.getAbsolutePath()));
+ }
+}
diff --git a/war/pom.xml b/war/pom.xml
index 52c2ecd0eb..7f77dc2d9a 100644
--- a/war/pom.xml
+++ b/war/pom.xml
@@ -111,7 +111,7 @@ THE SOFTWARE.
-
+
@@ -158,6 +158,11 @@ THE SOFTWARE.
stapler.trace
true
+
+
+ hudson.script.noCache
+ true
+
stapler.resourcePath
diff --git a/war/resources/css/style.css b/war/resources/css/style.css
index 76958a3d6b..263fa3e95a 100644
--- a/war/resources/css/style.css
+++ b/war/resources/css/style.css
@@ -687,6 +687,17 @@ TABLE.fingerprint-in-build TD {
.repeated-chunk .show-if-not-only { visibility: visible; }
.repeated-chunk.only .show-if-not-only { visibility: hidden; }
+/*
+ s marked with to-be-removed is used in conjunction with repetable.jelly and hetero-list.jelly
+ and represents a master copy that gets pulled out from HTML, then inserted later upon demand multiple times
+ when the user does "Add".
+*/
+DIV.to-be-removed { display: none; }
+
+/* ========================= Other form related CSS ========================= */
+
+.row-set-end { display: none; }
+
/* ========================= Yahoo UI style adjustments ========================= */
.ygtvlabel, .ygtvlabel:link, .ygtvlabel:visited, .ygtvlabel:hover {
color: inherit;
diff --git a/war/resources/help/tools/help-label.html b/war/resources/help/tools/help-label.html
new file mode 100644
index 0000000000..77586bd26e
--- /dev/null
+++ b/war/resources/help/tools/help-label.html
@@ -0,0 +1,4 @@
+
+ Optional label to restrict the use of this installation method.
+ Only nodes which have this label will be considered.
+
diff --git a/war/resources/scripts/hudson-behavior.js b/war/resources/scripts/hudson-behavior.js
index acc7dd9f40..bbbb793b8f 100644
--- a/war/resources/scripts/hudson-behavior.js
+++ b/war/resources/scripts/hudson-behavior.js
@@ -22,7 +22,7 @@
* THE SOFTWARE.
*/
//
-initOptionalBlock//
+//
// JavaScript for Hudson
// See http://www.ibm.com/developerworks/web/library/wa-memleak/?ca=dgr-lnxw97JavascriptLeaks
// for memory leak patterns and how to prevent them.
@@ -94,6 +94,13 @@ var FormChecker = {
}
}
+function toValue(e) {
+ // compute the form validation value to be sent to the server
+ if(e.getAttribute("type").toLowerCase()=="checkbox")
+ return e.checked;
+ return encode(e.value);
+}
+
// find the nearest ancestor node that has the given tag name
function findAncestor(e, tagName) {
do {
@@ -207,6 +214,14 @@ function makeButton(e,onclick) {
return btn;
}
+/*
+ If we are inside 'to-be-removed' class, some HTML altering behaviors interact badly, because
+ the behavior re-executes when the removed master copy gets reinserted later.
+ */
+function isInsideRemovable(e) {
+ return Element.ancestors(e).find(function(f){return f.hasClassName("to-be-removed");});
+}
+
var hudsonRules = {
"BODY" : function() {
tooltip = new YAHOO.widget.Tooltip("tt", {context:[], zindex:999});
@@ -216,6 +231,8 @@ var hudsonRules = {
// other behavior rules change them (like YUI buttons.)
"DIV.hetero-list-container" : function(e) {
+ if(isInsideRemovable(e)) return;
+
// components for the add button
var menu = document.createElement("SELECT");
var btn = findElementsBySelector(e,"INPUT.hetero-list-add")[0];
@@ -279,6 +296,8 @@ var hudsonRules = {
},
"DIV.repeated-container" : function(e) {
+ if(isInsideRemovable(e)) return;
+
// compute the insertion point
var ip = e.lastChild;
while (!Element.hasClassName(ip, "repeatable-insertion-point"))
@@ -516,6 +535,38 @@ var hudsonRules = {
makeButton(e);
},
+ "TR.optional-block-start": function(e) { // see optionalBlock.jelly
+ // set start.ref to checkbox in preparation of row-set-end processing
+ var checkbox = e.firstChild.firstChild;
+ e.setAttribute("ref", checkbox.id = "cb"+(iota++));
+ },
+
+ "TR.row-set-end": function(e) { // see rowSet.jelly and optionalBlock.jelly
+ // figure out the corresponding start block
+ var end = e;
+
+ for( var depth=0; ; e=e.previousSibling) {
+ if(Element.hasClassName(e,"row-set-end")) depth++;
+ if(Element.hasClassName(e,"row-set-start")) depth--;
+ if(depth==0) break;
+ }
+ var start = e;
+
+ var ref = start.getAttribute("ref");
+ if(ref==null)
+ start.id = ref = "rowSetStart"+(iota++);
+
+ applyNameRef(start,end,ref);
+ },
+
+ "BODY TR.optional-block-start": function(e) { // see optionalBlock.jelly
+ // this is prefixed by a pointless BODY so that two processing for optional-block-start
+ // can sandwitch row-set-end
+ // this requires "TR.row-set-end" to mark rows
+ var checkbox = e.firstChild.firstChild;
+ updateOptionalBlock(checkbox,false);
+ },
+
// image that shows [+] or [-], with hover effect.
// oncollapsed and onexpanded will be called when the button is triggered.
"IMG.fold-control" : function(e) {
@@ -598,11 +649,6 @@ function applyNameRef(s,e,id) {
}
}
-function initOptionalBlock(sid, eid, cid) {
- applyNameRef($(sid),$(eid),cid);
- updateOptionalBlock($(cid),false);
-}
-
// used by optionalBlock.jelly to update the form status
// @param c checkbox element
function updateOptionalBlock(c,scroll) {
@@ -1432,6 +1478,29 @@ function loadScript(href) {
document.getElementsByTagName("HEAD")[0].appendChild(s);
}
+var downloadService = {
+ continuations: {},
+
+ download : function(id,url,info, postBack,completionHandler) {
+ this.continuations[id] = {postBack:postBack,completionHandler:completionHandler};
+ loadScript(url+"?"+Hash.toQueryString(info));
+ },
+
+ post : function(id,data) {
+ var o = this.continuations[id];
+ new Ajax.Request(o.postBack, {
+ method:"post",
+ parameters:{json:Object.toJSON(data)},
+ onSuccess: function() {
+ if(o.completionHandler!=null)
+ o.completionHandler();
+ }
+ });
+ }
+};
+
+// update center service. for historical reasons,
+// this is separate from downloadSerivce
var updateCenter = {
postBackURL : null,
info: {},
|