File D:\maven-qcr-plugin-testsunitaires\qcr4java\jenkins-master\target\site\qc\core\src\main\java\hudson\tools\JDKInstaller.java.html

1 /*
2 * The MIT License
3 *
4 * Copyright (c) 2009-2010, Sun Microsystems, Inc., CloudBees, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24 package hudson.tools;
25
26 import hudson.AbortException;
27 import hudson.Extension;
28 import hudson.FilePath;
29 import hudson.Launcher;
30 import hudson.Launcher.ProcStarter;
31 import hudson.ProxyConfiguration;
32 import hudson.Util;
33 import hudson.model.DownloadService.Downloadable;
34 import hudson.model.JDK;
35 import hudson.model.Node;
36 import hudson.model.TaskListener;
37 import hudson.remoting.Callable;
38 import hudson.util.ArgumentListBuilder;
39 import hudson.util.FormValidation;
40 import hudson.util.HttpResponses;
41 import hudson.util.Secret;
42 import jenkins.model.Jenkins;
43 import net.sf.json.JSONObject;
44 import org.apache.commons.httpclient.Cookie;
45 import org.apache.commons.httpclient.HttpClient;
46 import org.apache.commons.httpclient.HttpMethodBase;
47 import org.apache.commons.httpclient.UsernamePasswordCredentials;
48 import org.apache.commons.httpclient.auth.AuthScope;
49 import org.apache.commons.httpclient.methods.GetMethod;
50 import org.apache.commons.httpclient.methods.PostMethod;
51 import org.apache.commons.io.IOUtils;
52 import org.kohsuke.stapler.DataBoundConstructor;
53 import org.kohsuke.stapler.HttpResponse;
54 import org.kohsuke.stapler.QueryParameter;
55 import org.kohsuke.stapler.Stapler;
56
57 import javax.servlet.ServletException;
58 import java.io.ByteArrayInputStream;
59 import java.io.DataInputStream;
60 import java.io.File;
61 import java.io.FileOutputStream;
62 import java.io.IOException;
63 import java.io.InputStream;
64 import java.io.InputStreamReader;
65 import java.io.OutputStreamWriter;
66 import java.io.PrintStream;
67 import java.net.URL;
68 import java.util.ArrayList;
69 import java.util.Arrays;
70 import java.util.Iterator;
71 import java.util.List;
72 import java.util.Locale;
73 import java.util.logging.Logger;
74 import java.util.regex.Matcher;
75 import java.util.regex.Pattern;
76
77 import static hudson.tools.JDKInstaller.Preference.*;
78
79 /**
80 * Install JDKs from java.sun.com.
81 *
82 * @author Kohsuke Kawaguchi
83 * @since 1.305
84 */
85 public class JDKInstaller extends ToolInstaller {
86 /**
87 * The release ID that Sun assigns to each JDK, such as "jdk-6u13-oth-JPR@CDS-CDS_Developer"
88 *
89 * <p>
90 * This ID can be seen in the "ProductRef" query parameter of the download page, like
91 * 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
92 */
93 public final String id;
94
95 /**
96 * We require that the user accepts the license by clicking a checkbox, to make up for the part
97 * that we auto-accept cds.sun.com license click through.
98 */
99 public final boolean acceptLicense;
100
101 @DataBoundConstructor
102 public JDKInstaller(String id, boolean acceptLicense) {
103 super(null);
104 this.id = id;
105 this.acceptLicense = acceptLicense;
106 }
107
108 public FilePath performInstallation(ToolInstallation tool, Node node, TaskListener log) throws IOException, InterruptedException {
109 FilePath expectedLocation = preferredLocation(tool, node);
110 PrintStream out = log.getLogger();
111 try {
112 if(!acceptLicense) {
113 out.println(Messages.JDKInstaller_UnableToInstallUntilLicenseAccepted());
114 return expectedLocation;
115 }
116 // already installed?
117 FilePath marker = expectedLocation.child(".installedByHudson");
118 if (marker.exists() && marker.readToString().equals(id)) {
119 return expectedLocation;
120 }
121 expectedLocation.deleteRecursive();
122 expectedLocation.mkdirs();
123
124 Platform p = Platform.of(node);
125 URL url = locate(log, p, CPU.of(node));
126
127 // out.println("Downloading "+url);
128 FilePath file = expectedLocation.child(p.bundleFileName);
129 file.copyFrom(url);
130
131 // JDK6u13 on Windows doesn't like path representation like "/tmp/foo", so make it a strict platform native format by doing 'absolutize'
132 install(node.createLauncher(log), p, new FilePathFileSystem(node), log, expectedLocation.absolutize().getRemote(), file.getRemote());
133
134 // successfully installed
135 file.delete();
136 marker.write(id, null);
137
138 } catch (DetectionFailedException e) {
139 out.println("JDK installation skipped: "+e.getMessage());
140 }
141
142 return expectedLocation;
143 }
144
145 /**
146 * Performs the JDK installation to a system, provided that the bundle was already downloaded.
147 *
148 * @param launcher
149 * Used to launch processes on the system.
150 * @param p
151 * Platform of the system. This determines how the bundle is installed.
152 * @param fs
153 * Abstraction of the file system manipulation on this system.
154 * @param log
155 * Where the output from the installation will be written.
156 * @param expectedLocation
157 * Path to install JDK to. Must be absolute and in the native file system notation.
158 * @param jdkBundle
159 * Path to the installed JDK bundle. (The bundle to download can be determined by {@link #locate(TaskListener, Platform, CPU)} call.)
160 */
161 public void install(Launcher launcher, Platform p, FileSystem fs, TaskListener log, String expectedLocation, String jdkBundle) throws IOException, InterruptedException {
162 PrintStream out = log.getLogger();
163
164 out.println("Installing "+ jdkBundle);
165 switch (p) {
166 case LINUX:
167 case SOLARIS:
168 // JDK on Unix up to 6 was distributed as shell script installer, but in JDK7 it switched to a plain tgz.
169 // so check if the file is gzipped, and if so, treat it accordingly
170 byte[] header = new byte[2];
171 {
172 DataInputStream in = new DataInputStream(fs.read(jdkBundle));
173 in.readFully(header);
174 in.close();
175 }
176
177 ProcStarter starter;
178 if (header[0]==0x1F && header[1]==(byte)0x8B) {// gzip
179 starter = launcher.launch().cmds("tar", "xvzf", jdkBundle);
180 } else {
181 fs.chmod(jdkBundle,0755);
182 starter = launcher.launch().cmds(jdkBundle, "-noregister");
183 }
184
185 int exit = starter
186 .stdin(new ByteArrayInputStream("yes".getBytes())).stdout(out)
187 .pwd(new FilePath(launcher.getChannel(), expectedLocation)).join();
188 if (exit != 0)
189 throw new AbortException(Messages.JDKInstaller_FailedToInstallJDK(exit));
190
191 // JDK creates its own sub-directory, so pull them up
192 List<String> paths = fs.listSubDirectories(expectedLocation);
193 for (Iterator<String> itr = paths.iterator(); itr.hasNext();) {
194 String s = itr.next();
195 if (!s.matches("j(2s)?dk.*"))
196 itr.remove();
197 }
198 if(paths.size()!=1)
199 throw new AbortException("Failed to find the extracted JDKs: "+paths);
200
201 // remove the intermediate directory
202 fs.pullUp(expectedLocation+'/'+paths.get(0),expectedLocation);
203 break;
204 case WINDOWS:
205 /*
206 Windows silent installation is full of bad know-how.
207
208 On Windows, command line argument to a process at the OS level is a single string,
209 not a string array like POSIX. When we pass arguments as string array, JRE eventually
210 turn it into a single string with adding quotes to "the right place". Unfortunately,
211 with the strange argument layout of InstallShield (like /v/qn" INSTALLDIR=foobar"),
212 it appears that the escaping done by JRE gets in the way, and prevents the installation.
213 Presumably because of this, my attempt to use /q/vn" INSTALLDIR=foo" didn't work with JDK5.
214
215 I tried to locate exactly how InstallShield parses the arguments (and why it uses
216 awkward option like /qn, but couldn't find any. Instead, experiments revealed that
217 "/q/vn ARG ARG ARG" works just as well. This is presumably due to the Visual C++ runtime library
218 (which does single string -> string array conversion to invoke the main method in most Win32 process),
219 and this consistently worked on JDK5 and JDK4.
220
221 Some of the official documentations are available at
222 - http://java.sun.com/j2se/1.5.0/sdksilent.html
223 - http://java.sun.com/j2se/1.4.2/docs/guide/plugin/developer_guide/silent.html
224 */
225 String logFile = jdkBundle+".install.log";
226
227 ArgumentListBuilder args = new ArgumentListBuilder();
228 args.add(jdkBundle);
229 if (isJava15() || isJava14()) {
230 args.add("/s","/v/qn REBOOT=ReallySuppress INSTALLDIR=\\\""+ expectedLocation +"\\\" /L \\\""+logFile+"\\\"");
231 } else {
232 // modern version supports arguments in more sane format.
233 args.add("/s","/v","/qn","/L","\\\""+logFile+"\\\"","REBOOT=ReallySuppress","INSTALLDIR=\\\""+ expectedLocation+"\\\"");
234 }
235 // according to http://community.acresso.com/showthread.php?t=83301, \" is the trick to quote values with whitespaces.
236 // Oh Windows, oh windows, why do you have to be so difficult?
237 int r = launcher.launch().cmds(args).stdout(out)
238 .pwd(new FilePath(launcher.getChannel(), expectedLocation)).join();
239 if (r != 0) {
240 out.println(Messages.JDKInstaller_FailedToInstallJDK(r));
241 // log file is in UTF-16
242 InputStreamReader in = new InputStreamReader(fs.read(logFile), "UTF-16");
243 try {
244 IOUtils.copy(in,new OutputStreamWriter(out));
245 } finally {
246 in.close();
247 }
248 throw new AbortException();
249 }
250
251 fs.delete(logFile);
252
253 break;
254 }
255 }
256
257 private boolean isJava15() {
258 return id.contains("-1.5");
259 }
260
261 private boolean isJava14() {
262 return id.contains("-1.4");
263 }
264
265 /**
266 * Abstraction of the file system to perform JDK installation.
267 * Consider {@link FilePathFileSystem} as the canonical documentation of the contract.
268 */
269 public interface FileSystem {
270 void delete(String file) throws IOException, InterruptedException;
271 void chmod(String file,int mode) throws IOException, InterruptedException;
272 InputStream read(String file) throws IOException;
273 /**
274 * List sub-directories of the given directory and just return the file name portion.
275 */
276 List<String> listSubDirectories(String dir) throws IOException, InterruptedException;
277 void pullUp(String from, String to) throws IOException, InterruptedException;
278 }
279
280 /*package*/ static final class FilePathFileSystem implements FileSystem {
281 private final Node node;
282
283 FilePathFileSystem(Node node) {
284 this.node = node;
285 }
286
287 public void delete(String file) throws IOException, InterruptedException {
288 $(file).delete();
289 }
290
291 public void chmod(String file, int mode) throws IOException, InterruptedException {
292 $(file).chmod(mode);
293 }
294
295 public InputStream read(String file) throws IOException {
296 return $(file).read();
297 }
298
299 public List<String> listSubDirectories(String dir) throws IOException, InterruptedException {
300 List<String> r = new ArrayList<String>();
301 for( FilePath f : $(dir).listDirectories())
302 r.add(f.getName());
303 return r;
304 }
305
306 public void pullUp(String from, String to) throws IOException, InterruptedException {
307 $(from).moveAllChildrenTo($(to));
308 }
309
310 private FilePath $(String file) {
311 return node.createPath(file);
312 }
313 }
314
315 /**
316 * This is where we locally cache this JDK.
317 */
318 private File getLocalCacheFile(Platform platform, CPU cpu) {
319 return new File(Jenkins.getInstance().getRootDir(),"cache/jdks/"+platform+"/"+cpu+"/"+id);
320 }
321
322 /**
323 * Performs a license click through and obtains the one-time URL for downloading bits.
324 */
325 public URL locate(TaskListener log, Platform platform, CPU cpu) throws IOException {
326 File cache = getLocalCacheFile(platform, cpu);
327 if (cache.exists() && cache.length()>1*1024*1024) return cache.toURL(); // if the file is too small, don't trust it. In the past, the download site served error message in 200 status code
328
329 log.getLogger().println("Installing JDK "+id);
330 JDKFamilyList families = JDKList.all().get(JDKList.class).toList();
331 if (families.isEmpty())
332 throw new IOException("JDK data is empty.");
333
334 JDKRelease release = families.getRelease(id);
335 if (release==null)
336 throw new IOException("Unable to find JDK with ID="+id);
337
338 JDKFile primary=null,secondary=null;
339 for (JDKFile f : release.files) {
340 String vcap = f.name.toUpperCase(Locale.ENGLISH);
341
342 // JDK files have either 'windows', 'linux', or 'solaris' in its name, so that allows us to throw
343 // away unapplicable stuff right away
344 if(!platform.is(vcap))
345 continue;
346
347 switch (cpu.accept(vcap)) {
348 case PRIMARY: primary = f;break;
349 case SECONDARY: secondary=f;break;
350 case UNACCEPTABLE: break;
351 }
352 }
353
354 if(primary==null) primary=secondary;
355 if(primary==null)
356 throw new AbortException("Couldn't find the right download for "+platform+" and "+ cpu +" combination");
357 LOGGER.fine("Platform choice:"+primary);
358
359 log.getLogger().println("Downloading JDK from "+primary.filepath);
360
361 HttpClient hc = new HttpClient();
362 hc.getParams().setParameter("http.useragent","Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)");
363 Jenkins j = Jenkins.getInstance();
364 ProxyConfiguration jpc = j!=null ? j.proxy : null;
365 if(jpc != null) {
366 hc.getHostConfiguration().setProxy(jpc.name, jpc.port);
367 if(jpc.getUserName() != null)
368 hc.getState().setProxyCredentials(AuthScope.ANY,new UsernamePasswordCredentials(jpc.getUserName(),jpc.getPassword()));
369 }
370
371 int authCount=0, totalPageCount=0; // counters for avoiding infinite loop
372
373 HttpMethodBase m = new GetMethod(primary.filepath);
374 hc.getState().addCookie(new Cookie(".oracle.com","gpw_e24",".", "/", -1, false));
375 try {
376 while (true) {
377 if (totalPageCount++>16) // looping too much
378 throw new IOException("Unable to find the login form");
379
380 LOGGER.fine("Requesting " + m.getURI());
381 int r = hc.executeMethod(m);
382 if (r/100==3) {
383 // redirect?
384 String loc = m.getResponseHeader("Location").getValue();
385 m.releaseConnection();
386 m = new GetMethod(loc);
387 continue;
388 }
389 if (r!=200)
390 throw new IOException("Failed to request " + m.getURI() +" exit code="+r);
391
392 if (m.getURI().getHost().equals("login.oracle.com")) {
393 LOGGER.fine("Appears to be a login page");
394 String resp = IOUtils.toString(m.getResponseBodyAsStream(), m.getResponseCharSet());
395 m.releaseConnection();
396 Matcher pm = Pattern.compile("<form .*?action=\"([^\"]*)\" .*?</form>", Pattern.DOTALL).matcher(resp);
397 if (!pm.find())
398 throw new IllegalStateException("Unable to find a form in the response:\n"+resp);
399
400 String form = pm.group();
401 PostMethod post = new PostMethod(
402 new URL(new URL(m.getURI().getURI()),pm.group(1)).toExternalForm());
403
404 String u = getDescriptor().getUsername();
405 Secret p = getDescriptor().getPassword();
406 if (u==null || p==null) {
407 log.hyperlink(getCredentialPageUrl(),"Oracle now requires Oracle account to download previous versions of JDK. Please specify your Oracle account username/password.\n");
408 throw new AbortException("Unable to install JDK unless a valid Oracle account username/password is provided in the system configuration.");
409 }
410
411 for (String fragment : form.split("<input")) {
412 String n = extractAttribute(fragment,"name");
413 String v = extractAttribute(fragment,"value");
414 if (n==null || v==null) continue;
415 if (n.equals("ssousername"))
416 v = u;
417 if (n.equals("password")) {
418 v = p.getPlainText();
419 if (authCount++ > 3) {
420 log.hyperlink(getCredentialPageUrl(),"Your Oracle account doesn't appear valid. Please specify a valid username/password\n");
421 throw new AbortException("Unable to install JDK unless a valid username/password is provided.");
422 }
423 }
424 post.addParameter(n, v);
425 }
426
427 m = post;
428 } else {
429 log.getLogger().println("Downloading " + m.getResponseContentLength() + "bytes");
430
431 // download to a temporary file and rename it in to handle concurrency and failure correctly,
432 File tmp = new File(cache.getPath()+".tmp");
433 try {
434 tmp.getParentFile().mkdirs();
435 FileOutputStream out = new FileOutputStream(tmp);
436 try {
437 IOUtils.copy(m.getResponseBodyAsStream(), out);
438 } finally {
439 out.close();
440 }
441
442 tmp.renameTo(cache);
443 return cache.toURL();
444 } finally {
445 tmp.delete();
446 }
447 }
448 }
449 } finally {
450 m.releaseConnection();
451 }
452 }
453
454 private static String extractAttribute(String s, String name) {
455 String h = name + "=\"";
456 int si = s.indexOf(h);
457 if (si<0) return null;
458 int ei = s.indexOf('\"',si+h.length());
459 return s.substring(si+h.length(),ei);
460 }
461
462 private String getCredentialPageUrl() {
463 return "/"+getDescriptor().getDescriptorUrl()+"/enterCredential";
464 }
465
466 public enum Preference {
467 PRIMARY, SECONDARY, UNACCEPTABLE
468 }
469
470 /**
471 * Supported platform.
472 */
473 public enum Platform {
474 LINUX("jdk.sh"), SOLARIS("jdk.sh"), WINDOWS("jdk.exe");
475
476 /**
477 * Choose the file name suitable for the downloaded JDK bundle.
478 */
479 public final String bundleFileName;
480
481 Platform(String bundleFileName) {
482 this.bundleFileName = bundleFileName;
483 }
484
485 public boolean is(String line) {
486 return line.contains(name());
487 }
488
489 /**
490 * Determines the platform of the given node.
491 */
492 public static Platform of(Node n) throws IOException,InterruptedException,DetectionFailedException {
493 return n.getChannel().call(new GetCurrentPlatform());
494 }
495
496 public static Platform current() throws DetectionFailedException {
497 String arch = System.getProperty("os.name").toLowerCase(Locale.ENGLISH);
498 if(arch.contains("linux")) return LINUX;
499 if(arch.contains("windows")) return WINDOWS;
500 if(arch.contains("sun") || arch.contains("solaris")) return SOLARIS;
501 throw new DetectionFailedException("Unknown CPU name: "+arch);
502 }
503
504 static class GetCurrentPlatform implements Callable<Platform,DetectionFailedException> {
505 private static final long serialVersionUID = 1L;
506 public Platform call() throws DetectionFailedException {
507 return current();
508 }
509 }
510
511 }
512
513 /**
514 * CPU type.
515 */
516 public enum CPU {
517 i386, amd64, Sparc, Itanium;
518
519 /**
520 * In JDK5u3, I see platform like "Linux AMD64", while JDK6u3 refers to "Linux x64", so
521 * just use "64" for locating bits.
522 */
523 public Preference accept(String line) {
524 switch (this) {
525 // these two guys are totally incompatible with everything else, so no fallback
526 case Sparc: return must(line.contains("SPARC"));
527 case Itanium: return must(line.contains("IA64"));
528
529 // 64bit Solaris, Linux, and Windows can all run 32bit executable, so fall back to 32bit if 64bit bundle is not found
530 case amd64:
531 if(line.contains("SPARC") || line.contains("IA64")) return UNACCEPTABLE;
532 if(line.contains("64")) return PRIMARY;
533 return SECONDARY;
534 case i386:
535 if(line.contains("64") || line.contains("SPARC") || line.contains("IA64")) return UNACCEPTABLE;
536 return PRIMARY;
537 }
538 return UNACCEPTABLE;
539 }
540
541 private static Preference must(boolean b) {
542 return b ? PRIMARY : UNACCEPTABLE;
543 }
544
545 /**
546 * Determines the CPU of the given node.
547 */
548 public static CPU of(Node n) throws IOException,InterruptedException, DetectionFailedException {
549 return n.getChannel().call(new GetCurrentCPU());
550 }
551
552 /**
553 * Determines the CPU of the current JVM.
554 *
555 * http://lopica.sourceforge.net/os.html was useful in writing this code.
556 */
557 public static CPU current() throws DetectionFailedException {
558 String arch = System.getProperty("os.arch").toLowerCase(Locale.ENGLISH);
559 if(arch.contains("sparc")) return Sparc;
560 if(arch.contains("ia64")) return Itanium;
561 if(arch.contains("amd64") || arch.contains("86_64")) return amd64;
562 if(arch.contains("86")) return i386;
563 throw new DetectionFailedException("Unknown CPU architecture: "+arch);
564 }
565
566 static class GetCurrentCPU implements Callable<CPU,DetectionFailedException> {
567 private static final long serialVersionUID = 1L;
568 public CPU call() throws DetectionFailedException {
569 return current();
570 }
571 }
572
573 }
574
575 /**
576 * Indicates the failure to detect the OS or CPU.
577 */
578 private static final class DetectionFailedException extends Exception {
579 private DetectionFailedException(String message) {
580 super(message);
581 }
582 }
583
584 public static final class JDKFamilyList {
585 public int version;
586 public JDKFamily[] data = new JDKFamily[0];
587
588 public boolean isEmpty() {
589 for (JDKFamily f : data) {
590 if (f.releases.length>0)
591 return false;
592 }
593 return true;
594 }
595
596 public JDKRelease getRelease(String productCode) {
597 for (JDKFamily f : data) {
598 for (JDKRelease r : f.releases) {
599 if (r.matchesId(productCode))
600 return r;
601 }
602 }
603 return null;
604 }
605 }
606
607 public static final class JDKFamily {
608 public String name;
609 public JDKRelease[] releases;
610 }
611
612 public static final class JDKRelease {
613 /**
614 * This maps to the former product code, like "jdk-6u13-oth-JPR"
615 */
616 public String name;
617 /**
618 * This is human readable.
619 */
620 public String title;
621 public JDKFile[] files;
622
623 /**
624 * We used to use IDs like "jdk-6u13-oth-JPR@CDS-CDS_Developer", but Oracle switched to just "jdk-6u13-oth-JPR".
625 * This method matches if the specified string matches the name, and it accepts both the old and the new format.
626 */
627 public boolean matchesId(String rhs) {
628 return rhs!=null && (rhs.equals(name) || rhs.startsWith(name+"@"));
629 }
630 }
631
632 public static final class JDKFile {
633 public String name;
634 public String title;
635 public String filepath;
636 }
637
638 @Override
639 public DescriptorImpl getDescriptor() {
640 return (DescriptorImpl)super.getDescriptor();
641 }
642
643 @Extension
644 public static final class DescriptorImpl extends ToolInstallerDescriptor<JDKInstaller> {
645 private String username;
646 private Secret password;
647
648 public DescriptorImpl() {
649 load();
650 }
651
652 public String getDisplayName() {
653 return Messages.JDKInstaller_DescriptorImpl_displayName();
654 }
655
656 @Override
657 public boolean isApplicable(Class<? extends ToolInstallation> toolType) {
658 return toolType==JDK.class;
659 }
660
661 public String getUsername() {
662 return username;
663 }
664
665 public Secret getPassword() {
666 return password;
667 }
668
669 public FormValidation doCheckId(@QueryParameter String value) {
670 if (Util.fixEmpty(value) == null)
671 return FormValidation.error(Messages.JDKInstaller_DescriptorImpl_doCheckId()); // improve message
672 return FormValidation.ok();
673 }
674
675 /**
676 * List of installable JDKs.
677 * @return never null.
678 */
679 public List<JDKFamily> getInstallableJDKs() throws IOException {
680 return Arrays.asList(JDKList.all().get(JDKList.class).toList().data);
681 }
682
683 public FormValidation doCheckAcceptLicense(@QueryParameter boolean value) {
684 if (username==null || password==null)
685 return FormValidation.errorWithMarkup(Messages.JDKInstaller_RequireOracleAccount(Stapler.getCurrentRequest().getContextPath()+'/'+getDescriptorUrl()+"/enterCredential"));
686 if (value) {
687 return FormValidation.ok();
688 } else {
689 return FormValidation.error(Messages.JDKInstaller_DescriptorImpl_doCheckAcceptLicense());
690 }
691 }
692
693 /**
694 * Submits the Oracle account username/password.
695 */
696 public HttpResponse doPostCredential(@QueryParameter String username, @QueryParameter String password) throws IOException, ServletException {
697 this.username = username;
698 this.password = Secret.fromString(password);
699 save();
700 return HttpResponses.redirectTo("credentialOK");
701 }
702 }
703
704 /**
705 * JDK list.
706 */
707 @Extension
708 public static final class JDKList extends Downloadable {
709 public JDKList() {
710 super(JDKInstaller.class);
711 }
712
713 public JDKFamilyList toList() throws IOException {
714 JSONObject d = getData();
715 if(d==null) return new JDKFamilyList();
716 return (JDKFamilyList)JSONObject.toBean(d,JDKFamilyList.class);
717 }
718 }
719
720 private static final Logger LOGGER = Logger.getLogger(JDKInstaller.class.getName());
721 }
722