alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 *                 Sun Public License Notice
 * 
 * The contents of this file are subject to the Sun Public License
 * Version 1.0 (the "License"). You may not use this file except in
 * compliance with the License. A copy of the License is available at
 * http://www.sun.com/
 * 
 * The Original Code is NetBeans. The Initial Developer of the Original
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2004 Sun
 * Microsystems, Inc. All Rights Reserved.
 */

package org.netbeans.modules.autoupdate;

import java.io.*;
import java.net.URLConnection;
import java.text.MessageFormat;
import java.util.jar.*;
import java.util.Iterator;
import java.util.List;
import org.netbeans.updater.UpdateTracking;

import org.openide.DialogDisplayer;

import org.openide.util.NbBundle;
import org.openide.NotifyDescriptor;

/** This class downloads modules and verifies the digital signatures
 * this class also copyies the downloaded modules.
 * @author  phrebejk
 */
class Downloader extends Object {

    /** The update check progress panel */
    ProgressDialog progressDialog;
    /** Set to true if the download was canceled by the user */
    private volatile boolean downloadCanceled;
    /** Total size of the download */
    private int downloadSize;
    /** KBytes downloaded */
    private long totalDownloaded;
    /** Number of modules to downaload */
    private long modulesCount;
    /** Shoud internet download be performed */
    private boolean urlDownload;

    /** Extension of the distribution files */
    private static final String NBM_EXTENSION = "nbm"; // NOI18N

    /** Wizard validator, enables the Next button in wizard */
    private Wizard.Validator validator;


    /** Creates new Downloader */
    public Downloader( ProgressDialog progressDialog,
                       Wizard.Validator validator, boolean urlDownload ) {
        this.validator = validator;
        this.progressDialog = progressDialog;
        this.urlDownload = urlDownload;
    }

    void doDownload() {

        downloadCanceled = false;

        Runnable task = new Runnable () {
                            public void run() {

                                progressDialog.setLabelText( ProgressDialog.PARTIAL_LABEL,
                                                             getBundle( "CTL_PreparingDownload_Label" ) );

                                downloadSize = getTotalDownloadSize();

                                if ( downloadCanceled )
                                    return;

                                downloadAll();

                                if ( downloadCanceled )
                                    return;

                                validator.setValid( true );
                            }
                        };

        Wizard.getRequestProcessor().post( task );
    }

    /** Total size of download in KBytes */
    int getTotalDownloadSize( ) {
        long result = 0L;
        modulesCount = 0;

        Iterator it = Wizard.getAllModules().iterator();

        while( it.hasNext() ) {
            ModuleUpdate mu = (ModuleUpdate)it.next();

            if ( mu.isSelected() && !mu.isDownloadOK() ) {
                result += mu.getDownloadSize();
                modulesCount++;
            }
        }
        return (int)(result / 1024);
    }


    /** Downloads the modules from web */
    private void downloadAll() {

        if ( downloadCanceled )
            return;

        progressDialog.setGaugeBounds( ProgressDialog.OVERALL_GAUGE, 0, downloadSize );
        progressDialog.setGaugeValue( ProgressDialog.OVERALL_GAUGE, 0 );
        progressDialog.setLabelText( ProgressDialog.OVERALL_LABEL, "" ); // NOI18N

        progressDialog.setGaugeValue( ProgressDialog.PARTIAL_GAUGE, 0 );

        int currentModule = 0;

        totalDownloaded = 0;

        Iterator it = Wizard.getAllModules().iterator();

        long start_time = System.currentTimeMillis();

        while( it.hasNext() ) {

            if ( downloadCanceled )
                return;

            ModuleUpdate mu = (ModuleUpdate)it.next();
            if ( mu.isSelected() && !mu.isDownloadOK() ) {
                progressDialog.setGaugeValue( ProgressDialog.PARTIAL_GAUGE, 0 );
                progressDialog.setLabelText( ProgressDialog.PARTIAL_LABEL,
                                             mu.getName() + " [" + (currentModule + 1) + "/" + modulesCount + "]" ); // NOI18N
                if ( urlDownload )
                    download( start_time, mu );
                else
                    downloadFromLocal( start_time, mu );
                currentModule++;
            }
        }

        progressDialog.setGaugeValue( ProgressDialog.OVERALL_GAUGE,  downloadSize );
        String mssgTotal = MessageFormat.format( getBundle( "FMT_DownloadedTotal" ),
                           new Object[] { new Integer( downloadSize ),
                                          new Integer( downloadSize ) } );
        progressDialog.setLabelText( ProgressDialog.OVERALL_LABEL, mssgTotal );

    }

