UI not updated while using ProgressMonitorInputStream in Swing to monitor compressed file decompress

Posted by Bozhidar Batsov on Stack Overflow See other posts from Stack Overflow or by Bozhidar Batsov
Published on 2010-05-12T08:52:41Z Indexed on 2010/05/12 9:24 UTC
Read the original article Hit count: 269

Filed under:
|

I'm working on swing application that relies on an embedded H2 database. Because I don't want to bundle the database with the app(the db is frequently updated and I want new users of the app to start with a recent copy), I've implemented a solution which downloads a compressed copy of the db the first time the application is started and extracts it. Since the extraction process might be slow I've added a ProgressMonitorInputStream to show to progress of the extraction process - unfortunately when the extraction starts, the progress dialog shows up but it's not updated at all. It seems like to events are getting through to the event dispatch thread. Here is the method:

public static String extractDbFromArchive(String pathToArchive) {
    if (SwingUtilities.isEventDispatchThread()) {
        System.out.println("Invoking on event dispatch thread");
    }

    // Get the current path, where the database will be extracted
    String currentPath = System.getProperty("user.home") + File.separator + ".spellbook" + File.separator;
    LOGGER.info("Current path: " + currentPath);

    try {
        //Open the archive
        FileInputStream archiveFileStream = new FileInputStream(pathToArchive);
        // Read two bytes from the stream before it used by CBZip2InputStream

        for (int i = 0; i < 2; i++) {
            archiveFileStream.read();
        }

        // Open the gzip file and open the output file
        CBZip2InputStream bz2 = new CBZip2InputStream(new ProgressMonitorInputStream(
                              null,
                              "Decompressing " + pathToArchive,
                              archiveFileStream));
        FileOutputStream out = new FileOutputStream(ARCHIVED_DB_NAME);

        LOGGER.info("Decompressing the tar file...");
        // Transfer bytes from the compressed file to the output file
        byte[] buffer = new byte[1024];
        int len;
        while ((len = bz2.read(buffer)) > 0) {
            out.write(buffer, 0, len);
        }

        // Close the file and stream
        bz2.close();
        out.close();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException ex) {
        ex.printStackTrace();
    }

    try {
        TarInputStream tarInputStream = null;
        TarEntry tarEntry;
        tarInputStream = new TarInputStream(new ProgressMonitorInputStream(
                              null,
                              "Extracting " + ARCHIVED_DB_NAME,
                              new FileInputStream(ARCHIVED_DB_NAME)));

        tarEntry = tarInputStream.getNextEntry();

        byte[] buf1 = new byte[1024];

        LOGGER.info("Extracting tar file");

        while (tarEntry != null) {
            //For each entry to be extracted
            String entryName = currentPath + tarEntry.getName();
            entryName = entryName.replace('/', File.separatorChar);
            entryName = entryName.replace('\\', File.separatorChar);

            LOGGER.info("Extracting entry: " + entryName);
            FileOutputStream fileOutputStream;
            File newFile = new File(entryName);
            if (tarEntry.isDirectory()) {
                if (!newFile.mkdirs()) {
                    break;
                }
                tarEntry = tarInputStream.getNextEntry();
                continue;
            }

            fileOutputStream = new FileOutputStream(entryName);
            int n;
            while ((n = tarInputStream.read(buf1, 0, 1024)) > -1) {
                fileOutputStream.write(buf1, 0, n);
            }

            fileOutputStream.close();
            tarEntry = tarInputStream.getNextEntry();

        }
        tarInputStream.close();
    } catch (Exception e) {
    }

    currentPath += "db" + File.separator + DB_FILE_NAME;

    if (!currentPath.isEmpty()) {
        LOGGER.info("DB placed in : " + currentPath);
    }

    return currentPath;
}

This method gets invoked on the event dispatch thread (SwingUtilities.isEventDispatchThread() returns true) so the UI components should be updated. I haven't implemented this as an SwingWorker since I need to wait for the extraction anyways before I can proceed with the initialization of the program. This method get invoked before the main JFrame of the application is visible. I don't won't a solution based on SwingWorker + property changed listeners - I think that the ProgressMonitorInputStream is exactly what I need, but I guess I'm not doing something right. I'm using Sun JDK 1.6.18. Any help would be greatly appreciated.

© Stack Overflow or respective owner

Related posts about java

Related posts about swing