You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Main.java 54KB

21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
4 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886
  1. /* *******************************************************************
  2. * Copyright (c) 2000-2001 Xerox Corporation,
  3. * 2002 Palo Alto Research Center, Incorporated (PARC).
  4. * All rights reserved.
  5. * This program and the accompanying materials are made available
  6. * under the terms of the Eclipse Public License v 2.0
  7. * which accompanies this distribution and is available at
  8. * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
  9. *
  10. * Contributors:
  11. * Xerox/PARC initial implementation
  12. * ******************************************************************/
  13. package $installer$.org.aspectj;
  14. import java.awt.BorderLayout;
  15. import java.awt.Component;
  16. import java.awt.Dimension;
  17. import java.awt.FlowLayout;
  18. import java.awt.Font;
  19. import java.awt.GridBagConstraints;
  20. import java.awt.GridBagLayout;
  21. import java.awt.Toolkit;
  22. import java.awt.event.ActionEvent;
  23. import java.awt.event.ActionListener;
  24. import java.awt.event.WindowAdapter;
  25. import java.awt.event.WindowEvent;
  26. import java.awt.event.WindowListener;
  27. import java.io.BufferedOutputStream;
  28. import java.io.BufferedReader;
  29. import java.io.BufferedWriter;
  30. import java.io.File;
  31. import java.io.FileInputStream;
  32. import java.io.FileOutputStream;
  33. import java.io.FileWriter;
  34. import java.io.IOException;
  35. import java.io.InputStream;
  36. import java.io.InputStreamReader;
  37. import java.io.OutputStream;
  38. import java.io.PrintStream;
  39. import java.lang.reflect.InvocationTargetException;
  40. import java.net.JarURLConnection;
  41. import java.net.URL;
  42. import java.util.Enumeration;
  43. import java.util.Map;
  44. import java.util.Properties;
  45. import java.util.jar.JarEntry;
  46. import java.util.jar.JarFile;
  47. import java.util.zip.ZipEntry;
  48. import java.util.zip.ZipInputStream;
  49. import javax.swing.BorderFactory;
  50. import javax.swing.BoxLayout;
  51. import javax.swing.Icon;
  52. import javax.swing.JButton;
  53. import javax.swing.JEditorPane;
  54. import javax.swing.JFileChooser;
  55. import javax.swing.JFrame;
  56. import javax.swing.JLabel;
  57. import javax.swing.JOptionPane;
  58. import javax.swing.JPanel;
  59. import javax.swing.JProgressBar;
  60. import javax.swing.JTextArea;
  61. import javax.swing.JTextField;
  62. import javax.swing.SwingUtilities;
  63. import javax.swing.border.Border;
  64. import javax.swing.border.CompoundBorder;
  65. import javax.swing.border.EmptyBorder;
  66. /**
  67. * Invoke the Installer gui. There are two ways to run without GUI by passing parameters to main:
  68. * <ol>
  69. * <li>pass <code>-text {pathToPropertiesFile}</code>:
  70. * <ul>
  71. * <li>"-text".equals(arg[0])</li>
  72. * <li>arg[1] is the path to a properties file which defines name="output.dir" value="{path to output dir}" name="context.javaPath"
  73. * value="{path to JDKDIR}", i.e,.
  74. *
  75. * <pre>
  76. * output.dir=c:/latest
  77. * "context.javaPath=c:/apps/jdk1.3.1
  78. * </pre>
  79. *
  80. * </li>
  81. * <li>outputDir must be created and empty (i.e., no overwriting</li>
  82. * <li>the VM being invoked should be the target vm</li>
  83. * </ul>
  84. * </li>
  85. * <li>pass <code>-to {pathToTargetDir}</code>:
  86. * <ul>
  87. * <li>"-to".equals(arg[0])</li>
  88. * <li>arg[1] is the path to a writable install directory.</li>
  89. * </ul>
  90. * </li>
  91. */
  92. public class Main {
  93. public static void main(String[] args) {
  94. Options.loadArgs(args);
  95. boolean hasGui = true;
  96. Properties properties = new Properties();
  97. InputStream istream = null;
  98. try {
  99. istream = Main.class.getResourceAsStream(Installer.RESOURCE_DIR + "/properties.txt");
  100. if (istream == null) {
  101. System.err.println("unable to load properties.txt using Main.class - exiting");
  102. Main.exit(-1);
  103. }
  104. properties.load(istream);
  105. // when running outside GUI, load values into properties
  106. // so that property-value resolution works
  107. // (otherwise, could just set values below).
  108. // XXX not sure if this indirection is actually needed.
  109. if (null != Options.textProperties) {
  110. istream.close();
  111. istream = new FileInputStream(Options.textProperties);
  112. properties.load(istream);
  113. hasGui = false;
  114. } else if (null != Options.targetDir) {
  115. String path = null;
  116. try {
  117. path = Options.targetDir.getCanonicalPath();
  118. } catch (IOException e) {
  119. path = Options.targetDir.getAbsolutePath();
  120. }
  121. String javaPath = ConfigureLauncherPane.getDefaultJavaHomeLocation();
  122. if (null == javaPath) {
  123. System.err.println("using GUI - unable to find java");
  124. } else {
  125. properties.setProperty("output.dir", path);
  126. properties.setProperty("context.javaPath", javaPath);
  127. hasGui = false;
  128. }
  129. }
  130. } catch (IOException ioe) {
  131. handleException(ioe);
  132. } finally {
  133. if (null != istream) {
  134. try {
  135. istream.close();
  136. } catch (IOException e) {
  137. } // ignore
  138. }
  139. }
  140. try {
  141. String className = (String) properties.get("installer.main.class");
  142. //UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
  143. Installer installer = (Installer) Class.forName(className).getDeclaredConstructor().newInstance();
  144. InstallContext installerContext = new InstallContext(properties);
  145. installerContext.setHasGui(hasGui);
  146. installer.setContext(installerContext);
  147. if (installerContext.hasGui()) { // let context force whether or not to run gui
  148. installer.runGUI();
  149. } else {
  150. // set output dir and java path in context after minimal validation
  151. String propName = "output.dir";
  152. String propValue = properties.getProperty(propName);
  153. if (null == propValue) {
  154. throw new Exception("expecting property " + propName);
  155. }
  156. String outputDirName = propValue;
  157. propName = "context.javaPath";
  158. propValue = properties.getProperty(propName);
  159. if (null == propValue) {
  160. throw new Exception("expecting property " + propName);
  161. }
  162. String javaPath = propValue;
  163. File outputDir = new File(outputDirName);
  164. if (!outputDir.isDirectory()) {
  165. throw new Exception("not a dir outputDirName: " + outputDirName + " dir: " + outputDir);
  166. }
  167. if (!outputDir.canWrite()) {
  168. throw new Exception("cannot write outputDirName: " + outputDirName + " dir: " + outputDir);
  169. }
  170. InstallContext context = installer.getContext(); // todo: why not use installerContext?
  171. context.setOutputDir(outputDir);
  172. context.javaPath = new File(javaPath);
  173. // todo: check javaPath for ... bin/java? lib/rt.jar?
  174. if (!outputDir.isDirectory() || !outputDir.canRead()) {
  175. throw new Exception("invalid javaPath: " + javaPath);
  176. }
  177. // directly set context and run
  178. WizardPane.setContext(installerContext);
  179. installer.run();
  180. }
  181. } catch (Exception e) {
  182. handleException(e);
  183. }
  184. }
  185. public static void handleException(Throwable e) {
  186. System.out.println("internal error: " + e.toString());
  187. e.printStackTrace();
  188. Main.exit(-1);
  189. }
  190. /** indirection for System.exit - todo apply cleanup here as necessary */
  191. public static void exit(int value) {
  192. System.exit(value);
  193. }
  194. } // class Main
  195. class Options {
  196. public static boolean verbose = false;
  197. public static String textProperties = null;
  198. public static File targetDir = null;
  199. public static boolean forceError1 = false;
  200. public static boolean forceError2 = false;
  201. public static boolean forceHandConfigure = false;
  202. public static void loadArgs(String[] args) {
  203. if (args == null) {
  204. return;
  205. }
  206. for (int i = 0; i < args.length; i++) {
  207. String arg = args[i];
  208. if (arg == null) {
  209. continue;
  210. }
  211. if (arg.equals("-verbose")) {
  212. verbose = true;
  213. } else if (arg.equals("-forceError1")) {
  214. forceError1 = true;
  215. } else if (arg.equals("-forceError2")) {
  216. forceError2 = true;
  217. } else if (arg.equals("-forceHandConfigure")) {
  218. forceHandConfigure = true;
  219. } else if (arg.equals("-text")) {
  220. if (i + 1 < args.length) {
  221. textProperties = args[++i];
  222. }
  223. } else if (arg.equals("-to")) {
  224. String next = "no argument";
  225. if (i + 1 < args.length) {
  226. next = args[++i];
  227. File targDir = new File(next);
  228. if (targDir.isDirectory() && targDir.canWrite()) {
  229. targetDir = targDir;
  230. }
  231. }
  232. if (null == targetDir) {
  233. System.err.println("invalid -to dir: " + next);
  234. }
  235. }
  236. }
  237. }
  238. }
  239. /** tools installer installs the entire 1.1+ distribution */
  240. class ToolsInstaller extends Installer {
  241. public String getTitle() {
  242. return "Installer for AspectJ(TM)";
  243. }
  244. public String getPrefix() {
  245. return "tools";
  246. }
  247. public String getReadmeFilename() {
  248. return "README-AspectJ.html";
  249. }
  250. public ToolsInstaller() {
  251. InstallPane installPane = new InstallPane(true);
  252. setInstallPane(installPane);
  253. panes = new WizardPane[] { new IntroPane(), new ConfigureLauncherPane(), new LocationPane(), installPane, new FinishPane() };
  254. }
  255. }
  256. class DocsInstaller extends Installer {
  257. public String getTitle() {
  258. return "AspectJ(TM) Documentation and Examples Installer";
  259. }
  260. public String getPrefix() {
  261. return "docs";
  262. }
  263. public DocsInstaller() {
  264. InstallPane installPane = new InstallPane(false);
  265. setInstallPane(installPane);
  266. panes = new WizardPane[] { new IntroPane(), new LocationPane(), installPane, new FinishPane() };
  267. }
  268. }
  269. class AJDEForJBuilderInstaller extends Installer {
  270. public String getTitle() {
  271. return "AspectJ(TM) Support for JBuilder";
  272. }
  273. public String getPrefix() {
  274. return "ajdeForJBuilder";
  275. }
  276. public AJDEForJBuilderInstaller() {
  277. InstallPane installPane = new InstallPane(false);
  278. setInstallPane(installPane);
  279. panes = new WizardPane[] { new IntroPane(), new LocationPane() {
  280. public String getDefaultLocation() {
  281. if (context.onWindows()) {
  282. // check some default locations
  283. String[] paths = { "c:\\JBuilder6\\lib\\ext", "c:\\apps\\JBuilder6\\lib\\ext",
  284. "c:\\Program Files\\JBuilder6\\lib\\ext" };
  285. int pathIndex = 0;
  286. for (; pathIndex < paths.length; pathIndex++) {
  287. if (new File(paths[pathIndex]).exists()) {
  288. return paths[pathIndex];
  289. }
  290. }
  291. return "c:\\JBuilder6\\lib\\ext";
  292. } else {
  293. return "/usr/JBuilder6/lib/ext";
  294. }
  295. }
  296. /**
  297. * Make sure that the old jar file gets removed.
  298. */
  299. public void verify() {
  300. File jbuilder = new File(location.getText() + "/../../lib/jbuilder.jar");
  301. if (!jbuilder.exists() && hasGui()) {
  302. int ret = JOptionPane.showConfirmDialog(frame, "The location you specified does not seem to be a "
  303. + "valid JBuilder install directory." + " Continue?", "Confirm Install", JOptionPane.YES_NO_OPTION,
  304. JOptionPane.QUESTION_MESSAGE);
  305. if (ret != JOptionPane.YES_OPTION) {
  306. Main.exit(-1);
  307. } else {
  308. // do nothing
  309. }
  310. }
  311. File oldFile = new File(location.getText() + "/ajbuilder.jar");
  312. if (oldFile.exists() && hasGui()) {
  313. int ret = JOptionPane.showConfirmDialog(frame,
  314. "This old version of AJDE for JBuilder (\"ajbuilder.jar\") exists"
  315. + " and must be removed from the install directory." + " OK to delete?", "Confirm Delete",
  316. JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
  317. if (ret != JOptionPane.YES_OPTION) {
  318. Main.exit(-1);
  319. } else {
  320. oldFile.delete();
  321. }
  322. }
  323. }
  324. }, installPane, new FinishPane() };
  325. }
  326. }
  327. class AJDEForForteInstaller extends Installer {
  328. public String getTitle() {
  329. return "AspectJ(TM) Support for Forte 4J";
  330. }
  331. public String getPrefix() {
  332. return "ajdeForForte";
  333. }
  334. private String installLoc = "";
  335. public AJDEForForteInstaller() {
  336. InstallPane installPane = new InstallPane(false);
  337. setInstallPane(installPane);
  338. panes = new WizardPane[] { new IntroPane(), new LocationPane() {
  339. public String getDefaultLocation() {
  340. if (context.onWindows()) {
  341. // check some default locations
  342. String[] paths = { "c:\\forte4j\\modules", "c:\\apps\\forte4j\\modules", "c:\\Program Files\\forte4j\\modules" };
  343. int pathIndex = 0;
  344. for (; pathIndex < paths.length; pathIndex++) {
  345. if (new File(paths[pathIndex]).exists()) {
  346. return paths[pathIndex];
  347. }
  348. }
  349. return "c:\\forte4j\\modules";
  350. } else {
  351. return "/usr/forte4j/modules";
  352. }
  353. }
  354. public void verify() {
  355. File forte = new File(location.getText() + "/../lib/openide.jar");
  356. installLoc = location.getText();
  357. if (!forte.exists() && hasGui()) {
  358. int ret = JOptionPane.showConfirmDialog(frame, "The location you specified does not seem to be a "
  359. + "valid Forte install directory." + " Continue?", "Confirm Install", JOptionPane.YES_NO_OPTION,
  360. JOptionPane.QUESTION_MESSAGE);
  361. if (ret != JOptionPane.YES_OPTION) {
  362. Main.exit(-1);
  363. } else {
  364. // do nothing
  365. }
  366. }
  367. }
  368. }, installPane, new FinishPane() {
  369. public void finalActions() { // todo verify dir ../lib/ext exists?
  370. // !!! this should be done with two install locations, not by moving a file
  371. new File(installLoc + "/../lib/ext/aspectjrt.jar").delete();
  372. new File(installLoc + "/aspectjrt.jar").renameTo(new File((installLoc + "/../lib/ext/aspectjrt.jar")));
  373. new File(installLoc + "/aspectjrt.jar").delete();
  374. }
  375. } };
  376. }
  377. }
  378. class SrcInstaller extends Installer {
  379. public String getTitle() {
  380. return "AspectJ(TM) Compiler and Core Tools Sources Installer";
  381. }
  382. public String getPrefix() {
  383. return "sources";
  384. }
  385. public SrcInstaller() {
  386. InstallPane installPane = new InstallPane(false);
  387. setInstallPane(installPane);
  388. panes = new WizardPane[] { new IntroPane(), new LocationPane(), installPane, new FinishPane() };
  389. }
  390. }
  391. abstract class Installer {
  392. static final String EXIT_MESSAGE = "Are you sure you want to cancel the installation?";
  393. static final String EXIT_TITLE = "Exiting installer";
  394. /**
  395. * relative directory in jar from package $installer$.org.aspectj for loading resources - todo must be tracked during build
  396. */
  397. public static final String RESOURCE_DIR = "resources";
  398. JFrame frame;
  399. InstallContext context;
  400. /** special pane that actually does the installation */
  401. InstallPane installPane;
  402. public Installer() {
  403. }
  404. protected void setInstallPane(InstallPane installPane) {
  405. this.installPane = installPane;
  406. }
  407. public InstallPane getInstallPane() {
  408. return installPane;
  409. }
  410. /** directly run the install pane, if any */
  411. public void run() {
  412. if (null != installPane) {
  413. installPane.run();
  414. }
  415. }
  416. public abstract String getPrefix();
  417. public String getReadmeFilename() {
  418. return "README-" + getPrefix().toUpperCase() + ".html";
  419. }
  420. public void setContext(InstallContext context) {
  421. this.context = context;
  422. context.installer = this;
  423. }
  424. public InstallContext getContext() {
  425. return context;
  426. }
  427. public String getTitle() {
  428. return "AspectJ(TM) Installer";
  429. }
  430. public int getWidth() {
  431. return 640;
  432. }
  433. public int getHeight() {
  434. return 460;
  435. }
  436. protected WizardPane[] panes = new WizardPane[0];
  437. public WizardPane[] getPanes() {
  438. return panes;
  439. }
  440. public int findPaneIndex(WizardPane pane) {
  441. for (int i = 0; i < panes.length; i++) {
  442. if (panes[i] == pane) {
  443. return i;
  444. }
  445. }
  446. return -1;
  447. }
  448. Component header, footer, body;
  449. public void runGUI() {
  450. frame = new JFrame(getTitle());
  451. WindowListener wl = new WindowAdapter() {
  452. public void windowClosing(WindowEvent arg0) {
  453. Main.exit(-1); // -1 unless exiting through done button
  454. }
  455. };
  456. frame.addWindowListener(wl);
  457. if (Options.forceError1) {
  458. throw new RuntimeException("forced error1 for testing purposes");
  459. }
  460. Dimension size = Toolkit.getDefaultToolkit().getScreenSize();
  461. int x = (int) (size.getWidth() - getWidth()) / 2;
  462. int y = (int) (size.getHeight() - getHeight()) / 2;
  463. //include a few sanity checks on starting position
  464. if (x < 0) {
  465. x = 0;
  466. }
  467. if (x > 600) {
  468. x = 600;
  469. }
  470. if (y < 0) {
  471. y = 0;
  472. }
  473. if (y > 400) {
  474. y = 400;
  475. }
  476. frame.setLocation(x, y);
  477. frame.setSize(getWidth(), getHeight());
  478. moveToPane(getPanes()[0]);
  479. frame.setVisible(true);
  480. }
  481. public void moveToPane(WizardPane pane) {
  482. WizardPane.setContext(this.context);
  483. Dimension size = frame.getContentPane().getSize();
  484. JPanel contents = new JPanel();
  485. contents.setLayout(new BorderLayout());
  486. header = makeHeader();
  487. contents.add(header, BorderLayout.NORTH);
  488. body = pane.getPanel();
  489. contents.add(body, BorderLayout.CENTER);
  490. footer = pane.getButtons();
  491. contents.add(footer, BorderLayout.SOUTH);
  492. contents.revalidate();
  493. contents.setSize(size);
  494. frame.setContentPane(contents);
  495. //XXX deal with threading here?
  496. pane.run();
  497. }
  498. public Icon loadImage(String name) {
  499. return new javax.swing.ImageIcon(this.getClass().getResource(name));
  500. }
  501. public Component makeHeader() {
  502. return new JLabel(loadImage(Installer.RESOURCE_DIR + "/aspectjBanner.gif"));
  503. }
  504. public ActionListener makeNextAction(final WizardPane pane) {
  505. int nextPaneIndex = findPaneIndex(pane) + 1;
  506. if (nextPaneIndex >= getPanes().length) {
  507. return null;
  508. }
  509. final WizardPane nextPane = getPanes()[nextPaneIndex];
  510. return new ActionListener() {
  511. public void actionPerformed(ActionEvent e) {
  512. pane.finish();
  513. moveToPane(nextPane);
  514. }
  515. };
  516. }
  517. public ActionListener makeBackAction(final WizardPane pane) {
  518. int nextPaneIndex = findPaneIndex(pane) - 1;
  519. if (nextPaneIndex < 0) {
  520. return null;
  521. }
  522. final WizardPane nextPane = getPanes()[nextPaneIndex];
  523. return new ActionListener() {
  524. public void actionPerformed(ActionEvent e) {
  525. moveToPane(nextPane);
  526. }
  527. };
  528. }
  529. public ActionListener makeCancelAction(WizardPane pane) {
  530. return new ActionListener() {
  531. public void actionPerformed(ActionEvent e) {
  532. int ret = JOptionPane.showConfirmDialog(frame, EXIT_MESSAGE, EXIT_TITLE, JOptionPane.YES_NO_OPTION,
  533. JOptionPane.QUESTION_MESSAGE);
  534. if (ret == JOptionPane.YES_OPTION) {
  535. Main.exit(-1);
  536. }
  537. }
  538. };
  539. }
  540. public ActionListener makeFinishAction(WizardPane pane) {
  541. return new ActionListener() {
  542. public void actionPerformed(ActionEvent e) {
  543. Main.exit(0);
  544. }
  545. };
  546. }
  547. }
  548. // willing to go up to 3 levels deep to find either jre or jdk
  549. // jre\[*\]lib\ext
  550. // jdk*\lib\tools.jar
  551. /*****
  552. * final static int MAX_DEPTH = 4; public static void findPaths(String prefix, File currentDir, int currentDepth) { if (currentDepth
  553. * > MAX_DEPTH) return; if (!currentDir.exists() || !currentDir.isDirectory()) return; File [] files = currentDir.listFiles(); if
  554. * (files == null) return; for (int i=0; i<files.length; i++) { if (files[i] == null) continue; if (!files[i].isDirectory())
  555. * continue; if (files[i].getName().startsWith(prefix)) { System.out.println("found: " + files[i]); } else { findPaths(prefix,
  556. * files[i], currentDepth + 1); } } }
  557. *
  558. * public static void findPaths(String prefix) { File [] files = File.listRoots(); for (int i=1; i<files.length; i++) { if
  559. * (!files[i].isDirectory()) continue; if (files[i].getName().toLowerCase().startsWith(prefix)) { System.out.println("found: " +
  560. * files[i]); } else { findPaths(prefix, files[i], 1); } } }
  561. *****/
  562. class InstallContext {
  563. public InstallContext(Map properties) {
  564. this.properties = properties;
  565. properties.put("user.home", System.getProperty("user.home"));
  566. //System.out.println("new install context");
  567. }
  568. private File outputDir;
  569. public void setOutputDir(File outputDir) {
  570. this.outputDir = outputDir;
  571. properties.put("installer.output.dir", outputDir.getAbsolutePath());
  572. properties.put("installer.output.dir.bin", new File(outputDir, "bin").getAbsolutePath());
  573. properties.put("installer.output.dir.doc", new File(outputDir, "doc").getAbsolutePath());
  574. properties.put("installer.output.aspectjrt", new File(new File(outputDir, "lib"), "aspectjrt.jar").getAbsolutePath());
  575. properties.put("installer.output.readme", new File(outputDir, installer.getReadmeFilename()).getAbsolutePath());
  576. }
  577. public File getOutputDir() {
  578. return outputDir;
  579. }
  580. private boolean hasGui;
  581. public File javaPath;
  582. public File toolsJarPath;
  583. public Installer installer;
  584. private Map<String,String> properties;
  585. public boolean hasGui() {
  586. return hasGui;
  587. }
  588. public void setHasGui(boolean hasGui) {
  589. if (this.hasGui != hasGui) {
  590. this.hasGui = hasGui;
  591. }
  592. }
  593. public Font getFont() {
  594. return new Font("Serif", Font.PLAIN, 14);
  595. }
  596. public String getOS() {
  597. return System.getProperty("os.name");
  598. }
  599. public boolean onOS2() {
  600. return getOS().equals("OS2") || getOS().equals("OS/2");
  601. }
  602. public boolean onWindows() {
  603. return getOS().startsWith("Windows") || onOS2();
  604. }
  605. public boolean onWindowsPro() {
  606. // TODO: Think about a more future-proof solution also checking 'os.version' system property. See also this table:
  607. // https://github.com/openjdk/jdk/blob/9604ee82690f89320614b37bfef4178abc869777/src/java.base/windows/native/libjava/java_props_md.c#L446
  608. // Alternatively, explicitly exclude unsupported versions because those won't change in the future.
  609. return getOS().matches("^Windows (NT|2000|XP|Vista|Server|7|8|10).*");
  610. }
  611. public boolean onMacintosh() {
  612. return getOS().startsWith("Mac");
  613. }
  614. public boolean onUnix() {
  615. return !onWindows();
  616. }
  617. static final String[] TEXT_EXTENSIONS = { ".txt", ".text", ".htm", ".html", ".java", ".ajava", "README", ".lst" };
  618. public boolean isTextFile(File file) {
  619. String name = file.getName();
  620. for (String textExtension : TEXT_EXTENSIONS) {
  621. if (name.endsWith(textExtension)) {
  622. return true;
  623. }
  624. }
  625. return false;
  626. }
  627. public void handleException(Throwable e) {
  628. System.out.println("internal error: " + e.toString());
  629. e.printStackTrace();
  630. if (hasGui()) {
  631. JOptionPane.showMessageDialog(installer.frame, e.toString(), "Unexpected Exception", JOptionPane.ERROR_MESSAGE);
  632. }
  633. }
  634. final static String OVERWRITE_MESSAGE = "Overwrite file ";
  635. final static String OVERWRITE_TITLE = "Overwrite?";
  636. final static String[] OVERWRITE_OPTIONS = { "Yes", "No", "Yes to all" //, "No to all"
  637. };
  638. final static int OVERWRITE_YES = 0;
  639. final static int OVERWRITE_NO = 1;
  640. final static int OVERWRITE_ALL = 2;
  641. //final static int OVERWRITE_NONE = 3;
  642. int overwriteState = OVERWRITE_NO;
  643. boolean shouldOverwrite(final File file) {
  644. //System.out.println("overwrite: " + file + " state " + overwriteState);
  645. if (overwriteState == OVERWRITE_ALL) {
  646. return true;
  647. //if (overwriteState == OVERWRITE_NONE) return false;
  648. }
  649. try {
  650. SwingUtilities.invokeAndWait(new Runnable() {
  651. public void run() {
  652. int ret = JOptionPane.showOptionDialog(installer.frame, OVERWRITE_MESSAGE + file.getPath(), OVERWRITE_TITLE,
  653. JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, OVERWRITE_OPTIONS,
  654. OVERWRITE_OPTIONS[OVERWRITE_YES]);
  655. overwriteState = ret;
  656. }
  657. });
  658. } catch (InvocationTargetException ite) {
  659. handleException(ite.getTargetException());
  660. } catch (InterruptedException ie) {
  661. }
  662. return overwriteState == OVERWRITE_YES || overwriteState == OVERWRITE_ALL;
  663. }
  664. public Map<String,String> getProperties() {
  665. return properties;
  666. }
  667. }
  668. abstract class WizardPane {
  669. static InstallContext context;
  670. protected JButton backButton = null;
  671. protected JButton nextButton = null;
  672. protected JButton cancelButton = null;
  673. public static void setContext(InstallContext con) {
  674. context = con;
  675. }
  676. public abstract JPanel makePanel();
  677. protected JTextArea makeTextArea(String data) {
  678. JTextArea text = new JTextArea(data);
  679. text.setOpaque(false);
  680. text.setFont(context.getFont());
  681. text.setEditable(false);
  682. return text;
  683. }
  684. /** @return false only if there is an InstallContext saying there is no GUI */
  685. protected boolean hasGui() {
  686. final InstallContext icontext = context;
  687. return ((null == icontext) || icontext.hasGui());
  688. }
  689. public static String stringFromStream(InputStream stream) throws IOException {
  690. BufferedReader reader = new BufferedReader(new InputStreamReader(stream, "US-ASCII"));
  691. StringBuilder ret = new StringBuilder();
  692. int data;
  693. while ((data = reader.read()) != -1) {
  694. ret.append((char) data);
  695. }
  696. return ret.toString();
  697. }
  698. public static String removeHead(String text) {
  699. int startIndex = text.indexOf("<head>");
  700. int stopIndex = text.indexOf("</head>");
  701. if (startIndex == -1 || stopIndex == -1) {
  702. return text;
  703. }
  704. stopIndex += 7;
  705. return text.substring(0, startIndex) + text.substring(stopIndex);
  706. }
  707. static String styleHeader = "<head></head>";/*
  708. * <STYLE TYPE=\"text/css\"><!--\n" + " h2 {\n" + " font-size: x-large;\n" +
  709. * " font-family: Serif;\n" + " font-weight: normal;\n" + " }\n" + " p {\n" +
  710. * " font-family: Serif;\n" + " font-weight: normal;\n" + //" color:black;\n"
  711. * + "}</head>\n";
  712. */
  713. public static String applyProperties(String text, Map<String,String> map) {
  714. // ${name} -> map.get(name).toString()
  715. int lastIndex = 0;
  716. StringBuilder buf = new StringBuilder();
  717. int startIndex;
  718. while ((startIndex = text.indexOf("${", lastIndex)) != -1) {
  719. int endIndex = text.indexOf('}', startIndex);
  720. //XXX internal error here
  721. if (endIndex == -1) {
  722. break;
  723. }
  724. buf.append(text.substring(lastIndex, startIndex));
  725. String key = text.substring(startIndex + 2, endIndex);
  726. lastIndex = endIndex + 1;
  727. Object replaceText = (map == null ? null : map.get(key));
  728. //System.out.println("key: " + key + " -> " + replaceText);
  729. if (replaceText == null) {
  730. replaceText = "NOT_FOUND";
  731. }
  732. buf.append(replaceText.toString());
  733. }
  734. buf.append(text.substring(lastIndex));
  735. return buf.toString();
  736. }
  737. public static String applyProperties(String text) {
  738. return applyProperties(text, (context == null ? null : context.getProperties()));
  739. }
  740. protected String loadText(String filename) {
  741. String fullname = Installer.RESOURCE_DIR + "/" + filename;
  742. //context.installer.getPrefix() + "-" + filename;
  743. try {
  744. String text = stringFromStream(getClass().getResourceAsStream(fullname));
  745. text = styleHeader + removeHead(text);
  746. text = applyProperties(text);
  747. //System.out.println(text);
  748. return text;
  749. } catch (IOException e) {
  750. context.handleException(e);
  751. return "";
  752. }
  753. }
  754. protected JEditorPane makeHTMLArea(String filename) {
  755. JEditorPane editorPane = new JEditorPane("text/html", loadText(filename));
  756. /*
  757. * { public void paint(Graphics g) { Graphics2D g2 = (Graphics2D)g; g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
  758. * RenderingHints.VALUE_ANTIALIAS_ON); super.paint(g2); } };
  759. */
  760. editorPane.setEditable(false);
  761. editorPane.setOpaque(false);
  762. return editorPane;
  763. }
  764. protected void setHTMLArea(JEditorPane pane, String filename) {
  765. pane.setText(loadText(filename));
  766. }
  767. protected JPanel makeLocationBox(String label, JTextField textField, JButton browseButton) {
  768. JPanel box = new JPanel();
  769. box.setLayout(new BoxLayout(box, BoxLayout.X_AXIS));
  770. textField.setFont(context.getFont());
  771. textField.selectAll();
  772. box.add(textField);
  773. box.add(browseButton);
  774. Border border = BorderFactory.createTitledBorder(label);
  775. final int INSET = 8;
  776. border = new CompoundBorder(border, new EmptyBorder(1, INSET, INSET, INSET));
  777. box.setBorder(border);
  778. return box;
  779. }
  780. private JPanel panel = null;
  781. public JPanel getPanel() {
  782. if (panel == null) {
  783. panel = makePanel();
  784. panel.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 10));
  785. }
  786. return panel;
  787. }
  788. protected void setListener(JButton button, ActionListener listener) {
  789. if (listener == null) {
  790. button.setEnabled(false);
  791. } else {
  792. button.addActionListener(listener);
  793. }
  794. }
  795. protected Component makeButtons(Installer installer) {
  796. JPanel panel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
  797. backButton = new JButton("Back");
  798. setListener(backButton, installer.makeBackAction(this));
  799. panel.add(backButton);
  800. nextButton = new JButton("Next");
  801. setListener(nextButton, installer.makeNextAction(this));
  802. panel.add(nextButton); //.setDefaultCapable(true);
  803. JLabel space = new JLabel();
  804. space.setPreferredSize(new Dimension(20, 0));
  805. panel.add(space);
  806. cancelButton = new JButton("Cancel");
  807. setListener(cancelButton, installer.makeCancelAction(this));
  808. panel.add(cancelButton);
  809. return panel;
  810. }
  811. private Component buttons = null;
  812. public Component getButtons() {
  813. if (buttons == null) {
  814. buttons = makeButtons(context.installer);
  815. //buttons.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 10));
  816. }
  817. context.installer.frame.getRootPane().setDefaultButton(nextButton);
  818. return buttons;
  819. }
  820. public void finish() {
  821. if (Options.forceError2) {
  822. throw new RuntimeException("forced error2 for testing purposes");
  823. }
  824. }
  825. public void run() {
  826. }
  827. }
  828. class IntroPane extends WizardPane {
  829. public JPanel makePanel() {
  830. Component text = makeHTMLArea("intro.html");
  831. JPanel panel = new JPanel(new BorderLayout());
  832. panel.add(text);
  833. return panel;
  834. }
  835. }
  836. class FinishPane extends WizardPane {
  837. public JPanel makePanel() {
  838. Component text = makeHTMLArea("finish.html");
  839. JPanel panel = new JPanel(new BorderLayout());
  840. panel.add(text);
  841. finalActions();
  842. return panel;
  843. }
  844. public Component makeButtons(Installer installer) {
  845. Component ret = super.makeButtons(installer);
  846. nextButton.setText("Finish");
  847. nextButton.setEnabled(true);
  848. nextButton.addActionListener(installer.makeFinishAction(this));
  849. backButton.setEnabled(false);
  850. cancelButton.setEnabled(false);
  851. return ret;
  852. }
  853. public void finalActions() {
  854. }
  855. }
  856. class LocationPane extends WizardPane implements ActionListener {
  857. //XXX need more sophisticated default location finding
  858. //XXX would like to find the place they last chose...
  859. public String getDefaultLocation() {
  860. if (context.onWindows()) {
  861. return "c:\\aspectj1.9";
  862. } else {
  863. return new File(System.getProperty("user.home"), "aspectj1.9").getAbsolutePath();
  864. }
  865. }
  866. protected JTextField location;
  867. public JPanel makePanel() {
  868. Component text = makeHTMLArea("location.html");
  869. location = new JTextField(getDefaultLocation());
  870. JButton browse = new JButton("Browse...");
  871. browse.addActionListener(this);
  872. JPanel locationBox = makeLocationBox("installation directory", location, browse);
  873. GridBagLayout bag = new GridBagLayout();
  874. GridBagConstraints c = new GridBagConstraints();
  875. JPanel panel = new JPanel(bag);
  876. c.fill = GridBagConstraints.BOTH;
  877. c.weightx = 1.0;
  878. c.gridwidth = GridBagConstraints.REMAINDER;
  879. bag.setConstraints(text, c);
  880. panel.add(text);
  881. c.weighty = 1.0;
  882. c.fill = GridBagConstraints.HORIZONTAL;
  883. c.gridwidth = GridBagConstraints.REMAINDER;
  884. bag.setConstraints(locationBox, c);
  885. panel.add(locationBox);
  886. //XXX set next button to read install
  887. //context.nextButton.setText("Install");
  888. return panel;
  889. }
  890. public Component makeButtons(Installer installer) {
  891. Component ret = super.makeButtons(installer);
  892. nextButton.setText("Install");
  893. return ret;
  894. }
  895. public void actionPerformed(ActionEvent e) {
  896. JFileChooser chooser = new JFileChooser(); // {
  897. // public void approveSelection() {
  898. // System.out.println("approved selection");
  899. // }
  900. //}; //field.getText());
  901. chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
  902. int returnVal = chooser.showDialog(location, "Select");
  903. if (returnVal == JFileChooser.APPROVE_OPTION) {
  904. File file = chooser.getSelectedFile();
  905. if (!file.isDirectory()) {
  906. file = file.getParentFile();
  907. }
  908. String name = file.getPath();
  909. location.setText(name);
  910. location.selectAll();
  911. }
  912. }
  913. /**
  914. * Override to do any additional checks.
  915. */
  916. protected void verify() {
  917. }
  918. public void finish() {
  919. verify();
  920. context.setOutputDir(new File(location.getText()));
  921. }
  922. }
  923. class ConfigureLauncherPane extends WizardPane {
  924. /*
  925. * //XXX check that the returned file is valid public String getDefaultJavaLocation() { String name = "java"; if
  926. * (context.onWindows()) name += ".exe";
  927. *
  928. * if (Options.verbose) { System.out.println("java.home: " + System.getProperty("java.home")); System.out.println(" java: " +
  929. * new File(new File(System.getProperty("java.home"), "bin"), name)); System.out.println(" java: " + new File(new
  930. * File(System.getProperty("java.home"), "bin"), name).getPath()); }
  931. *
  932. * return new File(new File(System.getProperty("java.home"), "bin"), name).getPath(); }
  933. */
  934. public static String getDefaultJavaHomeLocation() {
  935. if (!Options.forceHandConfigure) {
  936. File javaHome = findJavaHome();
  937. if (javaHome != null) {
  938. return javaHome.getPath();
  939. }
  940. }
  941. return null;
  942. }
  943. public void chooseFile(JTextField field) {
  944. JFileChooser chooser = new JFileChooser(); //field.getText());
  945. chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
  946. int returnVal = chooser.showDialog(field, "Select");
  947. if (returnVal == JFileChooser.APPROVE_OPTION) {
  948. String name = chooser.getSelectedFile().getPath();
  949. field.setText(name);
  950. field.selectAll();
  951. }
  952. }
  953. public ActionListener makeJavaLocationBrowseListener() {
  954. return new ActionListener() {
  955. public void actionPerformed(ActionEvent e) {
  956. chooseFile(javaLocation);
  957. }
  958. };
  959. }
  960. // public ActionListener makeToolsJarLocationBrowseListener() {
  961. // return new ActionListener() {
  962. // public void actionPerformed(ActionEvent e) {
  963. // chooseFile(toolsJarLocation);
  964. // }
  965. // };
  966. // }
  967. private JTextField javaLocation;
  968. //private JTextField toolsJarLocation;
  969. public JPanel makePanel() {
  970. String javaPath = getDefaultJavaHomeLocation();
  971. //String toolsJarPath = getDefaultToolsJarLocation();
  972. Component text;
  973. if (javaPath == null) {
  974. javaPath = "<java home not found>";
  975. text = makeHTMLArea("configure-hand.html");
  976. } else {
  977. text = makeHTMLArea("configure-auto.html");
  978. }
  979. javaLocation = new JTextField(javaPath);
  980. JButton javaLocationBrowse = new JButton("Browse...");
  981. javaLocationBrowse.addActionListener(makeJavaLocationBrowseListener());
  982. JPanel javaLocationBox = makeLocationBox("java home directory", javaLocation, javaLocationBrowse);
  983. // toolsJarLocation = new JTextField(toolsJarPath);
  984. // JButton toolsJarLocationBrowse = new JButton("Browse...");
  985. // toolsJarLocationBrowse.addActionListener(makeToolsJarLocationBrowseListener());
  986. // JPanel toolsJarLocationBox = makeLocationBox("full path to tools.jar", toolsJarLocation, toolsJarLocationBrowse);
  987. GridBagLayout bag = new GridBagLayout();
  988. GridBagConstraints c = new GridBagConstraints();
  989. JPanel panel = new JPanel(bag);
  990. c.fill = GridBagConstraints.BOTH;
  991. c.weightx = 1.0;
  992. c.weighty = 1.0;
  993. //c.ipady = 10;
  994. c.gridwidth = GridBagConstraints.REMAINDER;
  995. bag.setConstraints(text, c);
  996. panel.add(text);
  997. c.weighty = 0.0;
  998. //c.fill = GridBagConstraints.VERTICAL;
  999. bag.setConstraints(javaLocationBox, c);
  1000. panel.add(javaLocationBox);
  1001. // c.weighty = 0.25;
  1002. // JLabel space = new JLabel();
  1003. // bag.setConstraints(space, c);
  1004. // panel.add(space);
  1005. // c.weighty = 0.0;
  1006. // bag.setConstraints(toolsJarLocationBox, c);
  1007. // panel.add(toolsJarLocationBox);
  1008. c.weighty = 0.5;
  1009. JLabel space = new JLabel();
  1010. bag.setConstraints(space, c);
  1011. panel.add(space);
  1012. return panel;
  1013. }
  1014. public void finish() {
  1015. context.javaPath = new File(javaLocation.getText());
  1016. // context.toolsJarPath = new File(toolsJarLocation.getText());
  1017. //XXX need much more work on helping the user get these paths right
  1018. // if (context.javaPath.isDirectory()) {
  1019. // context.javaPath = new File(context.javaPath, "java");
  1020. // }
  1021. // if (context.toolsJarPath.isDirectory()) {
  1022. // context.toolsJarPath = new File(context.toolsJarPath, "tools.jar");
  1023. // }
  1024. }
  1025. //XXX add user.home to prefixes in a rational way
  1026. public static final String[] windowsPaths = { "c:\\jdk", "c:\\apps\\jdk", "${user.home}\\jdk" };
  1027. public static final String[] unixPaths = { "/usr/local/bin/jdk", "/usr/bin/jdk", "/usr/bin/jdk", "${user.home}/jdk" };
  1028. public static final String[] suffixes = { "1.3.1", "1.3", "1.2", "13", "12", "2", "", "1.4" };
  1029. public static boolean windows = true;
  1030. public static boolean isLegalJavaHome(File home) {
  1031. File bin = new File(home, "bin");
  1032. return new File(bin, "java").isFile() || new File(bin, "java.exe").isFile();
  1033. }
  1034. public static boolean isLegalJDKHome(File home) {
  1035. File lib = new File(home, "lib");
  1036. return new File(lib, "tools.jar").isFile();
  1037. }
  1038. public static File findJavaHome() {
  1039. String s = System.getProperty("java.home");
  1040. File javaHome = null;
  1041. if (s != null) {
  1042. javaHome = new File(s);
  1043. if (isLegalJDKHome(javaHome)) {
  1044. return javaHome;
  1045. }
  1046. if (isLegalJavaHome(javaHome)) {
  1047. File parent = javaHome.getParentFile();
  1048. if (parent != null && isLegalJDKHome(parent)) {
  1049. return parent;
  1050. }
  1051. }
  1052. }
  1053. String[] paths;
  1054. if (windows) {
  1055. paths = windowsPaths;
  1056. } else {
  1057. paths = unixPaths;
  1058. }
  1059. for (String suffix : suffixes) {
  1060. for (String path : paths) {
  1061. String prefix = path;
  1062. prefix = applyProperties(prefix);
  1063. File test = new File(prefix + suffix);
  1064. if (isLegalJavaHome(test)) {
  1065. if (isLegalJDKHome(test)) {
  1066. return test;
  1067. } else if (javaHome == null) {
  1068. javaHome = test;
  1069. }
  1070. }
  1071. }
  1072. }
  1073. return javaHome;
  1074. }
  1075. }
  1076. class InstallPane extends WizardPane {
  1077. private JProgressBar progressBar;
  1078. private JTextField progressItem;
  1079. private JEditorPane message;
  1080. private boolean makeLaunchScripts = false;
  1081. public InstallPane(boolean makeLaunchScripts) {
  1082. this.makeLaunchScripts = makeLaunchScripts;
  1083. }
  1084. public JPanel makePanel() {
  1085. message = makeHTMLArea("install-start.html");
  1086. progressBar = new JProgressBar();
  1087. progressItem = new JTextField();
  1088. progressItem.setOpaque(false);
  1089. progressItem.setFont(context.getFont());
  1090. progressItem.setEditable(false);
  1091. GridBagLayout bag = new GridBagLayout();
  1092. GridBagConstraints c = new GridBagConstraints();
  1093. JPanel panel = new JPanel(bag);
  1094. c.fill = GridBagConstraints.BOTH;
  1095. c.weightx = 1.0;
  1096. c.weighty = 1.0;
  1097. //c.ipady = 10;
  1098. c.gridwidth = GridBagConstraints.REMAINDER;
  1099. bag.setConstraints(message, c);
  1100. panel.add(message);
  1101. c.weighty = 0.0;
  1102. //c.fill = GridBagConstraints.VERTICAL;
  1103. bag.setConstraints(progressBar, c);
  1104. panel.add(progressBar);
  1105. c.weighty = 0.1;
  1106. JLabel space = new JLabel();
  1107. bag.setConstraints(space, c);
  1108. panel.add(space);
  1109. c.weighty = 0.0;
  1110. bag.setConstraints(progressItem, c);
  1111. panel.add(progressItem);
  1112. c.weighty = 0.5;
  1113. space = new JLabel();
  1114. bag.setConstraints(space, c);
  1115. panel.add(space);
  1116. return panel;
  1117. }
  1118. class InstallRunner implements Runnable {
  1119. public InstallRunner() {
  1120. }
  1121. public void run() {
  1122. try {
  1123. new CurrentJarUnpacker(context, InstallPane.this).unpack(Installer.RESOURCE_DIR + "/contents.txt",
  1124. context.getOutputDir());
  1125. if (makeLaunchScripts) {
  1126. LaunchScriptMaker lsm = new LaunchScriptMaker(context);
  1127. lsm.writeScript("ajc");
  1128. lsm.writeScript("ajdoc");
  1129. //lsm.writeScript("ajdb");
  1130. lsm.writeScript("ajbrowser");
  1131. // Moved to the bin dir in 1.2.1
  1132. // we should now come back and make the generation of this
  1133. // script uniform with those above.
  1134. lsm.writeAJLaunchScript("aj", false);
  1135. lsm.writeAJLaunchScript("aj5", true);
  1136. }
  1137. if (hasGui()) {
  1138. progressBar.setValue(100);
  1139. setHTMLArea(message, "install-finish.html");
  1140. }
  1141. } catch (IOException ioe) {
  1142. context.handleException(ioe);
  1143. }
  1144. if (hasGui()) {
  1145. cancelButton.setEnabled(false);
  1146. nextButton.setEnabled(true);
  1147. }
  1148. }
  1149. }
  1150. public Component makeButtons(Installer installer) {
  1151. Component ret = super.makeButtons(installer);
  1152. //nextButton.setText("Finish");
  1153. nextButton.setEnabled(false);
  1154. //nextButton.addActionListener(installer.makeFinishAction(this));
  1155. backButton.setEnabled(false);
  1156. return ret;
  1157. }
  1158. public void run() {
  1159. Thread thread = new Thread(new InstallRunner());
  1160. thread.start();
  1161. }
  1162. public void progressMessage(final String message) {
  1163. if (!hasGui()) {
  1164. return;
  1165. }
  1166. try {
  1167. //XXX performance tradeoff between invokeAndWait and invokeLater...
  1168. SwingUtilities.invokeAndWait(new Runnable() {
  1169. public void run() {
  1170. progressItem.setText(message);
  1171. }
  1172. });
  1173. } catch (InvocationTargetException ite) {
  1174. context.handleException(ite.getTargetException());
  1175. } catch (InterruptedException ie) {
  1176. }
  1177. }
  1178. int nBytes = 0;
  1179. int bytesWritten = 0;
  1180. public void progressBytesWritten(int bytes) {
  1181. if (!hasGui()) {
  1182. return;
  1183. }
  1184. bytesWritten += bytes;
  1185. final int PCT = (int) (100.0 * bytesWritten / nBytes);
  1186. //System.out.println("bytesWritten: " + bytesWritten);
  1187. try {
  1188. //XXX performance tradeoff between invokeAndWait and invokeLater...
  1189. SwingUtilities.invokeAndWait(new Runnable() {
  1190. public void run() {
  1191. progressBar.setValue(PCT);
  1192. }
  1193. });
  1194. } catch (InvocationTargetException ite) {
  1195. context.handleException(ite.getTargetException());
  1196. } catch (InterruptedException ie) {
  1197. }
  1198. }
  1199. }
  1200. class CurrentJarUnpacker {
  1201. InstallContext context;
  1202. InstallPane installPane;
  1203. public CurrentJarUnpacker(InstallContext context, InstallPane installPane) {
  1204. this.context = context;
  1205. this.installPane = installPane;
  1206. }
  1207. public File makeOutputFile(String name, File outputFile) {
  1208. int index;
  1209. int lastIndex = 0;
  1210. while ((index = name.indexOf('/', lastIndex)) != -1) {
  1211. outputFile = new File(outputFile, name.substring(lastIndex, index));
  1212. lastIndex = index + 1;
  1213. }
  1214. return new File(outputFile, name.substring(lastIndex));
  1215. }
  1216. final static int BUF_SIZE = 4096;
  1217. public void writeStream(InputStream zis, File outputFile) throws IOException {
  1218. if (outputFile.exists()) {
  1219. if (!context.shouldOverwrite(outputFile)) {
  1220. return;
  1221. }
  1222. }
  1223. installPane.progressMessage("writing " + outputFile.getAbsolutePath());
  1224. outputFile.getParentFile().mkdirs();
  1225. if (context.isTextFile(outputFile)) {
  1226. writeTextStream(zis, outputFile);
  1227. } else {
  1228. writeBinaryStream(zis, outputFile);
  1229. }
  1230. }
  1231. public void writeBinaryStream(InputStream zis, File outputFile) throws IOException {
  1232. byte[] buffer = new byte[BUF_SIZE];
  1233. int nRead = 0;
  1234. OutputStream os = new BufferedOutputStream(new FileOutputStream(outputFile));
  1235. while ((nRead = zis.read(buffer)) != -1) {
  1236. os.write(buffer, 0, nRead);
  1237. installPane.progressBytesWritten(nRead);
  1238. }
  1239. os.close();
  1240. }
  1241. public void writeTextStream(InputStream zis, File outputFile) throws IOException {
  1242. BufferedWriter os = new BufferedWriter(new FileWriter(outputFile));
  1243. BufferedReader r = new BufferedReader(new InputStreamReader(zis, "US-ASCII"));
  1244. String l;
  1245. while ((l = r.readLine()) != null) {
  1246. os.write(l);
  1247. os.newLine();
  1248. installPane.progressBytesWritten(l.length() + 1);
  1249. }
  1250. os.close();
  1251. }
  1252. public void writeResource(String name, File outputDir) throws IOException {
  1253. File outputFile = makeOutputFile(name, outputDir);
  1254. //System.out.println("finding name: " + name);
  1255. writeStream(getClass().getResourceAsStream("/" + name), outputFile);
  1256. }
  1257. public void writeResource(JarFile jarFile, JarEntry entry, File outputDir) throws IOException {
  1258. String name = entry.getName().substring(6);
  1259. File outputFile = makeOutputFile(name, outputDir);
  1260. //System.out.println("finding name: " + name);
  1261. // writeStream(getClass().getResourceAsStream("/" + name), outputFile);
  1262. writeStream(jarFile.getInputStream(entry), outputFile);
  1263. }
  1264. public void unpack(String contentsName, File outputDir) throws IOException {
  1265. URL url = getClass().getResource(contentsName);
  1266. // Process everything under 'files/**' copying to the target
  1267. // install directory with 'files/' removed
  1268. JarURLConnection juc = (JarURLConnection) url.openConnection();
  1269. JarFile jf = juc.getJarFile();
  1270. Enumeration<JarEntry> entries = jf.entries();
  1271. while (entries.hasMoreElements()) {
  1272. JarEntry je = entries.nextElement();
  1273. if (je.getName().startsWith("files/") && !je.getName().endsWith("/")) {
  1274. writeResource(jf, je, outputDir);
  1275. }
  1276. }
  1277. // InputStream stream = url.openStream();
  1278. // BufferedReader reader = new BufferedReader(new InputStreamReader(stream, "US-ASCII"));
  1279. // String line = reader.readLine();
  1280. // installPane.nBytes = Integer.parseInt(line);
  1281. //
  1282. // while ((line = reader.readLine()) != null) {
  1283. // writeResource(line, outputDir);
  1284. // }
  1285. installPane.progressMessage("done writing");
  1286. }
  1287. }
  1288. class LaunchScriptMaker {
  1289. static final String toolsPackage = "org.aspectj.tools";
  1290. InstallContext context;
  1291. public LaunchScriptMaker(InstallContext context) {
  1292. this.context = context;
  1293. }
  1294. /**
  1295. *
  1296. */
  1297. public void writeAJLaunchScript(String name, boolean isJava5) throws IOException {
  1298. if (!context.onUnix()) {
  1299. if (context.onOS2()) {
  1300. name += ".cmd";
  1301. } else if (context.onWindows()) {
  1302. name += ".bat";
  1303. }
  1304. }
  1305. File destDir = new File(context.getOutputDir(), "bin");
  1306. destDir.mkdirs();
  1307. File file = new File(destDir, name);
  1308. PrintStream ps = getPrintStream(file);
  1309. writeAJLaunchScriptContent(ps, isJava5);
  1310. ps.close();
  1311. if (context.onUnix()) {
  1312. makeExecutable(file);
  1313. }
  1314. }
  1315. /**
  1316. * @param ps
  1317. */
  1318. private void writeAJLaunchScriptContent(PrintStream ps, boolean isJava5) {
  1319. if (context.onUnix()) {
  1320. writeUnixHeader(ps);
  1321. if (isJava5) {
  1322. writeAJ5UnixLaunchLine(ps);
  1323. } else {
  1324. writeAJUnixLaunchLine(ps);
  1325. }
  1326. } else {
  1327. writeWindowsHeader(ps);
  1328. if (isJava5) {
  1329. writeAJ5WindowsLaunchLine(ps);
  1330. } else {
  1331. writeAJWindowsLaunchLine(ps);
  1332. }
  1333. }
  1334. }
  1335. /**
  1336. * @param ps
  1337. */
  1338. private void writeAJWindowsLaunchLine(PrintStream ps) {
  1339. ps.println("\"%JAVA_HOME%\\bin\\java\" -classpath " + "\"%ASPECTJ_HOME%\\lib\\aspectjweaver.jar\""
  1340. + " \"-Djava.system.class.loader=org.aspectj.weaver.loadtime.WeavingURLClassLoader\""
  1341. + " \"-Daj.class.path=%ASPECTPATH%;%CLASSPATH%\"" + " \"-Daj.aspect.path=%ASPECTPATH%\"" + " "
  1342. + makeScriptArgs(false));
  1343. }
  1344. /**
  1345. * @param ps
  1346. */
  1347. private void writeAJ5WindowsLaunchLine(PrintStream ps) {
  1348. ps.println("\"%JAVA_HOME%\\bin\\java\" -classpath " + "\"%ASPECTJ_HOME%\\lib\\aspectjweaver.jar;%CLASSPATH%\""
  1349. + " \"-javaagent:%ASPECTJ_HOME%\\lib\\aspectjweaver.jar\"" + " " + makeScriptArgs(false));
  1350. }
  1351. /**
  1352. * @param ps
  1353. */
  1354. private void writeAJUnixLaunchLine(PrintStream ps) {
  1355. ps.println("\"$JAVA_HOME/bin/java\" -classpath" + " \"$ASPECTJ_HOME/lib/aspectjweaver.jar\""
  1356. + " \"-Djava.system.class.loader=org.aspectj.weaver.loadtime.WeavingURLClassLoader\""
  1357. + " \"-Daj.class.path=$ASPECTPATH:$CLASSPATH\"" + " \"-Daj.aspect.path=$ASPECTPATH\"" + " " + makeScriptArgs(true));
  1358. }
  1359. /**
  1360. * @param ps
  1361. */
  1362. private void writeAJ5UnixLaunchLine(PrintStream ps) {
  1363. ps.println("\"$JAVA_HOME/bin/java\" -classpath" + " \"$ASPECTJ_HOME/lib/aspectjweaver.jar:$CLASSPATH\""
  1364. + " \"-javaagent:$ASPECTJ_HOME/lib/aspectjweaver.jar\"" + " " + makeScriptArgs(true));
  1365. }
  1366. private void writeWindowsHeader(PrintStream ps) {
  1367. ps.println("@echo off");
  1368. ps.println("REM This file generated by AspectJ installer");
  1369. ps.println("REM Created on " + new java.util.Date() + " by " + System.getProperty("user.name"));
  1370. ps.println("");
  1371. ps.println("if \"%JAVA_HOME%\" == \"\" set JAVA_HOME=" + context.javaPath.getAbsolutePath());
  1372. ps.println("if \"%ASPECTJ_HOME%\" == \"\" set ASPECTJ_HOME=" + context.getOutputDir().getAbsolutePath());
  1373. ps.println("");
  1374. ps.println("if exist \"%JAVA_HOME%\\bin\\java.exe\" goto haveJava");
  1375. ps.println("if exist \"%JAVA_HOME%\\bin\\java.bat\" goto haveJava");
  1376. ps.println("if exist \"%JAVA_HOME%\\bin\\java\" goto haveJava");
  1377. ps.println("echo java does not exist as %JAVA_HOME%\\bin\\java");
  1378. ps.println("echo please fix the JAVA_HOME environment variable");
  1379. ps.println(":haveJava");
  1380. }
  1381. private void writeWindowsLaunchLine(String className, PrintStream ps) {
  1382. ps.println("\"%JAVA_HOME%\\bin\\java\" -classpath " +
  1383. // "\"%ASPECTJ_HOME%\\lib\\aspectjtools.jar;%CLASSPATH%\""+
  1384. "\"%ASPECTJ_HOME%\\lib\\aspectjtools.jar;%JAVA_HOME%\\lib\\tools.jar;%CLASSPATH%\"" + " -Xmx64M " + className + //" -defaultClasspath " + "\"%CLASSPATH%\"" +
  1385. " " + makeScriptArgs(false));
  1386. }
  1387. private void writeUnixHeader(PrintStream ps) {
  1388. File binsh = new File(File.separator + "bin", "sh");
  1389. if (binsh.canRead()) {
  1390. ps.println("#!" + binsh.getPath());
  1391. }
  1392. ps.println("# This file generated by AspectJ installer");
  1393. ps.println("# Created on " + new java.util.Date() + " by " + System.getProperty("user.name"));
  1394. ps.println("");
  1395. ps.println("if [ \"$JAVA_HOME\" = \"\" ] ; then JAVA_HOME=" + quote(true, false, context.javaPath.getAbsolutePath()));
  1396. ps.println("fi");
  1397. ps.println("if [ \"$ASPECTJ_HOME\" = \"\" ] ; then ASPECTJ_HOME=" + quote(true, false, context.getOutputDir()));
  1398. ps.println("fi");
  1399. ps.println("");
  1400. }
  1401. private void writeUnixLaunchLine(String className, PrintStream ps) {
  1402. String sep = File.pathSeparator;
  1403. ps.println("\"$JAVA_HOME/bin/java\" -classpath " + "\"$ASPECTJ_HOME/lib/aspectjtools.jar" + sep
  1404. + "$JAVA_HOME/lib/tools.jar" + sep + "$CLASSPATH\"" + " -Xmx64M " + className + " " + makeScriptArgs(true));
  1405. }
  1406. private void makeExecutable(File file) {
  1407. try {
  1408. Runtime curRuntime = Runtime.getRuntime();
  1409. curRuntime.exec("chmod 777 " + quote(true, false, file));
  1410. } catch (Throwable t) {
  1411. // ignore any errors that occur while trying to chmod
  1412. }
  1413. }
  1414. private String makeScriptArgs(boolean unixStyle) {
  1415. if (unixStyle) {
  1416. return "\"$@\"";
  1417. } else if (context.onWindowsPro()) {
  1418. return "%*";
  1419. } else {
  1420. return "%1 %2 %3 %4 %5 %6 %7 %8 %9";
  1421. }
  1422. }
  1423. private String quote(boolean unixStyle, boolean forceQuotes, File file) {
  1424. return quote(unixStyle, forceQuotes, file.getAbsolutePath());
  1425. }
  1426. private String quote(boolean unixStyle, boolean forceQuotes, String s) {
  1427. if (context.onWindows() && unixStyle) {
  1428. s = s.replace('\\', '/');
  1429. }
  1430. if (!forceQuotes && s.indexOf(' ') == -1) {
  1431. return s;
  1432. }
  1433. return "\"" + s + "\"";
  1434. }
  1435. private File makeScriptFile(String name, boolean unixStyle) throws IOException {
  1436. if (!unixStyle) {
  1437. if (context.onOS2()) {
  1438. name += ".cmd";
  1439. } else if (context.onWindows()) {
  1440. name += ".bat";
  1441. }
  1442. }
  1443. //XXX probably want a context.getOutputBinDir()
  1444. File bindir = new File(context.getOutputDir(), "bin");
  1445. bindir.mkdirs();
  1446. File file = new File(bindir, name);
  1447. return file;
  1448. }
  1449. private PrintStream getPrintStream(File file) throws IOException {
  1450. return new PrintStream(new BufferedOutputStream(new FileOutputStream(file)));
  1451. }
  1452. String makeClassPathVar(boolean unixStyle) {
  1453. if (unixStyle) {
  1454. return "$CLASSPATH";
  1455. } else {
  1456. return "%CLASSPATH%";
  1457. }
  1458. }
  1459. public String makeClassPath(boolean unixStyle) throws IOException {
  1460. return context.toolsJarPath.getAbsolutePath() + File.pathSeparator
  1461. +
  1462. //XXX want context.getOutputLibDir()
  1463. new File(new File(context.getOutputDir(), "lib"), "aspectjtools.jar").getAbsolutePath() + File.pathSeparator
  1464. + makeClassPathVar(unixStyle);
  1465. }
  1466. public void writeScript(String className, PrintStream ps, boolean unixStyle) throws IOException {
  1467. if (unixStyle) {
  1468. writeUnixHeader(ps);
  1469. writeUnixLaunchLine(className, ps);
  1470. } else {
  1471. writeWindowsHeader(ps);
  1472. writeWindowsLaunchLine(className, ps);
  1473. }
  1474. /*
  1475. * ps.print(quote(unixStyle, false, context.javaPath.getAbsolutePath())); ps.print(" "); ps.print("-classpath ");
  1476. * ps.print(quote(unixStyle, true, makeClassPath(unixStyle))); ps.print(" "); ps.print("-Xmx64M "); ps.print(className);
  1477. * ps.print(" "); ps.print(makeScriptArgs(unixStyle));
  1478. */
  1479. }
  1480. public void writeScript(String className, boolean unixStyle) throws IOException {
  1481. File file = makeScriptFile(className, unixStyle);
  1482. if (!checkExistingFile(file)) {
  1483. return;
  1484. }
  1485. PrintStream ps = getPrintStream(file);
  1486. writeScript(toolsPackage + '.' + className + ".Main", ps, unixStyle);
  1487. ps.close();
  1488. //??? unixStyle vs. onUnix()
  1489. if (context.onUnix()) {
  1490. makeExecutable(file);
  1491. }
  1492. }
  1493. public boolean checkExistingFile(File file) {
  1494. if (!file.exists()) {
  1495. return true;
  1496. }
  1497. return context.shouldOverwrite(file);
  1498. }
  1499. /*
  1500. * final static String OVERWRITE_MESSAGE = "Overwrite launch script "; final static String OVERWRITE_TITLE = "Overwrite?";
  1501. *
  1502. * final static String[] OVERWRITE_OPTIONS = { "Yes", "No", "Yes to all", "No to all" };
  1503. *
  1504. * final static int OVERWRITE_YES = 0; final static int OVERWRITE_NO = 1; final static int OVERWRITE_ALL = 2; final static int
  1505. * OVERWRITE_NONE = 3;
  1506. *
  1507. * int overwriteState = OVERWRITE_NO; boolean shouldOverwrite(final File file) { if (overwriteState == OVERWRITE_ALL) return
  1508. * true; if (overwriteState == OVERWRITE_NONE) return false;
  1509. *
  1510. * try { SwingUtilities.invokeAndWait(new Runnable() { public void run() { int ret =
  1511. * JOptionPane.showOptionDialog(context.installer.frame, OVERWRITE_MESSAGE+file.getPath(), OVERWRITE_TITLE,
  1512. * JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, OVERWRITE_OPTIONS, OVERWRITE_OPTIONS[OVERWRITE_YES]);
  1513. *
  1514. * overwriteState = ret; } }); } catch (InvocationTargetException ite) { context.handleException(ite.getTargetException()); }
  1515. * catch (InterruptedException ie) { }
  1516. *
  1517. * return overwriteState == OVERWRITE_YES || overwriteState == OVERWRITE_ALL; }
  1518. */
  1519. public void writeScript(String className) throws IOException {
  1520. writeScript(className, true);
  1521. if (context.onWindows()) {
  1522. writeScript(className, false);
  1523. }
  1524. }
  1525. }
  1526. class JarUnpacker {
  1527. InstallContext context;
  1528. InstallPane installPane;
  1529. public JarUnpacker(InstallContext context, InstallPane installPane) {
  1530. this.context = context;
  1531. this.installPane = installPane;
  1532. }
  1533. public File makeOutputFile(String name, File outputFile) {
  1534. int index;
  1535. int lastIndex = 0;
  1536. while ((index = name.indexOf('/', lastIndex)) != -1) {
  1537. outputFile = new File(outputFile, name.substring(lastIndex, index));
  1538. lastIndex = index + 1;
  1539. }
  1540. return new File(outputFile, name.substring(lastIndex));
  1541. }
  1542. final static int BUF_SIZE = 4096;
  1543. public void writeStream(ZipInputStream zis, File outputFile) throws IOException {
  1544. if (outputFile.exists()) {
  1545. if (!context.shouldOverwrite(outputFile)) {
  1546. return;
  1547. }
  1548. }
  1549. installPane.progressMessage("writing " + outputFile.getAbsolutePath());
  1550. outputFile.getParentFile().mkdirs();
  1551. if (context.isTextFile(outputFile)) {
  1552. writeTextStream(zis, outputFile);
  1553. } else {
  1554. writeBinaryStream(zis, outputFile);
  1555. }
  1556. }
  1557. public void writeBinaryStream(ZipInputStream zis, File outputFile) throws IOException {
  1558. byte[] buffer = new byte[BUF_SIZE];
  1559. int nRead = 0;
  1560. OutputStream os = new BufferedOutputStream(new FileOutputStream(outputFile));
  1561. while ((nRead = zis.read(buffer)) != -1) {
  1562. os.write(buffer, 0, nRead);
  1563. installPane.progressBytesWritten(nRead);
  1564. }
  1565. os.close();
  1566. }
  1567. public void writeTextStream(ZipInputStream zis, File outputFile) throws IOException {
  1568. BufferedWriter os = new BufferedWriter(new FileWriter(outputFile));
  1569. BufferedReader r = new BufferedReader(new InputStreamReader(zis, "US-ASCII"));
  1570. String l;
  1571. while ((l = r.readLine()) != null) {
  1572. os.write(l);
  1573. os.newLine();
  1574. installPane.progressBytesWritten(l.length() + 1);
  1575. }
  1576. os.close();
  1577. }
  1578. public void writeEntry(ZipInputStream zis, ZipEntry entry, File outputDir) throws IOException {
  1579. if (entry.isDirectory()) {
  1580. return;
  1581. }
  1582. String name = entry.getName();
  1583. File outputFile = makeOutputFile(name, outputDir);
  1584. writeStream(zis, outputFile);
  1585. }
  1586. public void unpack(String jarName, File outputDir) throws IOException {
  1587. URL url = getClass().getResource(jarName);
  1588. InputStream stream = url.openStream();
  1589. ZipInputStream zis = new ZipInputStream(stream);
  1590. // int i = 0;
  1591. ZipEntry entry;
  1592. while ((entry = zis.getNextEntry()) != null) {
  1593. // final String name = entry.getName();
  1594. writeEntry(zis, entry, outputDir);
  1595. //
  1596. }
  1597. installPane.progressMessage("done writing");
  1598. }
  1599. }