6
|
1 import java.util.*;
|
|
2 import java.awt.event.ActionEvent;
|
|
3 import java.awt.event.ActionListener;
|
|
4 import java.io.*;
|
|
5 import javax.swing.*;
|
|
6 import javax.swing.filechooser.*;
|
|
7 import javax.swing.border.*;
|
|
8 import javax.swing.SwingUtilities;
|
|
9 import java.net.*;
|
|
10 import java.util.Stack;
|
|
11 import java.util.zip.ZipEntry;
|
|
12 import java.util.zip.ZipInputStream;
|
|
13
|
|
14 public class SmartInstallerTask extends SwingWorker<Boolean, String> {
|
|
15
|
|
16 int BUFFER = 1024;
|
|
17
|
|
18 int architecture = 0;
|
|
19 String installDirectoryName = null;
|
|
20 JTextArea logArea = null;
|
|
21 boolean[] selectedPrograms = null;
|
|
22
|
|
23 // program chooser buttons
|
|
24 String programChoosers[] = {"R", "R Color Brewer Package", "R HMisc Package", "MySQL", "MySQL account", "Python 2.6", "Python DB", "S-MART"};
|
|
25
|
|
26 // Web addresses for the tools
|
|
27 String packageAddresses[][] = {
|
|
28 {"http://cran.cict.fr/bin/windows/base/R-2.11.0-win32.exe", "http://cran.cict.fr/bin/windows64/base/R-2.11.0-win64.exe"},
|
|
29 {"", ""},
|
|
30 {"", ""},
|
|
31 {"http://mirrors.ircam.fr/pub/mysql/Downloads/MySQL-5.1/mysql-essential-5.1.47-win32.msi", "http://mirrors.ircam.fr/pub/mysql/Downloads/MySQL-5.1/mysql-essential-5.1.47-winx64.msi"},
|
|
32 {"", ""},
|
|
33 {"http://www.python.org/ftp/python/2.6.5/python-2.6.5.msi", "http://www.python.org/ftp/python/2.6.5/python-2.6.5.amd64.msi"},
|
|
34 {"http://www.technicalbard.com/files/MySQL-python-1.2.2.win32-py2.6.exe", "http://www.technicalbard.com/files/MySQL-python-1.2.2.win32-py2.6.exe"},
|
|
35 {"http://urgi.versailles.inra.fr/download/s-mart/s-mart.zip", "http://urgi.versailles.inra.fr/download/s-mart/s-mart.zip"}
|
|
36 };
|
|
37
|
|
38 // Packages to install
|
|
39 String rPackages[] = {"RColorBrewer", "Hmisc"};
|
|
40
|
|
41 // Script lines
|
|
42 String scriptLines[][] = {
|
|
43 {"\"<INSTALLDIR>\\R-2.11.0-win32.exe\"", "\"<INSTALLDIR>\\R-2.11.0-win64.exe\""},
|
|
44 {"\"<RFILE>\" CMD BATCH \"<INSTALLDIR>\\installRColorBrewer.R\"", "\"<RFILE>\" CMD BATCH \"<INSTALLDIR>\\installRColorBrewer.R\""},
|
|
45 {"\"<RFILE>\" CMD BATCH \"<INSTALLDIR>\\installHmisc.R\"", "\"<RFILE>\" CMD BATCH \"<INSTALLDIR>\\installHmisc.R\""},
|
|
46 {"msiexec /i \"<INSTALLDIR>\\mysql-essential-5.1.47-win32.msi\"", "msiexec /i \"<INSTALLDIR>\\mysql-essential-5.1.47-winx64.msi\""},
|
|
47 {"", ""},
|
|
48 {"msiexec /i \"<INSTALLDIR>\\python-2.6.5.msi\"", "msiexec /i \"<INSTALLDIR>\\python-2.6.5.amd64.msi\""},
|
|
49 {"<INSTALLDIR>\\MySQL-python-1.2.2.win32-py2.6.exe", "<INSTALLDIR>\\MySQL-python-1.2.2.win32-py2.6.exe"},
|
|
50 {"", ""}
|
|
51 };
|
|
52
|
|
53 // Files to uncompress
|
|
54 String compressedFiles[][] = {
|
|
55 {"", ""},
|
|
56 {"", ""},
|
|
57 {"", ""},
|
|
58 {"", ""},
|
|
59 {"", ""},
|
|
60 {"", ""},
|
|
61 {"", ""},
|
|
62 {"<INSTALLDIR>\\s-mart.zip", "<INSTALLDIR>\\s-mart.zip"}
|
|
63 };
|
|
64
|
|
65
|
|
66 public SmartInstallerTask(JTextArea ta, boolean[] b, String s, int a) {
|
|
67 logArea = ta;
|
|
68 selectedPrograms = b;
|
|
69 installDirectoryName = s;
|
|
70 architecture = a;
|
|
71 }
|
|
72
|
|
73
|
|
74 @Override
|
|
75 public Boolean doInBackground() {
|
|
76 boolean installOk;
|
|
77 publish("Starting install\n");
|
|
78 writeFiles();
|
|
79 for (int i = 0; i < selectedPrograms.length; i++) {
|
|
80 if (selectedPrograms[i]) {
|
|
81 if (! install(i)) {
|
|
82 return Boolean.FALSE;
|
|
83 }
|
|
84 }
|
|
85 }
|
|
86 removeFiles();
|
|
87 setEnvironmentVariables();
|
|
88 publish("Ending install\n");
|
|
89 return Boolean.TRUE;
|
|
90 }
|
|
91
|
|
92
|
|
93 @Override
|
|
94 protected void process(List<String> chunks) {
|
|
95 for (String chunk: chunks) {
|
|
96 logArea.append(chunk);
|
|
97 }
|
|
98 }
|
|
99
|
|
100
|
|
101 private boolean launch(String command) {
|
|
102 return realLaunch(new ProcessBuilder(command), command);
|
|
103 }
|
|
104
|
|
105 private boolean launch(String[] command) {
|
|
106 return realLaunch(new ProcessBuilder(command), Arrays.toString(command));
|
|
107 }
|
|
108
|
|
109 private boolean realLaunch(ProcessBuilder pb, String command) {
|
|
110 BufferedReader outputReader;
|
|
111 pb = pb.redirectErrorStream(true);
|
|
112 Process process = null;
|
|
113 publish(" Starting command '" + command + "'\n");
|
|
114 try {
|
|
115 process = pb.start();
|
|
116 BufferedInputStream outputStream = new BufferedInputStream(process.getInputStream());
|
|
117 InputStream is = process.getInputStream();
|
|
118 InputStreamReader isr = new InputStreamReader(is);
|
|
119 outputReader = new BufferedReader(isr);
|
|
120 }
|
|
121 catch (Exception exception) {
|
|
122 publish(" !Process cannot be started (command is '" + command + "')!\n");
|
|
123 exception.printStackTrace();
|
|
124 return false;
|
|
125 }
|
|
126 if (outputReader == null) {
|
|
127 publish(" !Problem in the output of the command!\n");
|
|
128 return false;
|
|
129 }
|
|
130 else {
|
|
131 publish(" Output is:\n");
|
|
132 try {
|
|
133 publish(" ---\n");
|
|
134 String line;
|
|
135 while ((line = outputReader.readLine()) != null) {
|
|
136 publish(" " + line + "\r\n");
|
|
137 }
|
|
138 publish(" ---\n");
|
|
139 }
|
|
140 catch (IOException e) {
|
|
141 publish(" !Cannot get the output of the command!\n");
|
|
142 return false;
|
|
143 }
|
|
144 }
|
|
145 int exitValue = process.exitValue();
|
|
146 if (exitValue != 0) {
|
|
147 publish(" !Problem during the execution of the command '" + command + "'!\n");
|
|
148 return false;
|
|
149 }
|
|
150 publish(" Ending command '" + command + "'\n");
|
|
151 return true;
|
|
152 }
|
|
153
|
|
154
|
|
155 private File lookForFile(String fileName, String[] putativePlaces) {
|
|
156 publish(" Looking for file " + fileName + "\n");
|
|
157 for (String place: putativePlaces) {
|
|
158 File file = new File(place, fileName);
|
|
159 publish(" Look at " + file.getAbsolutePath() + "\n");
|
|
160 if (file.exists()) {
|
|
161 publish(" Found it in expected place " + file.getAbsolutePath() + "\n");
|
|
162 return file;
|
|
163 }
|
|
164 }
|
|
165 Stack<File> files = new Stack<File>();
|
|
166 files.push(new File("\\"));
|
|
167 while (! files.empty()) {
|
|
168 File file = files.pop();
|
|
169 for (File childFile: file.listFiles()) {
|
|
170 if (childFile.isDirectory()) {
|
|
171 files.push(childFile);
|
|
172 }
|
|
173 else {
|
|
174 if (fileName.compareToIgnoreCase(childFile.getName()) == 0) {
|
|
175 publish(" Found it in unexpected place " + childFile.getAbsolutePath() + "\n");
|
|
176 return childFile;
|
|
177 }
|
|
178 }
|
|
179 }
|
|
180 }
|
|
181 publish(" !Cannot file file '" + fileName + "'!\n");
|
|
182 return null;
|
|
183 }
|
|
184
|
|
185
|
|
186 private boolean writeFile(String fileName, String content) {
|
|
187 try {
|
|
188 FileWriter fw = new FileWriter(fileName);
|
|
189 BufferedWriter bw = new BufferedWriter(fw);
|
|
190 bw.write(content);
|
|
191 bw.close();
|
|
192 fw.close();
|
|
193 }
|
|
194 catch (Exception e) {
|
|
195 publish(" !Cannot write file '" + fileName + "'!\n");
|
|
196 return false;
|
|
197 }
|
|
198 return true;
|
|
199 }
|
|
200
|
|
201
|
|
202 private boolean removeFile(String fileName) {
|
|
203 File file = new File(fileName);
|
|
204 if (file.exists()) {
|
|
205 if (! file.delete()) {
|
|
206 publish(" !Cannot delete file '" + file.getAbsolutePath() + "'!\n");
|
|
207 return false;
|
|
208 }
|
|
209 }
|
|
210 return true;
|
|
211 }
|
|
212
|
|
213
|
|
214 private boolean writeFiles() {
|
|
215 for (String rPackage: rPackages) {
|
|
216 String fileName = installDirectoryName + File.separator + "install" + rPackage + ".R";
|
|
217 String content = "install.packages(\"" + rPackage + "\", repos = \"http://cran.cict.fr\", dependencies = TRUE)\n";
|
|
218 if (! writeFile(fileName, content)) {
|
|
219 publish(" !Cannot write file for R package '" + rPackage + "'!\n");
|
|
220 return false;
|
|
221 }
|
|
222 }
|
|
223 String fileName = installDirectoryName + File.separator + "createUser.sql";
|
|
224 String content = "CREATE USER 'smart'@'localhost';\nGRANT ALL PRIVILEGES ON *.* TO 'smart'@'localhost' WITH GRANT OPTION;\nCREATE DATABASE smart;\nGRANT ALL ON smart.* TO 'smart'@'localhost';\n";
|
|
225 if (! writeFile(fileName, content)) {
|
|
226 publish(" !Cannot write mySQL configuration file!\n");
|
|
227 return false;
|
|
228 }
|
|
229 return true;
|
|
230 }
|
|
231
|
|
232 private boolean removeFiles() {
|
|
233 for (String rPackage: rPackages) {
|
|
234 File file = new File(installDirectoryName + File.separator + "install" + rPackage + ".R");
|
|
235 if (! file.delete()) {
|
|
236 publish("!Cannot delete R install file for " + rPackage + "!\n");
|
|
237 return false;
|
|
238 }
|
|
239 }
|
|
240 File file = new File(installDirectoryName + File.separator + "createUser.sql");
|
|
241 if (! file.delete()) {
|
|
242 publish("!Cannot delete mySQL configuration file!\n");
|
|
243 return false;
|
|
244 }
|
|
245 return true;
|
|
246 }
|
|
247
|
|
248 private boolean install(int element) {
|
|
249 publish(" Starting install of " + programChoosers[element] + "\n");
|
|
250 downloadPackage(element);
|
|
251 executeInstall(element);
|
|
252 uncompressPackage(element);
|
|
253 removePackage(element);
|
|
254 postProcess(element);
|
|
255 publish(" Ending install of " + programChoosers[element] + "\n");
|
|
256 return true;
|
|
257 }
|
|
258
|
|
259
|
|
260 private String getLocalName(String remoteName) {
|
|
261 String localName = installDirectoryName + File.separator + (new File(remoteName)).getName();
|
|
262 int position = localName.indexOf("?");
|
|
263 if (position >= 0) {
|
|
264 localName = localName.substring(0, position);
|
|
265 }
|
|
266 return localName;
|
|
267 }
|
|
268
|
|
269
|
|
270 private boolean downloadPackage(int element) {
|
|
271 String fileName = packageAddresses[element][architecture];
|
|
272 if (! "".equals(fileName)) {
|
|
273 publish(" Starting download of " + programChoosers[element] + "\n");
|
|
274 try {
|
|
275 BufferedInputStream bis = new BufferedInputStream(new URL(fileName).openStream());
|
|
276 FileOutputStream fos = new FileOutputStream(getLocalName(fileName));
|
|
277 BufferedOutputStream bos = new BufferedOutputStream(fos, BUFFER);
|
|
278 byte[] data = new byte[BUFFER];
|
|
279 int x = 0;
|
|
280 while((x = bis.read(data, 0, BUFFER)) >= 0) {
|
|
281 bos.write(data, 0, x);
|
|
282 }
|
|
283 bos.close();
|
|
284 fos.close();
|
|
285 bis.close();
|
|
286 }
|
|
287 catch (IOException e) {
|
|
288 publish(" !Cannot download file '" + fileName + "'!\n");
|
|
289 return false;
|
|
290 }
|
|
291 publish(" Ending download of " + programChoosers[element] + "\n");
|
|
292 }
|
|
293 return true;
|
|
294 }
|
|
295
|
|
296
|
|
297 private String replaceSubstring(String line) {
|
|
298 if (line.contains("<INSTALLDIR>")) {
|
|
299 String protectedDirectory = installDirectoryName.replaceAll("\\\\", "\\\\\\\\");
|
|
300 line = line.replaceAll("<INSTALLDIR>", protectedDirectory);
|
|
301 }
|
|
302 if (line.contains("<RFILE>")) {
|
|
303 String userName = System.getenv().get("USERNAME");
|
|
304 String[] possibleRDirectories = {"C:\\Program Files\\R-2.11.0", "C:\\Documents and Settings\\" + userName + "\\Mes documents\\R\\R-2.11.0\\bin", "C:\\Documents and Settings\\" + userName + "\\My documents\\R\\R-2.11.0\\bin"};
|
|
305 String rDirectory = lookForFile("'.exe", possibleRDirectories).getAbsolutePath();
|
|
306 rDirectory = rDirectory.replaceAll("\\\\", "\\\\\\\\");
|
|
307 line = line.replaceAll("<RFILE>", rDirectory);
|
|
308 }
|
|
309 if (line.contains("<MYSQLFILE>")) {
|
|
310 String userName = System.getenv().get("USERNAME");
|
|
311 String[] possibleRDirectories = {"C:\\Program Files\\MySQL\\MySQL Server 5.1\\bin", "C:\\Documents and Settings\\" + userName + "\\Mes documents\\MySQL\\MySQL Server 5.1\\bin", "C:\\Documents and Settings\\" + userName + "\\My documents\\MySQL\\MySQL Server 5.1\\bin"};
|
|
312 String rDirectory = lookForFile("mysql.exe", possibleRDirectories).getAbsolutePath();
|
|
313 rDirectory = rDirectory.replaceAll("\\\\", "\\\\\\\\");
|
|
314 line = line.replaceAll("<MYSQLFILE>", rDirectory);
|
|
315 }
|
|
316 return line;
|
|
317 }
|
|
318
|
|
319
|
|
320 private boolean executeInstall(int element) {
|
|
321 String commands = scriptLines[element][architecture];
|
|
322 if (! "".equals(commands)) {
|
|
323 for (String command: commands.split(";")) {
|
|
324 command = replaceSubstring(command);
|
|
325 publish(" Starting command '" + command + "'\n");
|
|
326 Process process = null;
|
|
327 try {
|
|
328 process = Runtime.getRuntime().exec(command);
|
|
329 }
|
|
330 catch (IOException e) {
|
|
331 publish(" !Cannot execute command '" + command + "'!\n");
|
|
332 return false;
|
|
333 }
|
|
334 try {
|
|
335 process.waitFor();
|
|
336 }
|
|
337 catch (InterruptedException e) {
|
|
338 publish(" !Cannot wait for the end of the command '" + command + "'!\n");
|
|
339 return false;
|
|
340 }
|
|
341 int exitValue = process.exitValue();
|
|
342 if (exitValue != 0) {
|
|
343 publish(" !Problem during the execution of the command '" + command + "'!\n");
|
|
344 return false;
|
|
345 }
|
|
346 publish(" Ending command '" + command + "'\n");
|
|
347 }
|
|
348 }
|
|
349 return true;
|
|
350 }
|
|
351
|
|
352
|
|
353 private boolean uncompressPackage(int element) {
|
|
354 String file = compressedFiles[element][architecture];
|
|
355 if (! "".equals(file)) {
|
|
356 file = replaceSubstring(file);
|
|
357 publish(" Starting uncompressing file '" + file + "'\n");
|
|
358 try {
|
|
359 FileInputStream fis = new FileInputStream(file);
|
|
360 BufferedInputStream bis = new BufferedInputStream(fis);
|
|
361 ZipInputStream zis = new ZipInputStream(bis);
|
|
362 ZipEntry entry;
|
|
363 while ((entry = zis.getNextEntry()) != null) {
|
|
364 if (! entry.isDirectory()) {
|
|
365 File newFile = new File(installDirectoryName + File.separator + entry.getName());
|
|
366 // create parent directories
|
|
367 File upDirectory = newFile.getParentFile();
|
|
368 while (upDirectory != null){
|
|
369 if (! upDirectory.exists()) {
|
|
370 upDirectory.mkdir();
|
|
371 publish(" Creating directory '" + upDirectory.getAbsolutePath() + "'\n");
|
|
372 }
|
|
373 upDirectory = upDirectory.getParentFile();
|
|
374 }
|
|
375 // write the files to the disk
|
|
376 publish(" Extracting '" + entry.getName() + "' to '" + newFile.getAbsolutePath() + "'\n");
|
|
377 int count;
|
|
378 byte data[] = new byte[BUFFER];
|
|
379 FileOutputStream fos = new FileOutputStream(newFile);
|
|
380 BufferedOutputStream bos = new BufferedOutputStream(fos, BUFFER);
|
|
381 while ((count = zis.read(data, 0, BUFFER)) != -1){
|
|
382 bos.write(data, 0, count);
|
|
383 }
|
|
384 bos.flush();
|
|
385 bos.close();
|
|
386 fos.close();
|
|
387 }
|
|
388 }
|
|
389 zis.close();
|
|
390 bis.close();
|
|
391 fis.close();
|
|
392 }
|
|
393 catch(FileNotFoundException e) {
|
|
394 publish(" !Cannot find file '" + file + "'!\n");
|
|
395 return false;
|
|
396 }
|
|
397 catch(Exception e){
|
|
398 publish(" !Cannot uncompress file '" + file + "'!\n");
|
|
399 return false;
|
|
400 }
|
|
401 publish(" Ending uncompressing file '" + file + "'\n");
|
|
402 }
|
|
403 return true;
|
|
404 }
|
|
405
|
|
406
|
|
407 private boolean removePackage(int element) {
|
|
408 String packageName = packageAddresses[element][architecture];
|
|
409 if ("".equals(packageName)) {
|
|
410 return true;
|
|
411 }
|
|
412 String fileName = getLocalName(packageAddresses[element][architecture]);
|
|
413 return removeFile(fileName);
|
|
414 }
|
|
415
|
|
416
|
|
417 private boolean postProcess(int element) {
|
|
418 switch (element) {
|
|
419 case 4:
|
|
420 // Create mySQL user
|
|
421 PasswordAsker pa = new PasswordAsker();
|
|
422 if (! pa.waitForPassword()) {
|
|
423 publish("Problem in the password asker!\n");
|
|
424 return false;
|
|
425 }
|
|
426 String command = "\"<MYSQLFILE>\" --user=root --password=" + pa.getPassword() + " -e \"source <INSTALLDIR>\\createUser.sql\"";
|
|
427 command = replaceSubstring(command);
|
|
428 if (! launch(command)) {
|
|
429 publish(" !Cannot create SQL accounts!\n");
|
|
430 return false;
|
|
431 }
|
|
432 return true;
|
|
433 case 7:
|
|
434 // Move S-MART files to parent directory
|
|
435 File installDirectory = new File(installDirectoryName + File.separator + "S-Mart");
|
|
436 for (File file: installDirectory.listFiles()) {
|
|
437 File destinationFile = new File(file.getParentFile().getParentFile(), file.getName());
|
|
438 if (! file.renameTo(destinationFile)) {
|
|
439 publish(" !Cannot move '" + file.getAbsolutePath() + "' to '" + destinationFile.getAbsolutePath() + "'!\n");
|
|
440 }
|
|
441 }
|
|
442 if (! installDirectory.delete()) {
|
|
443 publish(" !Cannot remove installation S-MART directory '" + installDirectory.getAbsolutePath() + "'!\n");
|
|
444 }
|
|
445 }
|
|
446 return true;
|
|
447 }
|
|
448
|
|
449
|
|
450 private boolean setEnvironmentVariables() {
|
|
451 String[] command = {"REG", "ADD", "HKCU\\Environment", "/v", "PYTHONPATH", "/t", "REG_SZ", "/d", "\"" + installDirectoryName + "\\Python\"", "/f"};
|
|
452 return launch(command);
|
|
453 }
|
|
454 }
|
|
455
|