source: trunk/gli/src/org/greenstone/gatherer/WGet.java@ 10517

Last change on this file since 10517 was 9646, checked in by mdewsnip, 19 years ago

Removed an unused function containing a lot of weird hard-wired scms URLs.

  • Property svn:keywords set to Author Date Id Revision
File size: 12.7 KB
Line 
1/**
2 *#########################################################################
3 *
4 * A component of the Gatherer application, part of the Greenstone digital
5 * library suite from the New Zealand Digital Library Project at the
6 * University of Waikato, New Zealand.
7 *
8 * <BR><BR>
9 *
10 * Author: John Thompson, Greenstone Digital Library, University of Waikato
11 *
12 * <BR><BR>
13 *
14 * Copyright (C) 1999 New Zealand Digital Library Project
15 *
16 * <BR><BR>
17 *
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 2 of the License, or
21 * (at your option) any later version.
22 *
23 * <BR><BR>
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * <BR><BR>
31 *
32 * You should have received a copy of the GNU General Public License
33 * along with this program; if not, write to the Free Software
34 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
35 *########################################################################
36 */
37package org.greenstone.gatherer;
38
39import java.awt.*;
40import java.io.*;
41import java.net.*;
42import java.util.*;
43import javax.swing.*;
44import javax.swing.tree.*;
45import org.greenstone.gatherer.collection.DownloadJob;
46
47/** This class provides access to the functionality of the WGet program, either by calling it via a shell script or by the JNI. It maintains a queue of pending jobs, and the component for showing these tasks to the user.
48 * @author John Thompson, Greenstone Digital Library, University of Waikato
49 * @version 2.3
50 */
51public class WGet
52 extends Thread {
53
54 /** <i>true</i> if there is a task currently being carried out, <i>false</i> otherwise. */
55 private boolean busy = false;
56 /** <i>true</i> if verbose debug messages should be displayed, <i>false</i> otherwise. */
57 private boolean debug = false;
58 /** <i>true</i> if successfully completed tasks should be automatically removed from the job queue. */
59 private boolean remove_complete_jobs = true;
60
61 private JPanel filler_pane = null;
62 /** The panel that the task list will be shown in. */
63 private JPanel list_pane;
64 /** The job currently underway. */
65 private DownloadJob job;
66 /** A scroll pane which will be used to display the list of pending tasks. */
67 private JScrollPane list_scroll;
68 /** A queue of download tasks. */
69 private Vector job_queue;
70 /** A static flag used to switch between simple and advanced modes. If <i>true</i> the Process object is used to externally call the Wget program. If <i>false</i> the native WGet libraries are statically loaded and the JNI used to download directly. */
71 static final private boolean simple = true;
72 /** Load the WGet native library. */
73 static {
74 if(!simple) {
75 System.load(System.getProperty("user.dir") + File.separator + "libgatherer.so");
76 }
77 }
78
79 /** Constructor. Nothing special. */
80 public WGet() {
81 job = null;
82 job_queue = new Vector();
83 filler_pane = new JPanel();
84 list_pane = new JPanel();
85 list_pane.setLayout(new BoxLayout(list_pane, BoxLayout.Y_AXIS));
86 //list_pane.setLayout(new GridLayout(height_count,1));
87 list_scroll = new JScrollPane(list_pane);
88 //list_scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
89 }
90
91 /** Called by the WGet native code to inform us of a new download starting within the given job.
92 * @param url The url that is being downloaded, as a <strong>String</strong>.
93 * @see org.greenstone.gatherer.collection.DownloadJob
94 */
95 public synchronized void addDownload(String url) {
96 job.addDownload(url);
97 }
98
99 /* Used to advise the DownloadJob of a newly parsed link. Its up to DownloadJob to decide if it already knows about this url, and if not to update its progress bar.
100 * @param url The url in question as a <strong>String</strong>.
101 * @param type <i>true</i> if this is an internal link, <i>false</i> for and external one.
102 * @return A <i>boolean</i> with a value of <i>true</i> indicating if the url was added, <i>false</i> otherwise.
103 * @see org.greenstone.gatherer.collection.DownloadJob
104 */
105 public synchronized boolean addLink(String url, int type) {
106 return job.addLink(url, type);
107 }
108
109
110 /** This method is called to delete a certain job from the queue.
111 * This job may be pending, complete or even in progress. However
112 * if it is currently downloading then the delete method must
113 * wait until the native job has cleanly exited before removing
114 * the job.
115 * @param delete_me The <strong>DownloadJob</strong> that is to be deleted.
116 */
117 public void deleteDownloadJob(DownloadJob delete_me) {
118 if (delete_me == job) {
119 // While this seems wasteful its only for the briefest moment.
120 while(busy) {
121 }
122 job = null;
123 }
124 if (delete_me.hasSignalledStop()) {
125 list_pane.remove(delete_me.getProgressBar());
126 job_queue.remove(delete_me);
127 // Unfortunately removing a task gets a bit more complicated as we have to resize the filler
128 list_pane.remove(filler_pane);
129 if(job_queue.size() > 0) {
130 Dimension progress_bar_size = delete_me.getProgressBar().getPreferredSize();
131 Dimension list_pane_size = list_pane.getSize();
132 int height = list_pane_size.height - (job_queue.size() * progress_bar_size.height);
133 progress_bar_size = null;
134 if(height > 0) {
135 filler_pane.setPreferredSize(new Dimension(list_pane_size.width, height));
136 list_pane.add(filler_pane);
137 }
138 list_pane_size = null;
139 }
140 list_pane.updateUI();
141 }
142 else {
143 DebugStream.println("Somehow we're trying to delete a job that is still running.");
144 }
145 }
146
147 /** Called by the WGet native code when the current download,
148 * for the indicated job, is completed. In turn all download
149 * listeners are informed.
150 * @see org.greenstone.gatherer.collection.DownloadJob
151 */
152 public synchronized void downloadComplete() {
153 job.downloadComplete();
154 }
155
156 /** Called by the WGet native code when the requested download returns
157 * a status code other than 200-399 for the specified download job.
158 * for.
159 * @see org.greenstone.gatherer.collection.DownloadJob
160 */
161 public synchronized void downloadFailed() {
162 // Add the failed download as a new job if the user so requests.
163 job.downloadFailed();
164 }
165
166 /** Called by the WGet native code when some non-fatal error has caused
167 * a download to fail. An example of a warning would be if a file can't
168 * be downloaded as doing so would clobber an existing file and the -nc
169 * flag is set.
170 * @see org.greenstone.gatherer.collection.DownloadJob
171 */
172 public synchronized void downloadWarning() {
173 job.downloadWarning();
174 }
175
176 /** Used by other graphic functions to get a reference to the
177 * scroll pane containing the current list of jobs.
178 */
179 public JScrollPane getDownloadJobList() {
180 return list_scroll;
181 }
182
183 /** Returns the current state of the stop flag for the job indicated.
184 * @return A boolean representing whether the user has requested to
185 * stop.
186 * @see org.greenstone.gatherer.collection.DownloadJob
187 */
188 public synchronized boolean hasSignalledStop() {
189 return job.hasSignalledStop();
190 }
191
192 /** Creates a new mirroring job on the queue given the target url and the destination (private, public). All other details are harvested from the config file, but these two must be captured from the GUI's current state.
193 * @param no_parents
194 * @param other_hosts
195 * @param page_requisites
196 * @param url a URL which points to the root url for the mirroring
197 * @param depth
198 * @param destination the destination file as a String
199 * @see org.greenstone.gatherer.Configuration
200 * @see org.greenstone.gatherer.collection.DownloadJob
201 * @see org.greenstone.gatherer.gui.DownloadProgressBar
202 * @see org.greenstone.gatherer.util.GURL
203 */
204 public void newDownloadJob(boolean no_parents, boolean other_hosts, boolean page_requisites, URL url, int depth, String destination) {
205 // Create the job and fill in the details from gatherer.config.
206 DebugStream.println("About to create a new job");
207
208 DownloadJob new_job = new DownloadJob(Configuration.get("mirroring.debug", false), no_parents, other_hosts, page_requisites, Configuration.get("mirroring.quiet", false), url, depth, destination, Configuration.proxy_pass, Configuration.proxy_user, this, simple);
209
210 // Tell it to run as soon as possible
211 new_job.setState(DownloadJob.RUNNING);
212
213 // Add to job_queue job list.
214 job_queue.add(new_job);
215 // Now add it to the visual component, job list.
216 list_pane.remove(filler_pane);
217 Dimension progress_bar_size = new_job.getProgressBar().getPreferredSize();
218 Dimension list_pane_size = list_pane.getSize();
219 int height = list_pane_size.height - (job_queue.size() * progress_bar_size.height);
220 progress_bar_size = null;
221 list_pane.add(new_job.getProgressBar());
222 if(height > 0) {
223 filler_pane.setPreferredSize(new Dimension(list_pane_size.width, height));
224 list_pane.add(filler_pane);
225 }
226 list_pane_size = null;
227 //list_pane.setAlignmentX(Component.LEFT_ALIGNMENT);
228 list_pane.updateUI();
229 new_job = null;
230 synchronized(this) {
231 notify(); // Just incase its sleeping.
232 }
233 }
234
235 /** Called by the WGet native code to signal the current progress of
236 * downloading for the specified job.
237 * @param current A long representing the number of bytes that have
238 * been downloaded since the last update.
239 * @param expected A long representing the total number of bytes
240 * expected for this download.
241 * @see org.greenstone.gatherer.collection.DownloadJob
242 */
243 public synchronized void updateProgress(long current, long expected) {
244 job.updateProgress(current, expected);
245 }
246
247 /* There may be times when the download thread is sleeping, but the
248 * user has indicated that a previously paused job should now begin
249 * again. The flag within the job will change, so we tell the thread
250 * to start again.
251 */
252 public void resumeThread() {
253 synchronized(this) {
254 notify(); // Just incase its sleeping.
255 }
256 }
257
258 /* This begins the WGet thread, which simply iterates through the waiting
259 * jobs attempting each one. Successful downloads are removed from the
260 * waiting list.
261 * @see org.greenstone.gatherer.collection.DownloadJob
262 */
263 public void run() {
264 while(true) {
265 // If there are jobs job_queue and we have more room.
266 if(job_queue.size() > 0) {
267 int index = 0;
268 while(job_queue.size() > 0 && index < job_queue.size()) {
269 // Get the first job that isn't stopped.
270 job = (DownloadJob) job_queue.get(index);
271 if(job.getState() == DownloadJob.RUNNING) {
272 DebugStream.println("DownloadJob " + job.toString() + " Begun.");
273 // A lock to prevent us deleting this job while its being
274 // run, unless you want things to go really wrong.
275 busy = true;
276 if(simple) {
277 job.callWGet();
278 }
279 else {
280 job.callWGetNative();
281 }
282 busy = false;
283 DebugStream.println("DownloadJob " + job.toString() + " complete.");
284 // And if the user has requested that complete jobs
285 // be removed, then remove it from the list.
286 //deleteDownloadJob(job);
287 job = null;
288 }
289 index++;
290 }
291 }
292 // In order to save processor time, I'll suspend the thread
293 // if theres no advantage to it running. Actions such as
294 // new or complete jobs will resume the thread.
295 else {
296 try {
297 synchronized(this) {
298 DebugStream.println("WGet thread is waiting for DownloadJobs.");
299 wait();
300 }
301 } catch (InterruptedException e) {
302 // Time to get going again.
303 }
304 }
305 } // End While.
306 }
307
308 /* Link to the call to the WGet Native method for downloading.
309 * @param argc An int representing the number of elements in argv.
310 * @param argv An array of objects passed as arguments to wget.
311 * @param debug Whether the native code should show java-only debug
312 * messages.
313 */
314 public native int wget(int argc, Object argv[], boolean debug);
315
316 /* Link to the call to the WGet Native method for converting url links.
317 * @param argc An int representing the number of object elements in argv.
318 * @param argv An array of objects passed as arguments to wget.
319 * @param urlc An int representing the number of url string elements in urlv.
320 * @param urlv An array of strings representing urls.
321 * @param filec An int representing the number of file string elements in filev.
322 * @param filev An array of strings representing files.
323 */
324 public native void wren(int argc, Object argv[], int urlc, Object urlv[], int filec, Object filev[]);
325}
Note: See TracBrowser for help on using the repository browser.