001: /*
002: * The contents of this file are subject to the terms of the Common Development
003: * and Distribution License (the License). You may not use this file except in
004: * compliance with the License.
005: *
006: * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
007: * or http://www.netbeans.org/cddl.txt.
008: *
009: * When distributing Covered Code, include this CDDL Header Notice in each file
010: * and include the License file at http://www.netbeans.org/cddl.txt.
011: * If applicable, add the following below the CDDL Header, with the fields
012: * enclosed by brackets [] replaced by your own identifying information:
013: * "Portions Copyrighted [year] [name of copyright owner]"
014: *
015: * The Original Software is NetBeans. The Initial Developer of the Original
016: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
017: * Microsystems, Inc. All Rights Reserved.
018: */
019:
020: package org.netbeans.installer;
021:
022: import com.installshield.product.ProductAction;
023: import com.installshield.product.ProductActionSupport;
024: import com.installshield.product.ProductBuilderSupport;
025: import com.installshield.product.ProductException;
026: import com.installshield.product.RequiredBytesTable;
027: import com.installshield.util.Log;
028: import com.installshield.wizard.service.MutableOperationState;
029: import com.installshield.wizard.service.exitcode.ExitCodeService;
030: import com.installshield.wizard.service.file.FileService;
031:
032: import java.io.BufferedReader;
033: import java.io.File;
034:
035: public class UnpackJarsAction extends ProductAction {
036:
037: //return code incase an error returns
038: public static final int UNPACK_JARS_UNHANDLED_ERROR = -400;
039:
040: public static final int UNPACK_JARS_MD5_ERROR = -401;
041:
042: private static final String JARS_CATALOG_FILE = "packedjars.xml";
043:
044: private int installMode = 0;
045: private static final int INSTALL = 0;
046: private static final int UNINSTALL = 1;
047:
048: private String statusDesc = "";
049: private String nbInstallDir = "";
050: private String rootInstallDir = "";
051: private String uninstDir = "";
052:
053: private boolean success = false;
054:
055: private ProgressThread progressThread;
056: private MutableOperationState mutableOperationState;
057:
058: public UnpackJarsAction() {
059: }
060:
061: public void build(ProductBuilderSupport support) {
062: try {
063: support.putClass(RunCommand.class.getName());
064: support
065: .putClass("org.netbeans.installer.RunCommand$StreamAccumulator");
066: support.putClass(Util.class.getName());
067: support.putClass(UnpackJarsAction.ProgressThread.class
068: .getName());
069: support.putClass(UnpackJars.class.getName());
070: support.putClass(UnpackJars.ErrorCatcher.class.getName());
071: support.putClass(UnpackJars.JarItem.class.getName());
072: support.putClass(UnpackJars.ProgressInfo.class.getName());
073: support.putClass(XMLUtil.class.getName());
074: support.putClass(XMLUtil.CustomEntityResolver.class
075: .getName());
076: } catch (Exception ex) {
077: System.out.println(ex.getLocalizedMessage());
078: ex.printStackTrace();
079: }
080: }
081:
082: private void init(ProductActionSupport support) {
083: rootInstallDir = resolveString("$P(absoluteInstallLocation)");
084: if (Util.isMacOSX()) {
085: nbInstallDir = rootInstallDir
086: + File.separator
087: + resolveString("$L(org.netbeans.installer.Bundle,Product.nbLocationBelowInstallRoot)");
088: } else {
089: nbInstallDir = rootInstallDir;
090: }
091: logEvent(this , Log.DBG, "nbInstallDir: " + nbInstallDir);
092: uninstDir = nbInstallDir + File.separator + "_uninst";
093: logEvent(this , Log.DBG, "uninstDir: " + uninstDir);
094:
095: mutableOperationState = support.getOperationState();
096:
097: }
098:
099: public void install(ProductActionSupport support) {
100: long currtime = System.currentTimeMillis();
101: statusDesc = resolveString("$L(org.netbeans.installer.Bundle,ProgressPanel.unpackJarsMessage)")
102: + " "
103: + resolveString("$L(org.netbeans.installer.Bundle,ProgressPanel.waitMessage)");
104:
105: support.getOperationState().setStatusDescription(statusDesc);
106:
107: try {
108: init(support);
109: installMode = INSTALL;
110:
111: long startTime = System.currentTimeMillis();
112:
113: File catalog = new File(uninstDir, JARS_CATALOG_FILE);
114: if (!catalog.exists()) {
115: try {
116: logEvent(this , Log.ERROR, "# # # # # # # #");
117: logEvent(this , Log.ERROR,
118: "Fatal error: Cannot find jar catalog file: "
119: + catalog);
120: ExitCodeService ecservice = (ExitCodeService) getService(ExitCodeService.NAME);
121: ecservice.setExitCode(UNPACK_JARS_UNHANDLED_ERROR);
122: } catch (Exception ex) {
123: logEvent(this , Log.ERROR,
124: "Could not set exit code.");
125: }
126: return;
127: }
128: UnpackJars unpackJars = new UnpackJars();
129: unpackJars.init(nbInstallDir, this );
130: boolean ret;
131: ret = unpackJars.parseCatalog(this , catalog
132: .getAbsolutePath());
133: if (!ret) {
134: try {
135: logEvent(this , Log.ERROR, "# # # # # # # #");
136: logEvent(this , Log.ERROR,
137: "Fatal error: Cannot parse jar catalog.");
138: ExitCodeService ecservice = (ExitCodeService) getService(ExitCodeService.NAME);
139: ecservice.setExitCode(UNPACK_JARS_UNHANDLED_ERROR);
140: } catch (Exception ex) {
141: logEvent(this , Log.ERROR,
142: "Could not set exit code.");
143: }
144: return;
145: }
146:
147: startProgress(unpackJars);
148:
149: FileService fileService = null;
150: try {
151: fileService = (FileService) getService(FileService.NAME);
152: if (fileService == null) {
153: logEvent(this , Log.ERROR,
154: "Error: Cannot get FileService.");
155: }
156: } catch (Exception ex) {
157: logEvent(this , Log.ERROR,
158: "Error: Cannot get FileService.");
159: logEvent(this , Log.ERROR, "Exception: "
160: + ex.getMessage());
161: Util.logStackTrace(this , ex);
162: }
163: if (fileService == null) {
164: try {
165: logEvent(this , Log.ERROR, "# # # # # # # #");
166: logEvent(this , Log.ERROR,
167: "Fatal error: Cannot get file service.");
168: ExitCodeService ecservice = (ExitCodeService) getService(ExitCodeService.NAME);
169: ecservice.setExitCode(UNPACK_JARS_UNHANDLED_ERROR);
170: } catch (Exception ex) {
171: logEvent(this , Log.ERROR,
172: "Could not set exit code.");
173: }
174: return;
175: }
176:
177: int retVal = unpackJars.unpackJars(this , fileService);
178: if (retVal != 0) {
179: try {
180: logEvent(this , Log.ERROR, "# # # # # # # #");
181: logEvent(this , Log.ERROR,
182: "Fatal error: Cannot unpack jars.");
183: ExitCodeService ecservice = (ExitCodeService) getService(ExitCodeService.NAME);
184: ecservice.setExitCode(retVal);
185: } catch (Exception ex) {
186: logEvent(this , Log.ERROR,
187: "Could not set exit code.");
188: }
189: return;
190: }
191:
192: long endTime = System.currentTimeMillis();
193:
194: logEvent(this , Log.DBG, "Unpack Jars took: "
195: + (endTime - startTime) + "ms");
196: } catch (Exception ex) {
197: logEvent(this , Log.ERROR, ex);
198: } finally {
199: stopProgress();
200: }
201: }
202:
203: /** Does cleaning of unpacked jars. */
204: public void uninstall(ProductActionSupport support) {
205: init(support);
206: installMode = UNINSTALL;
207: //Perform work
208: File catalog = new File(uninstDir, JARS_CATALOG_FILE);
209: if (!catalog.exists()) {
210: try {
211: logEvent(this , Log.ERROR, "# # # # # # # #");
212: logEvent(this , Log.ERROR,
213: "Fatal error: Cannot find jar catalog file: "
214: + catalog);
215: ExitCodeService ecservice = (ExitCodeService) getService(ExitCodeService.NAME);
216: ecservice.setExitCode(UNPACK_JARS_UNHANDLED_ERROR);
217: } catch (Exception ex) {
218: logEvent(this , Log.ERROR, "Could not set exit code.");
219: }
220: return;
221: }
222: UnpackJars unpackJars = new UnpackJars();
223: unpackJars.init(nbInstallDir, this );
224: boolean ret;
225: ret = unpackJars.parseCatalog(this , catalog.getAbsolutePath());
226: if (!ret) {
227: try {
228: logEvent(this , Log.ERROR, "# # # # # # # #");
229: logEvent(this , Log.ERROR,
230: "Fatal error: Cannot parse jar catalog.");
231: ExitCodeService ecservice = (ExitCodeService) getService(ExitCodeService.NAME);
232: ecservice.setExitCode(UNPACK_JARS_UNHANDLED_ERROR);
233: } catch (Exception ex) {
234: logEvent(this , Log.ERROR, "Could not set exit code.");
235: }
236: return;
237: }
238: unpackJars.deleteJars(this );
239: catalog.delete();
240: }
241:
242: /**
243: * Returns difference between total size of uncompressed jars and total size
244: * of compressed jars size to show correct total install size on Preview panel.
245: * Total size of compressed jars is already included in beanCoreIDE.
246: */
247: public long getCheckSum() {
248: return 72000000L;
249: }
250:
251: /* Returns the required bytes table information.
252: * @return required bytes table.
253: * @see com.installshield.product.RequiredBytesTable
254: */
255: public RequiredBytesTable getRequiredBytes()
256: throws ProductException {
257: RequiredBytesTable req = new RequiredBytesTable();
258:
259: nbInstallDir = resolveString("$P(absoluteInstallLocation)");
260: logEvent(this , Log.DBG, "getRequiredBytes nbInstallDir: "
261: + nbInstallDir);
262: req.addBytes(nbInstallDir, getCheckSum());
263:
264: return req;
265: }
266:
267: private static int ESTIMATED_TIME = 3500; // tenths of seconds
268:
269: public int getEstimatedTimeToInstall() {
270: return ESTIMATED_TIME;
271: }
272:
273: public void startProgress(UnpackJars unpackJars) {
274: progressThread = new ProgressThread(unpackJars);
275: progressThread.start();
276: }
277:
278: public void stopProgress() {
279: //Method startProgress() must be called first
280: if (progressThread == null) {
281: return;
282: }
283: logEvent(this , Log.DBG, "in progress stop");
284: progressThread.finish();
285: logEvent(this , Log.DBG, "Finishing ProgressThread");
286: //wait until progressThread is interrupted
287: while (progressThread.isAlive()) {
288: logEvent(this , Log.DBG,
289: "Waiting for progressThread to die...");
290: try {
291: Thread.currentThread().sleep(1000);
292: } catch (Exception ex) {
293: }
294: }
295: logEvent(this , Log.DBG, "ProgressThread finished");
296: progressThread = null;
297: logEvent(this , Log.DBG, "active Threads -> "
298: + Thread.currentThread().activeCount());
299: }
300:
301: /** Inner class to update the progress pane while installation */
302: class ProgressThread extends Thread {
303: private boolean loop = true;
304: private MutableOperationState mos;
305:
306: //progress bar related variables
307: private long percentageCompleted = 0L;
308: private long percentageStart = 0L;
309: private long checksum = 0L;
310:
311: //status detail related variables
312: //progress dots (...) after the path if it is being shown since s while
313: private final int MIN_DOTS = 3;
314: private int fileCounter = 0;
315: private String lastPathShown;
316:
317: //status description related variables
318: private File logFile;
319: private boolean doStatusDescUpdate = true;
320:
321: //variables related to pkg unzipping before installation. Only for Solaris
322: private boolean isUnzipping = false;
323: private File unzipLog;
324: private BufferedReader unzipLogReader = null;
325: private long startTime = 0L;
326:
327: private UnpackJars unpackJars;
328:
329: public ProgressThread(UnpackJars unpackJars) {
330: this .mos = mutableOperationState;
331: this .unpackJars = unpackJars;
332: checksum = unpackJars.totalOriginalSize;
333: }
334:
335: public void run() {
336: long sleepTime = 500L;
337: percentageStart = mos.getProgress().getPercentComplete();
338: logEvent(this , Log.DBG, "Starting percentageStart: "
339: + percentageStart);
340: while (loop) {
341: try {
342: updateProgressBar();
343: Thread.currentThread().sleep(sleepTime);
344: if (isCanceled()) {
345: return;
346: }
347: } catch (InterruptedException ex) {
348: loop = false;
349: return;
350: } catch (Exception ex) {
351: loop = false;
352: String trace = Util.getStackTrace(ex);
353: logEvent(this , Log.DBG, trace);
354: logEvent(this , Log.ERROR, trace);
355: return;
356: }
357: }
358: logEvent(this , Log.DBG, "Finished loop loop:" + loop);
359: }
360:
361: public void finish() {
362: loop = false;
363: mos.setStatusDetail("");
364: logEvent(this , Log.DBG, "Finishing");
365: ;
366: if (!mos.isCanceled()) {
367: mos.setStatusDescription("");
368: } else {
369: String statusDesc = resolveString("$L(org.netbeans.installer.Bundle, ProgressPanel.installationCancelled)");
370: mos.setStatusDescription(statusDesc);
371: mos.getProgress().setPercentComplete(0);
372: }
373:
374: }
375:
376: /** Check if the operation is canceled. */
377: private boolean isCanceled() {
378: if (mos.isCanceled() && loop) {
379: logEvent(this , Log.DBG, "MOS is cancelled");
380: loop = false;
381: }
382:
383: return mos.isCanceled();
384: }
385:
386: /** Updates the progress bar. */
387: private void updateProgressBar() {
388: if (isCanceled()) {
389: return;
390: }
391: long size = unpackJars.getProgressInfo()
392: .getCompletedBytes();
393: long perc = (size * (100 - percentageStart)) / checksum;
394: logEvent(this , Log.DBG, "installed size = " + size
395: + " perc = " + perc);
396: if (perc <= percentageCompleted) {
397: return;
398: }
399: long increment = perc - percentageCompleted;
400: mos.updatePercentComplete(ESTIMATED_TIME, increment, 100L);
401: mos.setStatusDetail(unpackJars.getProgressInfo()
402: .getFileName());
403: percentageCompleted = perc;
404: }
405:
406: }
407:
408: }
|