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 java.awt.event.ActionEvent;
022    import java.awt.event.ActionListener;
023    import java.io.BufferedReader;
024    import java.io.File;
025    import java.io.FileOutputStream;
026    import java.io.InputStream;
027    import java.io.PrintWriter;
028    import java.net.Socket;
029    import java.net.URL;
030    import java.net.ConnectException;
031    import java.util.ArrayList;
032    import java.util.Locale;
033    import java.util.Properties;
034    import java.util.ResourceBundle;
035    
036    import javax.swing.*;
037    
038    import com.valhalla.gui.ProgressDialog;
039    
040    /**
041     * Downloads plugins
042     *
043     * @author Adam Olsen
044     * @version 1.0
045     */
046    public class PluginDownloaderThread implements Runnable {
047        private ResourceBundle resources = ResourceBundle.getBundle(
048                "PluginManager", Locale.getDefault());
049    
050        private PluginManager manager = null;
051    
052        private ProgressDialog progress = null;
053    
054        private ArrayList list = null;
055    
056        private double size = 0;
057    
058        private String mirror, script, installDir;
059    
060        private boolean cancelled = false;
061    
062        /**
063         * Sets up the thread
064         *
065         * @param manager
066         *            the PluginManager that contains this thread
067         * @param list
068         *            the list of plugins to download
069         * @param progress
070         *            the dialog that tracks this threads progress
071         */
072        public PluginDownloaderThread(PluginManager manager, ArrayList list) {
073            this.manager = manager;
074            this.list = list;
075    
076            mirror = manager.getMirror();
077            script = manager.getScript();
078            installDir = manager.getInstallDir();
079    
080            size = calculateSize(list);
081    
082            this.progress = new ProgressDialog(manager, resources
083                    .getString("downloading"), 0, (int) size + 1);
084            JButton button = this.progress.getButton();
085            button.addActionListener(new ActionListener() {
086                public void actionPerformed(ActionEvent e) {
087                    progress.delete();
088                    cancelled = true;
089                }
090            });
091        }
092    
093        /**
094         * Called by the enclosing Thread
095         */
096        public void run() {
097            if (size <= 0.0) {
098                manager.throwError("selectPlugins", true);
099                progress.delete();
100    
101                return;
102            }
103    
104            InputStream in = null;
105            BufferedReader bIn = null;
106    
107            File cacheDir = new File(installDir, "downloadcache");
108            if (!cacheDir.isDirectory() && !cacheDir.mkdirs()) {
109                progress.delete();
110                manager.throwError("couldNotCreateCache", true);
111                return;
112            }
113    
114            try {
115                int totalRead = 0;
116    
117                for (int i = 0; i < list.size(); i++) {
118                    if (cancelled)
119                        return;
120                    Properties props = (Properties) list.get(i);
121                    if (props.getProperty("selected") != null) {
122    
123                        URL url = new URL("http://" + mirror + script +
124                            "?command=getPlugin&apiVersion=" + PluginLoader.getAPIVersion()
125                            + "&plugin=" + props.getProperty("fileName"));
126                        System.out.println("accessing URL:" + url);
127                        in = url.openStream();
128    
129                        File outFile = new File(cacheDir, props
130                                .getProperty("fileName"));
131                        int pluginSize = Integer
132                                .parseInt(props.getProperty("size"));
133                        FileOutputStream fileOut = new FileOutputStream(outFile);
134    
135                        int readSize = 0;
136                        int totalSize = 0;
137                        byte buf[] = new byte[1024];
138    
139                        while (true) {
140                            if (cancelled) {
141                                in.close();
142                                fileOut.close();
143                                return;
144                            }
145    
146                            readSize = in.read(buf, 0, 1024);
147                            if (readSize == -1)
148                                break;
149    
150                            fileOut.write(buf, 0, readSize);
151                            totalRead += readSize;
152                            totalSize += readSize;
153    
154                            final int tempSize = totalRead;
155                            SwingUtilities.invokeLater(new Runnable() {
156                                public void run() {
157                                    progress.setValue(tempSize);
158                                    progress.repaint();
159                                }
160                            });
161                        }
162    
163                        fileOut.close();
164    
165                        if (cancelled)
166                            return;
167    
168                        if (totalSize != pluginSize) {
169                            com.valhalla.Logger.debug(pluginSize + " " + totalSize);
170                            manager.throwError("downloadError", true);
171                            progress.delete();
172                            return;
173                        }
174    
175                        in.close();
176                    }
177                }
178    
179            } catch (ConnectException e) {
180                JOptionPane.showMessageDialog(null,
181                    resources.getString("couldNotConnectThroughProxy"),
182                    resources.getString("connectionError"),
183                    JOptionPane.ERROR_MESSAGE);
184            } catch (Exception e) {
185                manager.throwError(e.getMessage(), false);
186                progress.delete();
187                return;
188            }
189    
190            if (cancelled)
191                return;
192    
193            progress.delete();
194    
195            SwingUtilities.invokeLater(new Runnable() {
196                public void run() {
197                    manager.doneDownloadingPlugins(list);
198                }
199            });
200        }
201    
202        /**
203         * Gets the size of the selected plugins in an array
204         *
205         * @param list
206         *            the plugin list
207         * @return the size of the selected plugins
208         */
209        public static double calculateSize(ArrayList list) {
210            double size = 0;
211            for (int i = 0; i < list.size(); i++) {
212                Properties p = (Properties) list.get(i);
213                if (p.getProperty("selected") != null) {
214                    try {
215                        double s = Double.parseDouble(p.getProperty("size"));
216                        size += s;
217                    } catch (Exception e) {
218                        e.printStackTrace();
219                    }
220                }
221            }
222    
223            return size;
224        }
225    }