source: main/trunk/gli/src/org/greenstone/gatherer/gui/DownloadPane.java@ 31593

Last change on this file since 31593 was 31593, checked in by ak19, 7 years ago

Porting the modifications for SafeProcess.java from GS3 src code to GLI. Now GLI also uses the new SafeProcess.CustomProcessHandler instead of the LineByLineHandler whose process flow may have been less transparent to developers. GLI's updated SafeProcess.java has now been tested successfully against DownloadPane, GS3ServerThread and FormatConversionDialog all of which use SafeProcess.java since yesterday. Things that worked still work.

  • Property svn:keywords set to Author Date Id Revision
File size: 28.6 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.gui;
38
39import java.awt.*;
40import java.awt.event.*;
41import java.io.*;
42import java.net.*;
43import java.util.*;
44import javax.swing.*;
45import javax.swing.border.*;
46import javax.swing.event.*;
47import javax.swing.tree.*;
48import org.greenstone.gatherer.Configuration;
49import org.greenstone.gatherer.DebugStream;
50import org.greenstone.gatherer.Dictionary;
51import org.greenstone.gatherer.Gatherer;
52import org.greenstone.gatherer.file.WorkspaceTree;
53import org.greenstone.gatherer.greenstone.LocalGreenstone;
54import org.greenstone.gatherer.util.SafeProcess;
55import org.greenstone.gatherer.util.StaticStrings;
56import org.greenstone.gatherer.util.Utility;
57import org.greenstone.gatherer.download.Download;
58import org.greenstone.gatherer.download.DownloadScrollPane;
59import org.greenstone.gatherer.download.ServerInfoDialog;
60import org.greenstone.gatherer.util.XMLTools;
61import org.greenstone.gatherer.cdm.*;
62import org.greenstone.gatherer.gui.*;
63import org.w3c.dom.*;
64import org.xml.sax.*;
65import org.greenstone.gatherer.GAuthenticator;
66
67/**
68 * @author John Thompson, Greenstone Digital Library, University of Waikato
69 * @version 2.1
70 */
71public class DownloadPane
72 extends JPanel {
73
74 static final private Dimension LABEL_SIZE = new Dimension(225, 25);
75 static final private Dimension TREE_SIZE = new Dimension(150, 500);
76 //static final private String CONTENTS[] = { "DOWNLOAD.MODE.WebDownload", "DOWNLOAD.MODE.MediaWikiDownload", "DOWNLOAD.MODE.OAIDownload", "DOWNLOAD.MODE.ZDownload" , "DOWNLOAD.MODE.SRWDownload"};
77 private String CONTENTS[] = null;
78
79 private boolean download_button_enabled = false;
80 private boolean ready = false;
81
82 private JPanel options_pane;
83 // TODO should use Vector to store all loaded downloads!!
84
85 private DesignTree tree;
86 private HashMap download_map;
87 private ServerInfoDialog server_info;
88 private JScrollPane list_scroll;
89 private DownloadScrollPane getter;
90 private String mode = null;
91 private TreePath previous_path;
92 private String proxy_url = "";
93
94 /** Main System code */
95 public DownloadPane() {
96 super();
97 JScrollPane scrol_tmp;
98 this.setComponentOrientation(Dictionary.getOrientation());
99 // TODO: Download the WDownload and the download panel fixed!!
100 getter = new DownloadScrollPane();
101 getter.start();
102 list_scroll = getter.getDownloadJobList();
103 list_scroll.setComponentOrientation(Dictionary.getOrientation());
104
105 // TODO should use Vector to store all loaded downloads!!
106 String lang = Configuration.getLanguage();
107 download_map = new HashMap();
108
109 // run downloadinfo.pl -describeall, load the downloaders into the download_map,
110 // and get back their list of names, which are of the form "<downloader>Download".
111 // Store these names in the CONTENTS[] array as "DOWNLOAD.MODE.<downloader>Download",
112 // with z3950 as a minor exception: DOWNLOAD.MODE.ZDownload.
113 ArrayList<String> downloaderNamesList = loadDownloadersInfo(lang);
114 int size = downloaderNamesList.size();
115 CONTENTS = new String[size];
116 for(int i = 0; i < size; i++) {
117 String downloadName = downloaderNamesList.get(i); // e.g. "WebDownload"
118 CONTENTS[i] = "DOWNLOAD.MODE."+downloadName.replace("3950", ""); // A special case is Z3950Download,
119 // which has to be stored in CONTENTS array as DOWNLOAD.MODE.ZDownload
120 }
121
122 // Creation
123 tree = new DesignTree();
124 tree.setComponentOrientation(Dictionary.getOrientation());
125 options_pane = new JPanel();
126 options_pane.setComponentOrientation(Dictionary.getOrientation());
127
128 JButton clear_cache_button = new GLIButton(Dictionary.get("Mirroring.ClearCache"), Dictionary.get("Mirroring.ClearCache_Tooltip"));
129 clear_cache_button.setEnabled(true);
130 clear_cache_button.setMnemonic(KeyEvent.VK_C);
131
132 JButton download_button = new GLIButton(Dictionary.get("Mirroring.Download"), Dictionary.get("Mirroring.Download_Tooltip"));
133 download_button.setEnabled(true);
134 download_button.setMnemonic(KeyEvent.VK_D);
135
136 JButton information_button = new GLIButton(Dictionary.get("Download.ServerInformation"), Dictionary.get("Download.ServerInformation_Tooltip"));
137 information_button.setEnabled(true);
138 information_button.setMnemonic(KeyEvent.VK_S);
139
140
141 JButton preferences_button = new GLIButton(Dictionary.get("Mirroring.Preferences"), Dictionary.get("Mirroring.Preferences_Tooltip"));
142 preferences_button.setEnabled(true);
143 preferences_button.setMnemonic(KeyEvent.VK_P);
144
145 // Connect
146 clear_cache_button.addActionListener(new ClearCacheListener());
147 download_button.addActionListener(new DownloadButtonListener());
148 preferences_button.addActionListener(new PreferencesButtonActionListener());
149 information_button.addActionListener(new InformationButtonActionListener());
150 tree.addTreeSelectionListener(new TreeListener());
151
152 // Add to Panel
153 JPanel button_pane = new JPanel();
154 button_pane.setComponentOrientation(Dictionary.getOrientation());
155 button_pane.setLayout(new GridLayout(1,4)); // GridLayout so button pane resizes with window-width
156 button_pane.setBorder(BorderFactory.createEtchedBorder());
157 button_pane.add(clear_cache_button);
158 button_pane.add(download_button);
159 button_pane.add(information_button);
160 button_pane.add(preferences_button);
161
162 JPanel tree_pane = new JPanel();
163 tree_pane.setComponentOrientation(Dictionary.getOrientation());
164 tree_pane.setLayout(new BorderLayout());
165 scrol_tmp = new JScrollPane(tree);
166 scrol_tmp.setComponentOrientation(Dictionary.getOrientation());
167 tree_pane.add(scrol_tmp, BorderLayout.CENTER);
168 tree_pane.setPreferredSize(TREE_SIZE);
169
170
171 Color colour_two = Configuration.getColor("coloring.collection_tree_background", false);
172 options_pane.setBackground(colour_two);
173 options_pane.setBorder(BorderFactory.createEtchedBorder());
174
175
176 JScrollPane options_scroll_pane = new JScrollPane(options_pane);
177 options_scroll_pane.setComponentOrientation(Dictionary.getOrientation());
178 JSplitPane mode_pane = new JSplitPane();
179 mode_pane.setComponentOrientation(Dictionary.getOrientation());
180 mode_pane.setBorder(BorderFactory.createEmptyBorder(0,0,0,0));
181 if (Dictionary.getOrientation().isLeftToRight()){
182 mode_pane.add(tree_pane,JSplitPane.LEFT);
183 mode_pane.add(options_scroll_pane,JSplitPane.RIGHT);
184 mode_pane.setDividerLocation(TREE_SIZE.width);
185 }else{
186 mode_pane.add(tree_pane,JSplitPane.RIGHT);
187 mode_pane.add(options_scroll_pane,JSplitPane.LEFT);
188 mode_pane.setDividerLocation(1-TREE_SIZE.width);
189 }
190
191
192 JPanel edit_pane = new JPanel();
193 edit_pane.setComponentOrientation(Dictionary.getOrientation());
194 edit_pane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(2,0,0,0), BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder("Download Setting"), BorderFactory.createEmptyBorder(2,2,2,2))));
195 edit_pane.setLayout(new BorderLayout());
196 edit_pane.add(mode_pane,BorderLayout.CENTER);
197 edit_pane.add(button_pane,BorderLayout.PAGE_END);
198
199 // Add to "this"
200 setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
201 setLayout(new GridLayout(2,1));
202 add(edit_pane);
203 add(list_scroll);
204
205 //set the mode to the first downloader in the list
206 mode = convertCONTENTStoMode(CONTENTS[0]); // e.g. Web
207 generateOptions(options_pane,(Download)download_map.get(mode));
208 previous_path = tree.getSelectionPath();
209 }
210
211 /** System Utilities */
212 public void modeChanged(int gli_mode) {
213 // do nothing at this stage - should we be renewing download options??
214 }
215
216 private void addHeader(String name, Color color, JPanel target_pane) {
217 JPanel header = new JPanel();
218 header.setComponentOrientation(Dictionary.getOrientation());
219 header.setBackground(color);
220 JPanel inner_pane = new JPanel();
221 inner_pane.setComponentOrientation(Dictionary.getOrientation());
222 inner_pane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(5,5,5,5), BorderFactory.createRaisedBevelBorder()));
223 inner_pane.setBackground(color);
224 JLabel header_label = new JLabel("<html><strong>" + name + "</strong></html>");
225 header_label.setComponentOrientation(Dictionary.getOrientation());
226 header_label.setBackground(Configuration.getColor("coloring.collection_heading_background", false));
227 header_label.setHorizontalAlignment(JLabel.CENTER);
228 header_label.setOpaque(true);
229
230 // Layout
231 inner_pane.setLayout(new BorderLayout());
232 inner_pane.add(header_label, BorderLayout.CENTER);
233
234 header.setLayout(new BorderLayout());
235 header.add(inner_pane, BorderLayout.CENTER);
236 target_pane.add(header);
237 }
238
239 /** Supporting Functions */
240 private ArrayList<String> loadDownloadersInfo(String lang) {
241 Document document = null;
242
243 try {
244 if (Gatherer.isGsdlRemote) {
245 String output = Gatherer.remoteGreenstoneServer.getScriptOptions("downloadinfo.pl", "&describeall");
246 Reader reader = new StringReader(output);
247 document = XMLTools.parseXML(reader);
248 }
249 else {
250 ArrayList args_list = new ArrayList();
251 String args[] = null;
252 if(Configuration.perl_path != null) {
253 args_list.add(Configuration.perl_path);
254 } else if(Utility.isWindows()) {
255 args_list.add("Perl.exe");
256 } else {
257 args_list.add("perl");
258 }
259 args_list.add("-S");
260 args_list.add(LocalGreenstone.getBinScriptDirectoryPath()+"downloadinfo.pl");
261 args_list.add("-describeall");
262 args_list.add("-xml");
263 args_list.add("-language");
264 args_list.add(lang);
265
266 // Create the process.
267 args = (String []) args_list.toArray(new String[0]);
268
269 SafeProcess process = new SafeProcess(args);
270 DebugStream.println("Getting Download Info: "+args_list);
271
272 // run the SafeProcess
273 int exitVal = process.runProcess();
274 if(exitVal != 0) {
275 throw new Exception("*** Error running Download Info process, process exited with: "
276 + exitVal);
277 }
278
279 // get the result and process it.
280 // This time we expect XML to have come out of the process std error stream.
281 String errStreamOutput = process.getStdError();
282 ///System.err.println("*********\nDownload Pane data, got:\n" + errStreamOutput + "\n**********\n");
283 StringReader xmlStrReader = new StringReader(errStreamOutput);
284 document = XMLTools.parseXML(xmlStrReader);
285 xmlStrReader.close();
286
287 }
288
289
290 }
291 catch (Exception error) {
292 System.err.println("Failed when trying to parse downloadinfo.pl -describeall");
293 error.printStackTrace();
294 }
295
296 if(document != null) {
297 return parseXML(document.getDocumentElement());
298 }
299
300 return null;
301 }
302
303 private ArrayList<String> parseXML(Node root) {
304 ArrayList<String> downloaders = null;
305 Element downloadList = (Element)root;
306 int length = -1;
307 if(downloadList.hasAttribute("length")) {
308 length = Integer.parseInt(downloadList.getAttribute("length"));
309 downloaders = new ArrayList<String>(length);
310
311 for (Node node = downloadList.getFirstChild(); node != null; node = node.getNextSibling()) {
312 // goes through each <DownloadInfo> of describeAll
313
314 String download_name = null;
315
316 for(Node infoNode = node.getFirstChild();
317 infoNode != null; infoNode = infoNode.getNextSibling()) {
318
319 String node_name = infoNode.getNodeName();
320 if(node_name.equalsIgnoreCase("Name")) { // <Name>WebDownload</Name>
321 download_name = XMLTools.getValue(infoNode); // e.g. WebDownload
322 }
323
324 // At this top level of <DownloadInfo> elements,
325 // skip all the downloaders that are Abstract, as these are pure superclasses
326 else if(node_name.equalsIgnoreCase("Abstract")) {
327 String isAbstract = XMLTools.getValue(infoNode);
328
329 if(isAbstract.equalsIgnoreCase("no") && download_name != null) {
330 downloaders.add(download_name);
331 Download downloader = parseDownloadInfoXML(node); // parse the <DownloadInfo> node properly
332 // now embedded references to abstract superclasses (embedded <DownloadInfo> nodes)
333 // will be handled
334
335 String shortName = download_name.replace("Download", ""); // e.g. "Web"
336 download_map.put(shortName, downloader);
337 }
338 }
339 }
340 }
341 }
342
343 return downloaders;
344 }
345
346 private Download parseDownloadInfoXML(Node root) {
347
348 Download download = new Download();
349 String node_name = null;
350 for (Node node = root.getFirstChild(); node != null; node = node.getNextSibling()) {
351 node_name = node.getNodeName();
352 if(node_name.equalsIgnoreCase("Name")) {
353 String name = XMLTools.getValue(node);
354 download.setName(name);
355 }
356 else if (node_name.equalsIgnoreCase("Desc")) {
357 download.setDescription(XMLTools.getValue(node));
358 }
359 else if (node_name.equalsIgnoreCase("Abstract")) {
360 download.setIsAbstract(XMLTools.getValue(node).equalsIgnoreCase(StaticStrings.YES_STR));
361 }
362 else if(node_name.equalsIgnoreCase("Arguments")) {
363 for(Node arg = node.getFirstChild(); arg != null; arg = arg.getNextSibling()) {
364 node_name = arg.getNodeName();
365 if(node_name.equalsIgnoreCase("Option")) {
366 Argument argument = new Argument((Element)arg);
367 argument.parseXML((Element)arg);
368 argument.setValue(argument.getDefaultValue());
369 download.addArgument(argument);
370 }
371
372 }
373 }
374 else if(node_name.equalsIgnoreCase("DownloadInfo")) {
375 Download super_download = parseDownloadInfoXML(node);
376 download.setSuper(super_download);
377 }
378 }
379
380 if(download.getName() != null) {
381 return download;
382 }
383 return null;
384 }
385
386 /** Update the previous setup */
387 private boolean updateArguments(boolean checkRequired)
388 {
389 boolean cont = true;
390 for(int i = 0; i < options_pane.getComponentCount(); i++) {
391
392 Component component = options_pane.getComponent(i);
393 if(component instanceof ArgumentControl) {
394 cont = cont && ((ArgumentControl)component).updateArgument(checkRequired);
395 }
396 }
397
398 if(cont){return true; }
399
400 return false;
401 }
402
403 /** Generate Controls for Options */
404 /* at some stage we should think about which options should be shown for
405 * different modes. Currently, always show all options (unless hidden)*/
406 private void generateOptions(JPanel options_pane, ArgumentContainer data) {
407 options_pane.removeAll();
408 /** Create the current option panel */
409
410 ArrayList arguments = data.getArguments(true, false);
411 int mode = Configuration.getMode();
412 ArrayList added_arguments = new ArrayList();
413
414 for(int i = 0; i < arguments.size(); i++) {
415 Argument argument = (Argument) arguments.get(i);
416
417 if (argument.isHiddenGLI()) continue;
418 ArgumentControl argument_control = new ArgumentControl(argument,false,null);
419 added_arguments.add(argument_control);
420 }
421
422
423 options_pane.setLayout(new GridLayout(added_arguments.size(),1));
424 for(int i = 0; i < added_arguments.size(); i++) {
425 options_pane.add((ArgumentControl)added_arguments.get(i));
426
427 }
428 }
429
430 /** Behaviour Functions */
431 public void afterDisplay() {
432 ready = true;
433 }
434
435
436 public void gainFocus() {
437 if(!ready) {
438 return;
439 }
440
441 // It is also a good time to determine if the download should be enabled - ie if its allowed to be enabled and a valid URL is present in the field.
442 download_button_enabled = true;
443 //download_button.setEnabled(download_button_enabled);
444 }
445
446
447
448 public void refresh(int refresh_reason, boolean ready)
449 {
450 }
451
452 /** Private classes */
453 /** This tree provides a 'table of contents' for the various components of the design process (collection configuration in more technical terms). */
454 private class DesignTree extends JTree {
455
456 private DesignNode root = null;
457 /** Constructor. Automatically generates all of the nodes, in the order of CONTENTS. */
458 public DesignTree() {
459 super();
460 this.setComponentOrientation(Dictionary.getOrientation());
461 resetModel(Configuration.getMode());
462 expandRow(0);
463 setRootVisible(false);
464 setSelectionRow(0);
465 }
466
467 /** Reset the model used by the design page contents tree. This is necessary to hide the partitions entry when in lower detail modes
468 * @param mode the current detail mode as an int
469 */
470 public void resetModel(int mode) {
471 root = new DesignNode("DOWNLOAD.MODE.Root");
472 // Now add the design categories.
473 for(int i = 0; i < CONTENTS.length; i++) {
474 root.add(new DesignNode(CONTENTS[i]));
475 }
476 this.setModel(new DefaultTreeModel(root));
477 updateUI();
478 }
479 /** Set the current view to the one specified.
480 * @param type the name of the desired view as a String
481 */
482 public void setSelectedView(String type) {
483 type = Dictionary.get(type);
484 for(int i = 0; i < root.getChildCount(); i++) {
485 DesignNode child = (DesignNode) root.getChildAt(i);
486 if(child.toString().equals(type)) {
487 TreePath path = new TreePath(child.getPath());
488 setSelectionPath(path);
489 }
490 }
491 }
492 }
493
494 /** A tree node that retains a reference to one of the possible design sub-views relating to the different sub-managers. */
495 private class DesignNode extends DefaultMutableTreeNode {
496 /** Constructor.
497 * @param object The <strong>Object</strong> assigned to this node.
498 */
499 public DesignNode(String object) {
500 super(object);
501 }
502 /** Retrieve a textual representation of the object.
503 * @return a String
504 */
505 public String toString() {
506 // return Dictionary.get("CDM.GUI." + (String)getUserObject());
507 return Dictionary.get((String) getUserObject());
508 }
509 }
510
511 /** Listens for selection changes in the 'contents' tree, and switches to the appropriate view. */
512 private class TreeListener
513 implements TreeSelectionListener {
514 /** Called whenever the selection changes, we must update the view so it matches the node selected.
515 * @param event A <strong>TreeSelectionEvent</strong> containing more information about the tree selection.
516 * @see org.greenstone.gatherer.cdm.ClassifierManager
517 * @see org.greenstone.gatherer.cdm.CollectionDesignManager
518 * @see org.greenstone.gatherer.cdm.CollectionMetaManager
519 * @see org.greenstone.gatherer.cdm.FormatManager
520 * @see org.greenstone.gatherer.cdm.LanguageManager
521 * @see org.greenstone.gatherer.cdm.MetadataSetView
522 * @see org.greenstone.gatherer.cdm.SubcollectionManager
523 * @see org.greenstone.gatherer.cdm.TranslationView
524 * @see org.greenstone.gatherer.cdm.PlugInManager
525 */
526 public void valueChanged(TreeSelectionEvent event) {
527 if(!tree.isSelectionEmpty()) {
528 TreePath path = tree.getSelectionPath();
529
530 DesignNode node = (DesignNode)path.getLastPathComponent();
531 String type = (String)node.getUserObject();
532 Gatherer.g_man.wait(true);
533
534 // type has the value DOWNLOAD.MODE.<downloader>Download,
535 // mode should then be of the form <downloader>
536 mode = convertCONTENTStoMode(type);
537 generateOptions(options_pane,(Download)download_map.get(mode));
538
539 tree.setSelectionPath(path);
540 previous_path = path;
541 repaint();
542
543 Gatherer.g_man.wait(false);
544 }
545 }
546 }
547
548 private String convertCONTENTStoMode(String content) {
549 return content.replace("DOWNLOAD.MODE.", "").replace("ZDownload", "Z3950").replace("Download", "");
550 }
551
552 private class ClearCacheListener
553 implements ActionListener {
554 public void actionPerformed(ActionEvent event) {
555 // Retrieve the cache folder and delete it.
556 Utility.delete(Utility.getCacheDir());
557 // ...and refresh the node in the workspace tree to show it's all gone
558 Gatherer.g_man.refreshWorkspaceTree(WorkspaceTree.DOWNLOADED_FILES_CHANGED);
559 }
560 }
561
562 private class DownloadButtonListener
563 implements ActionListener {
564 public void actionPerformed(ActionEvent event) {
565
566 if(checkURL(true) && checkProxy() == true) {
567
568 // Proxy settings are now set. Check that the url is not a redirect, else get
569 // redirect url (we do this step in order to avoid some unintuitive behaviour from wget)
570 Download current_download = (Download)download_map.get(mode);
571 Argument arg_url = current_download.getArgument("url");
572 if(arg_url != null) { // it's null for z3950 and possibly for other downloaders
573 String url_str = arg_url.getValue();
574 String redirect_url_str = getRedirectURL(url_str);
575
576 // only update the Argument and its GUI ArgumentControl if the URL
577 // has in fact changed
578 if(!url_str.equals(redirect_url_str)) {
579 arg_url.setValue(redirect_url_str);
580 updateArgument(arg_url, redirect_url_str);
581 }
582 }
583 getter.newDownloadJob((Download)download_map.get(mode) ,mode,proxy_url);
584 }
585 }
586 }
587
588 /**
589 * The Java code here will retrieve the page at the given url. If the response code is
590 * a redirect, it will get the redirect url so that wget may be called with the proper url.
591 * This preprocessing of the URL is necessary because:
592 * Wget does not behave the way the browser does when faced with urls of the form
593 * http://www.englishhistory.net/tudor/citizens and if that page does not exist.
594 * The directory listing with a slash at the end (http://www.englishhistory.net/tudor/citizens/)
595 * does exist, however. In order to prevent wget from assuming that the root URL
596 * to traverse is http://www.englishhistory.net/tudor/ instead of the intended
597 * http://www.englishhistory.net/tudor/citizens/, we need give wget the redirect location
598 * that's returned when we initially make a request for http://www.englishhistory.net/tudor/citizens
599 * The proper url is sent back in the Location header, allowing us to bypass wget's
600 * unexpected behaviour.
601 * This method ensures that urls like http://www.nzdl.org/niupepa also continue to work:
602 * there is no http://www.nzdl.org/niupepa/ page, because this url actually redirects to an
603 * entirely different URL.
604 * @return the redirect url for the given url if any redirection is involved, or the
605 * url_str.
606 */
607 private String getRedirectURL(String url_str) {
608 HttpURLConnection connection = null;
609 if(url_str.startsWith("http:")) { // only test http urls
610 try {
611 URL url = new URL(url_str);
612 connection = (HttpURLConnection)url.openConnection(); //new HttpURLConnection(url);
613 // don't let it automatically follow redirects, since we want to
614 // find out whether we are dealing with redirects in the first place
615 connection.setInstanceFollowRedirects(false);
616
617 // now check for whether we get a redirect response
618 // HTTP Codes 3xx are redirects, http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
619 int responseCode = connection.getResponseCode();
620 if(responseCode >= 300 && responseCode < 400) {
621 String responseMsg = connection.getResponseMessage();
622
623 // Get the Location header since this specifies the new location of the resource
624 String location = connection.getHeaderField("Location");
625
626 // this becomes the url that wget should download from
627 url_str = location.trim();
628 }
629
630 connection.disconnect();
631 } catch(Exception e) {
632 if(connection != null) {
633 connection.disconnect();
634 }
635 System.err.println("Checking redirection. Tried to connect to "
636 + url_str + ",\nbut got exception: " + e);
637 }
638 }
639
640 return url_str;
641 }
642
643
644 /** For a string-based Argument whose value has changed, this method
645 * updates the GUI ArgumentControl's value correspondingly. */
646 private void updateArgument(Argument arg, String value) {
647 for(int i = 0; i < options_pane.getComponentCount(); i++) {
648 Component component = options_pane.getComponent(i);
649 if(component instanceof ArgumentControl) {
650 ArgumentControl control = (ArgumentControl)component;
651 if(control.getArgument() == arg) {
652 control.setValue(value);
653 control.repaint();
654 }
655 }
656 }
657 }
658
659 private boolean checkURL(boolean checkRequired){
660
661 if (!updateArguments(checkRequired)){
662 return false;
663 }
664
665 Download current_download = (Download)download_map.get(mode);
666 Argument arg_url = current_download.getArgument("url");
667
668 if (arg_url == null) return true;
669
670 String url_str = arg_url.getValue();
671 URL url = null;
672 try {
673 url = new URL(url_str);
674 }
675 catch(MalformedURLException error) {
676 JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("Mirroring.Invalid_URL"), Dictionary.get("Mirroring.Invalid_URL_Title"), JOptionPane.ERROR_MESSAGE);
677 return false;
678 }
679
680 return true;
681 }
682
683
684 private boolean checkProxy(){
685
686 proxy_url = null;
687
688 Download current_download = (Download)download_map.get(mode);
689
690 Argument arg = current_download.getArgument("proxy_on");
691
692 if (arg == null) return true;
693
694 // Determine if we have to use a proxy.
695 if(Configuration.get("general.use_proxy", true)) {
696
697 String proxy_host = Configuration.getString("general.proxy_host", true);
698 String proxy_port = Configuration.getString("general.proxy_port", true);
699 // Find out whether the user has already authenticated themselves
700 String user_pass = "";
701 String address = proxy_host + ":" + proxy_port;
702
703 int count = 0;
704 // Only for wget, need to avoid a second automatic authentication popup (first asks
705 // the proxy authentication for wget, and the second will ask the same for the realm)
706 // Once the authentication has been reused, it will set the GAuthenticator state back to REGULAR
707 GAuthenticator.setMode(GAuthenticator.DOWNLOAD);
708 while(count < 3 && (user_pass = (String) GAuthenticator.authentications.get(address)) == null) {
709 Authenticator.requestPasswordAuthentication(proxy_host, null, Integer.parseInt(proxy_port), "http://", Dictionary.get("WGet.Prompt"), "HTTP");
710 count++;
711 }
712 if(count >= 3) {
713 return false;
714 }
715
716 if(user_pass.indexOf("@") != -1) {
717
718 // Write the use proxy command - we don't do this anymore, instead we set environment variables - hopefully these can't be spied on like the following can (using ps) - actually the environment stuff didn't work for windows, so lets go back to this
719 if (Utility.isWindows()) {
720
721 arg.setValue("true");
722 arg.setAssigned(true);
723
724 arg = current_download.getArgument("proxy_host");
725 arg.setValue(proxy_host);
726 arg.setAssigned(true);
727
728 arg = current_download.getArgument("proxy_port");
729 arg.setValue(proxy_port);
730 arg.setAssigned(true);
731
732 arg = current_download.getArgument("user_name");
733 arg.setValue(user_pass.substring(0, user_pass.indexOf("@")));
734 arg.setAssigned(true);
735
736 arg = current_download.getArgument("user_password");
737 arg.setValue(user_pass.substring(user_pass.indexOf("@") + 1));
738 arg.setAssigned(true);
739 }
740 else{
741 String user_name = user_pass.substring(0, user_pass.indexOf("@"));
742 String user_pwd = user_pass.substring(user_pass.indexOf("@") + 1);
743 proxy_url = user_name+":"+user_pwd+"@"+proxy_host+":"+proxy_port+"/";
744
745 }
746
747 return true;
748 }
749 else{
750 return false;
751 }
752
753 }
754
755 return true;
756 }
757
758 /*
759 private class PreferencesButtonActionListener
760 implements ActionListener {
761 public void actionPerformed(ActionEvent event) {
762 new Preferences(Preferences.CONNECTION_PREFS);
763 }
764 }*/
765
766 private class InformationButtonActionListener
767 implements ActionListener {
768 public void actionPerformed(ActionEvent event) {
769 //turn off the check for find argument
770 Download current_download = (Download)download_map.get(mode);
771
772 if (!checkProxy() || !checkURL(false) )return;
773
774
775 if(server_info != null) {
776 server_info.dispose();
777 }
778
779
780 Argument arg_url = current_download.getArgument("url");
781 String str_url = "";
782
783 if( arg_url!= null && arg_url.isAssigned()) {
784 str_url = arg_url.getValue();
785 }
786
787
788 server_info = new ServerInfoDialog(str_url ,proxy_url, mode,(Download)download_map.get(mode));
789
790 }
791 }
792
793 private class PreferencesButtonActionListener
794 implements ActionListener {
795 public void actionPerformed(ActionEvent event) {
796 new Preferences(Preferences.CONNECTION_PREFS);
797 }
798 }
799}
Note: See TracBrowser for help on using the repository browser.