    /** Downloads a .NBM file into download directory
    */
    private void download( long start_time, ModuleUpdate moduleUpdate ) {

        // throws java.io.IOException {

        int moduleDownloaded = 0;
        int flen = 0;

        while ( true ) {    // Retry loop

            File destFile = null;
            try {

                URLConnection distrConnection = null;
                distrConnection = moduleUpdate.getDistribution().openConnection();
                flen = distrConnection.getContentLength();
                moduleUpdate.setRemoteDistributionFilename(distrConnection);

                if ( downloadCanceled )
                    return;

                moduleDownloaded = 0;

                progressDialog.setGaugeBounds( ProgressDialog.PARTIAL_GAUGE, 0, flen / 1024 );

                moduleUpdate.setDownloadStarted( true );
                
                destFile = getNBM( moduleUpdate );

                BufferedInputStream bsrc = new BufferedInputStream( distrConnection.getInputStream() );
                BufferedOutputStream bdest = new BufferedOutputStream( new FileOutputStream( destFile ) );

                int c;
                int i = 0;

                try {
                    while( ( c = bsrc.read() ) != -1 ) {
                        bdest.write( c );

                        moduleDownloaded++;
                        totalDownloaded++;

                        if ( downloadCanceled )
                            return;

                        if ( moduleDownloaded % 4096 == 0 ) {
                            updateOverall();
                            progressDialog.setGaugeValue( ProgressDialog.PARTIAL_GAUGE, moduleDownloaded / 1024 );
                        }
                    }
                }
                finally {
                    if (bsrc != null) bsrc.close();
                    if (bdest != null) bdest.close();
                    if ( downloadCanceled )
                        getNBM( moduleUpdate ).delete();
                }
            } catch ( NullPointerException x ) {
                x.printStackTrace();
                
                // Download failed
                
                String mssg = MessageFormat.format( getBundle( "FMT_DownloadFailed" ),
                new Object[] { moduleUpdate.getName() } );
                NotifyDescriptor nd = new NotifyDescriptor.Confirmation ( mssg,
                getBundle( "CTL_DownloadFailed" ),
                NotifyDescriptor.YES_NO_CANCEL_OPTION );
                DialogDisplayer.getDefault().notify( nd );
                
                if ( nd.getValue().equals( NotifyDescriptor.YES_OPTION ) ) {
                    totalDownloaded -= moduleDownloaded; // Dont't count lost bytes
                    continue; // Retry
                }
                else if ( nd.getValue().equals( NotifyDescriptor.CANCEL_OPTION ) ) {
                    downloadCanceled = true; // Stop whole download
                    validator.setValid( true );
                    return;
                }
                // User selected not to download current module
                totalDownloaded -= moduleDownloaded; // Dont't count lost bytes
                downloadSize -= (int)(moduleUpdate.getDownloadSize() / 1024);
                if ( destFile != null )
                    destFile.delete();
                return;
            } catch ( IOException e ) {
                e.printStackTrace();

                // Download failed

                String mssg = MessageFormat.format( getBundle( "FMT_DownloadFailed" ),
                                                    new Object[] { moduleUpdate.getName() } );
                NotifyDescriptor nd = new NotifyDescriptor.Confirmation ( mssg,
                                      getBundle( "CTL_DownloadFailed" ),
                                      NotifyDescriptor.YES_NO_CANCEL_OPTION );
                DialogDisplayer.getDefault().notify( nd );

                if ( nd.getValue().equals( NotifyDescriptor.YES_OPTION ) ) {
                    totalDownloaded -= moduleDownloaded; // Dont't count lost bytes
                    continue; // Retry
                }
                else if ( nd.getValue().equals( NotifyDescriptor.CANCEL_OPTION ) ) {
                    downloadCanceled = true; // Stop whole download
                    validator.setValid( true );
                    return;
                }
                // User selected not to download current module
                totalDownloaded -= moduleDownloaded; // Dont't count lost bytes
                downloadSize -= (int)(moduleUpdate.getDownloadSize() / 1024);                
                if ( destFile != null )
                    destFile.delete();
                return;
            }

            //progressDialog.setGaugeValue( ProgressDialog.PARTIAL_GAUGE, (int)(moduleUpdate.getDownloadSize() / 1024 ) );
            progressDialog.setGaugeValue( ProgressDialog.PARTIAL_GAUGE, flen / 1024 + 10);
            moduleUpdate.setDownloadOK( true );
            return; // The module downloaded O.K.
        }
    }
    
    private void downloadFromLocal( long start_time, ModuleUpdate moduleUpdate ) {
        progressDialog.setGaugeBounds( ProgressDialog.PARTIAL_GAUGE, 0, 1 );
        if (downloadFromLocal (moduleUpdate)) {
            totalDownloaded += moduleUpdate.getDownloadSize();
            progressDialog.setGaugeValue( ProgressDialog.PARTIAL_GAUGE, 1);
        }
        updateOverall();
    }

