/* * The MIT License * * Copyright (c) 2009-2010, Sun Microsystems, Inc., CloudBees, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package hudson.tools; import hudson.AbortException; import hudson.Extension; import hudson.FilePath; import hudson.Launcher; import hudson.Launcher.ProcStarter; import hudson.ProxyConfiguration; import hudson.Util; import hudson.model.DownloadService.Downloadable; import hudson.model.JDK; import hudson.model.Node; import hudson.model.TaskListener; import hudson.remoting.Callable; import hudson.util.ArgumentListBuilder; import hudson.util.FormValidation; import hudson.util.HttpResponses; import hudson.util.Secret; import jenkins.model.Jenkins; import jenkins.security.MasterToSlaveCallable; import net.sf.json.JSONObject; import org.apache.commons.httpclient.Cookie; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpMethodBase; import org.apache.commons.httpclient.UsernamePasswordCredentials; import org.apache.commons.httpclient.auth.AuthScope; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.httpclient.methods.PostMethod; import org.apache.commons.io.IOUtils; import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.HttpResponse; import org.kohsuke.stapler.QueryParameter; import org.kohsuke.stapler.Stapler; import javax.servlet.ServletException; import java.io.ByteArrayInputStream; import java.io.DataInputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintStream; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; import static hudson.tools.JDKInstaller.Preference.*; /** * Install JDKs from java.sun.com. * * @author Kohsuke Kawaguchi * @since 1.305 */ public class JDKInstaller extends ToolInstaller { /** * The release ID that Sun assigns to each JDK, such as "jdk-6u13-oth-JPR@CDS-CDS_Developer" * *
* This ID can be seen in the "ProductRef" query parameter of the download page, like
* https://cds.sun.com/is-bin/INTERSHOP.enfinity/WFS/CDS-CDS_Developer-Site/en_US/-/USD/ViewProductDetail-Start?ProductRef=jdk-6u13-oth-JPR@CDS-CDS_Developer
*/
public final String id;
/**
* We require that the user accepts the license by clicking a checkbox, to make up for the part
* that we auto-accept cds.sun.com license click through.
*/
public final boolean acceptLicense;
@DataBoundConstructor
public JDKInstaller(String id, boolean acceptLicense) {
super(null);
this.id = id;
this.acceptLicense = acceptLicense;
}
public FilePath performInstallation(ToolInstallation tool, Node node, TaskListener log) throws IOException, InterruptedException {
FilePath expectedLocation = preferredLocation(tool, node);
PrintStream out = log.getLogger();
try {
if(!acceptLicense) {
out.println(Messages.JDKInstaller_UnableToInstallUntilLicenseAccepted());
return expectedLocation;
}
// already installed?
FilePath marker = expectedLocation.child(".installedByHudson");
if (marker.exists() && marker.readToString().equals(id)) {
return expectedLocation;
}
expectedLocation.deleteRecursive();
expectedLocation.mkdirs();
Platform p = Platform.of(node);
URL url = locate(log, p, CPU.of(node));
// out.println("Downloading "+url);
FilePath file = expectedLocation.child(p.bundleFileName);
file.copyFrom(url);
// JDK6u13 on Windows doesn't like path representation like "/tmp/foo", so make it a strict platform native format by doing 'absolutize'
install(node.createLauncher(log), p, new FilePathFileSystem(node), log, expectedLocation.absolutize().getRemote(), file.getRemote());
// successfully installed
file.delete();
marker.write(id, null);
} catch (DetectionFailedException e) {
out.println("JDK installation skipped: "+e.getMessage());
}
return expectedLocation;
}
/**
* Performs the JDK installation to a system, provided that the bundle was already downloaded.
*
* @param launcher
* Used to launch processes on the system.
* @param p
* Platform of the system. This determines how the bundle is installed.
* @param fs
* Abstraction of the file system manipulation on this system.
* @param log
* Where the output from the installation will be written.
* @param expectedLocation
* Path to install JDK to. Must be absolute and in the native file system notation.
* @param jdkBundle
* Path to the installed JDK bundle. (The bundle to download can be determined by {@link #locate(TaskListener, Platform, CPU)} call.)
*/
public void install(Launcher launcher, Platform p, FileSystem fs, TaskListener log, String expectedLocation, String jdkBundle) throws IOException, InterruptedException {
PrintStream out = log.getLogger();
out.println("Installing "+ jdkBundle);
switch (p) {
case LINUX:
case SOLARIS:
// JDK on Unix up to 6 was distributed as shell script installer, but in JDK7 it switched to a plain tgz.
// so check if the file is gzipped, and if so, treat it accordingly
byte[] header = new byte[2];
{
DataInputStream in = new DataInputStream(fs.read(jdkBundle));
in.readFully(header);
in.close();
}
ProcStarter starter;
if (header[0]==0x1F && header[1]==(byte)0x8B) {// gzip
starter = launcher.launch().cmds("tar", "xvzf", jdkBundle);
} else {
fs.chmod(jdkBundle,0755);
starter = launcher.launch().cmds(jdkBundle, "-noregister");
}
int exit = starter
.stdin(new ByteArrayInputStream("yes".getBytes())).stdout(out)
.pwd(new FilePath(launcher.getChannel(), expectedLocation)).join();
if (exit != 0)
throw new AbortException(Messages.JDKInstaller_FailedToInstallJDK(exit));
// JDK creates its own sub-directory, so pull them up
List