001    /*
002            Copyright (C) 2003 Adam Olsen
003    
004            This program is free software; you can redistribute it and/or modify
005            it under the terms of the GNU General Public License as published by
006            the Free Software Foundation; either version 1, or (at your option)
007            any later version.
008    
009            This program is distributed in the hope that it will be useful,
010            but WITHOUT ANY WARRANTY; without even the implied warranty of
011            MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
012            GNU General Public License for more details.
013    
014            You should have received a copy of the GNU General Public License
015            along with this program; if not, write to the Free Software
016            Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
017    */
018    
019    package com.valhalla.pluginmanager;
020    
021    import javax.swing.*;
022    import java.awt.*;
023    import java.awt.event.*;
024    import java.io.*;
025    import java.net.*;
026    import java.util.*;
027    import com.valhalla.gui.*;
028    
029    /**
030     * Downloads plugins
031     *
032     * @author Adam Olsen
033     * @version 1.0
034    */
035    public class PluginDownloaderThread implements Runnable
036    {
037            private ResourceBundle resources =
038                    ResourceBundle.getBundle( "PluginManager", Locale.getDefault() );
039    
040            private PluginManager manager = null;
041            private ProgressDialog progress = null;
042            private ArrayList list = null;
043            private double size = 0;
044            private String mirror, script, installDir;
045            private boolean cancelled = false;
046    
047            /**
048             * Sets up the thread
049             * @param manager the PluginManager that contains this thread
050             * @param list the list of plugins to download
051             * @param progress the dialog that tracks this threads progress
052            */
053            public PluginDownloaderThread( PluginManager manager, ArrayList list )
054            {
055                    this.manager = manager;
056                    this.list = list;
057    
058                    mirror = manager.getMirror();
059                    script = manager.getScript();
060                    installDir = manager.getInstallDir();
061    
062                    size = calculateSize( list );
063    
064                    this.progress = new ProgressDialog( resources.getString( "downloading" ), 0, (int)size + 1 );
065                    JButton button = this.progress.getButton();
066                    button.addActionListener( new ActionListener()
067                    {
068                            public void actionPerformed( ActionEvent e ) { progress.delete(); cancelled = true; }
069                    } );
070            }
071    
072            /**
073             * Called by the enclosing Thread
074            */
075            public void run()
076            {
077                    if( size <= 0.0 )
078                    {
079                            manager.throwError( "selectPlugins", true );
080                            progress.delete();
081    
082                            return;
083                    }
084    
085                    Socket socket = null;
086                    PrintWriter out = null;
087                    InputStream in = null;
088                    BufferedReader bIn = null;
089    
090    
091                    File cacheDir = new File( installDir, "downloadcache" );
092                    if( !cacheDir.isDirectory() && !cacheDir.mkdirs() )
093                    {
094                            progress.delete();
095                            manager.throwError( "couldNotCreateCache", true );
096                            return;
097                    }
098    
099                    try {
100                            int totalRead = 0;
101    
102                            for( int i = 0; i < list.size(); i++ )
103                            {
104                                    if( cancelled ) return;
105                                    Properties props = (Properties)list.get( i );
106                                    if( props.getProperty( "selected" ) != null )
107                                    {
108                                            socket = new Socket( mirror, 80 );
109                                            out = new PrintWriter( socket.getOutputStream(), true );
110                                            in = socket.getInputStream();
111    
112                                            File outFile = new File( cacheDir, props.getProperty( "fileName" ) );
113                                            int pluginSize = Integer.parseInt( props.getProperty( "size" ) );
114                                            FileOutputStream fileOut = new FileOutputStream( outFile );
115    
116                                            out.println( "GET " + script + "?command=getPlugin&apiVersion=" +
117                                                    PluginLoader.getAPIVersion() + "&plugin=" + props.getProperty( "fileName" ) + " HTTP/1.0" );
118                                            out.println( "Host: " + mirror + "\n" );
119    
120                                            String checkString = null;
121                                            int checkCount = 0;
122                                            while( true )
123                                            {
124                                                    char c = (char)in.read();
125                                                    if( c == -1 ) break;
126                                                    checkString += c;
127                                                    if( checkString.length() >= 4 &&
128                                                            checkString.substring( checkString.length() - 4 ).equals( "\r\n\r\n" ) ) break;
129                                            }
130    
131                                            int readSize = 0;
132                                            int totalSize = 0;
133                                            byte buf[] = new byte[1024];
134    
135                                            while( true )
136                                            {
137                                                    if( cancelled )
138                                                    {
139                                                            in.close();
140                                                            fileOut.close();
141                                                            return;
142                                                    }
143    
144                                                    readSize = in.read( buf, 0, 1024 );
145                                                    if( readSize == -1 ) break;
146    
147                                                    fileOut.write( buf, 0, readSize );
148                                                    totalRead += readSize;
149                                                    totalSize += readSize;
150    
151                                                    final int tempSize = totalRead;
152                                                    SwingUtilities.invokeLater( new Runnable()
153                                                    {
154                                                            public void run()
155                                                            {
156                                                                    progress.setValue( tempSize );
157                                                                    progress.repaint();
158                                                            }
159                                                    } );
160                                            }
161    
162                                            fileOut.close();
163    
164                                            if( cancelled ) return;
165    
166                                            if( totalSize != pluginSize )
167                                            {
168                                                    com.valhalla.Logger.debug( pluginSize + " " + totalSize );
169                                                    manager.throwError( "downloadError", true );
170                                                    progress.delete();
171                                                    return;
172                                            }
173    
174                                            socket.close();
175                                    }
176                            }
177    
178                    }
179                    catch( Exception e )
180                    {
181                            manager.throwError( e.getMessage(), false );
182                            progress.delete();
183                            return;
184                    }
185    
186                    if( cancelled ) return;
187    
188                    progress.delete();
189    
190                    SwingUtilities.invokeLater( new Runnable()
191                    {
192                            public void run()
193                            {
194                                    manager.doneDownloadingPlugins( list );
195                            }
196                    } );
197            }
198    
199            /**
200             * Gets the size of the selected plugins in an array
201             * @param list the plugin list
202             * @return the size of the selected plugins
203            */
204            public static double calculateSize( ArrayList list )
205            {
206                    double size = 0;
207                    for( int i = 0; i < list.size(); i++ )
208                    {
209                            Properties p = (Properties)list.get( i );
210                            if( p.getProperty( "selected" ) != null )
211                            {
212                                    try {
213                                            double s = Double.parseDouble( p.getProperty( "size" ) );
214                                            size += s;
215                                    }
216                                    catch( Exception e ) { e.printStackTrace(); }
217                            }
218                    }
219    
220                    return size;
221            }
222    }