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

1 package hudson.tools;
2
3 import hudson.FilePath;
4 import hudson.model.DownloadService.Downloadable;
5 import hudson.model.Node;
6 import hudson.model.TaskListener;
7 import net.sf.json.JSONObject;
8 import org.kohsuke.stapler.DataBoundConstructor;
9
10 import java.io.IOException;
11 import java.util.Arrays;
12 import java.util.Collections;
13 import java.util.List;
14 import java.net.URL;
15
16 /**
17 * Partial convenience implementation of {@link ToolInstaller} that just downloads
18 * an archive from the URL and extracts it.
19 *
20 * <p>
21 * Each instance of this is configured to download from a specific URL identified by an ID.
22 *
23 * @author Kohsuke Kawaguchi
24 * @since 1.308
25 */
26 public abstract class DownloadFromUrlInstaller extends ToolInstaller {
27 public final String id;
28
29 @DataBoundConstructor
30 protected DownloadFromUrlInstaller(String id) {
31 // this installer implementation is designed for platform independent binary,
32 // and as such we don't provide the label support
33 super(null);
34 this.id = id;
35 }
36
37 /**
38 * Checks if the specified expected location already contains the installed version of the tool.
39 *
40 * This check needs to run fairly efficiently. The current implementation uses the souce URL of {@link Installable},
41 * based on the assumption that released bits do not change its content.
42 */
43 protected boolean isUpToDate(FilePath expectedLocation, Installable i) throws IOException, InterruptedException {
44 FilePath marker = expectedLocation.child(".installedFrom");
45 return marker.exists() && marker.readToString().equals(i.url);
46 }
47
48 /**
49 * Gets the {@link Installable} identified by {@link #id}.
50 *
51 * @return null if no such ID is found.
52 */
53 public Installable getInstallable() throws IOException {
54 for (Installable i : ((DescriptorImpl<?>)getDescriptor()).getInstallables())
55 if(id.equals(i.id))
56 return i;
57 return null;
58 }
59
60 public FilePath performInstallation(ToolInstallation tool, Node node, TaskListener log) throws IOException, InterruptedException {
61 FilePath expected = preferredLocation(tool, node);
62
63 Installable inst = getInstallable();
64 if(inst==null) {
65 log.getLogger().println("Invalid tool ID "+id);
66 return expected;
67 }
68
69 if(isUpToDate(expected,inst))
70 return expected;
71
72 if(expected.installIfNecessaryFrom(new URL(inst.url), log, "Unpacking " + inst.url + " to " + expected + " on " + node.getDisplayName())) {
73 expected.child(".timestamp").delete(); // we don't use the timestamp
74 FilePath base = findPullUpDirectory(expected);
75 if(base!=null && base!=expected)
76 base.moveAllChildrenTo(expected);
77 // leave a record for the next up-to-date check
78 expected.child(".installedFrom").write(inst.url,"UTF-8");
79 expected.act(new ZipExtractionInstaller.ChmodRecAPlusX());
80 }
81
82 return expected;
83 }
84
85 /**
86 * Often an archive contains an extra top-level directory that's unnecessary when extracted on the disk
87 * into the expected location. If your installation sources provide that kind of archives, override
88 * this method to find the real root location.
89 *
90 * <p>
91 * The caller will "pull up" the discovered real root by throw away the intermediate directory,
92 * so that the user-configured "tool home" directory contains the right files.
93 *
94 * <p>
95 * The default implementation applies some heuristics to auto-determine if the pull up is necessary.
96 * This should work for typical archive files.
97 *
98 * @param root
99 * The directory that contains the extracted archive. This directory contains nothing but the
100 * extracted archive. For example, if the user installed
101 * http://archive.apache.org/dist/ant/binaries/jakarta-ant-1.1.zip , this directory would contain
102 * a single directory "jakarta-ant".
103 *
104 * @return
105 * Return the real top directory inside {@code root} that contains the meat. In the above example,
106 * <tt>root.child("jakarta-ant")</tt> should be returned. If there's no directory to pull up,
107 * return null.
108 */
109 protected FilePath findPullUpDirectory(FilePath root) throws IOException, InterruptedException {
110 // if the directory just contains one directory and that alone, assume that's the pull up subject
111 // otherwise leave it as is.
112 List<FilePath> children = root.list();
113 if(children.size()!=1) return null;
114 if(children.get(0).isDirectory())
115 return children.get(0);
116 return null;
117 }
118
119 public static abstract class DescriptorImpl<T extends DownloadFromUrlInstaller> extends ToolInstallerDescriptor<T> {
120
121 @SuppressWarnings("deprecation") // intentionally adding dynamic item here
122 protected DescriptorImpl() {
123 Downloadable.all().add(createDownloadable());
124 }
125
126 protected Downloadable createDownloadable() {
127 return new Downloadable(getId());
128 }
129
130 /**
131 * This ID needs to be unique, and needs to match the ID token in the JSON update file.
132 * <p>
133 * By default we use the fully-qualified class name of the {@link DownloadFromUrlInstaller} subtype.
134 */
135 public String getId() {
136 return clazz.getName().replace('$','.');
137 }
138
139 /**
140 * List of installable tools.
141 *
142 * <p>
143 * The UI uses this information to populate the drop-down. Subtypes can override this method
144 * if it wants to change the way the list is filled.
145 *
146 * @return never null.
147 */
148 public List<? extends Installable> getInstallables() throws IOException {
149 JSONObject d = Downloadable.get(getId()).getData();
150 if(d==null) return Collections.emptyList();
151 return Arrays.asList(((InstallableList)JSONObject.toBean(d,InstallableList.class)).list);
152 }
153 }
154
155 /**
156 * Used for JSON databinding to parse the obtained list.
157 */
158 public static class InstallableList {
159 // initialize with an empty array just in case JSON doesn't have the list field (which shouldn't happen.)
160 public Installable[] list = new Installable[0];
161 }
162
163 /**
164 * Downloadable and installable tool.
165 */
166 public static class Installable {
167 /**
168 * Used internally to uniquely identify the name.
169 */
170 public String id;
171 /**
172 * This is the human readable name.
173 */
174 public String name;
175 /**
176 * URL.
177 */
178 public String url;
179 }
180 }
181