    /** Copies the external NBM file into the appropriate location where 
     * Downloader can work with.
     *
     * @param moduleUpdate moduleupdate for local nbm
     * @return false if there was a problem
     */
    static boolean downloadFromLocal ( ModuleUpdate moduleUpdate ) {
        if ( tryCopy( moduleUpdate.getDistributionFile(), getNBM( moduleUpdate ) ) ) {
            moduleUpdate.setDownloadOK( true );
            return true;
        }
        else {
            getNBM( moduleUpdate ).delete();
            return false;
        }
    }
    
    private void updateOverall() {
        String mssgTotal = MessageFormat.format( getBundle( "FMT_DownloadedTotal" ),
                           new Object[] { new Integer( (int)(totalDownloaded / 1024) ),
                                          new Integer( downloadSize ) } );

        progressDialog.setGaugeValue( ProgressDialog.OVERALL_GAUGE, (int)(totalDownloaded / 1024) > downloadSize ?
                                      downloadSize : (int)( totalDownloaded / 1024 ) );
        progressDialog.setLabelText( ProgressDialog.OVERALL_LABEL, mssgTotal );
    }

    void cancelDownload() {
        downloadCanceled = true;
    }


    static File getNBM( ModuleUpdate mu ) {
        //File distrFile = new File(mu.getDistributionFileName() );
        //File destFile = new File( Autoupdater.Support.getDownloadDirectory(), distrFile.getName() );
        File destFile = new File( Autoupdater.Support.getDownloadDirectory (null), mu.getDistributionFilename() );
        return destFile;
    }
    
    static File getMovedNBM( ModuleUpdate mu ) {
        File destFile = null;
        if ( mu.isToInstallDir() )
            destFile = Autoupdater.Support.getDownloadDirectory (mu.findInstallDirectory ());
        else
            destFile = Autoupdater.Support.getDownloadDirectory (null);
        
        return new File (destFile, mu.getDistributionFilename());
    }

    static boolean tryMove( ModuleUpdate mu ) {            
        File inst = new File ( 
            Autoupdater.Support.getDownloadDirectory (mu.findInstallDirectory ()), 
            mu.getDistributionFilename()
        );
        
        boolean ok = getNBM( mu ).renameTo( inst );
        if ( ok )
            return true;
        
        // issue 21607
        ok = tryCopy( getNBM( mu ), inst );
        if ( ok )
            getNBM( mu ).delete();
        
        return ok;
    }
    
    static void saveCopy( ModuleUpdate mu, File target ) {
        tryCopy( getNBM( mu ), target );
    }
    
    private static boolean tryCopy( File src, File dest ) {
        BufferedInputStream bsrc = null;
        BufferedOutputStream bdest = null;

        try {
            try {
                bsrc = new BufferedInputStream( new FileInputStream( src ), 4096 );
                bdest = new BufferedOutputStream( new FileOutputStream( dest ), 4096 );

                int c;
                while( ( c = bsrc.read() ) != -1 ) {
                    bdest.write( c );
                }
            }
            finally {
                // workaround #39006, don't close a not opened stream
                if (bsrc != null) bsrc.close();
                if (bdest != null) bdest.close();
            }
        }
        catch ( IOException e ) {
            return false;
        }
        return true;
    }
    
    static void deleteModuleNBM( ModuleUpdate mu ) {
        getNBM( mu ).delete();
    }

    // Deletes all files in download directory
    static void deleteDownload() {
        boolean noTestPrepared = true;
        PreparedModules prepared = null;
        
        List/**/ clusters = UpdateTracking.clusters (true);
        assert clusters != null : "Clusters cannot be empty."; // NOI18N
        Iterator it =  clusters.iterator ();
        while (it.hasNext ()) {
            if (Autoupdater.Support.getInstall_Later ((File)it.next ()).exists ()) {
                noTestPrepared = false;
                prepared = PreparedModules.getPrepared();
            }
        }
        
        File[] nbms = getNBMFiles();

        for( int i = 0; i < nbms.length; i++ ) {
            if ( noTestPrepared || !prepared.hasNBM( nbms[i].getName() ) )
                nbms[i].delete();
        }
    }
    
    static boolean bannedWriteToInstall(ModuleUpdate mu) {
        File f = mu.findInstallDirectory ();
        
        return f == null || !f.canWrite();
    }

    private static File[] getNBMFiles() {
        File dirList[] = Autoupdater.Support.getDownloadDirectory (null).listFiles( new FilenameFilter() {
                             public boolean accept( File dir, String name ) {
                                 return name.endsWith( NBM_EXTENSION );
                             }
                         });

        return dirList;
    }

    private String getBundle( String key ) {
        return NbBundle.getMessage( Downloader.class, key );
    }
}
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.