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

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

Fix to getRedirectURL() being stuck forever if the proxy details are wrong. I still can't work out what my proxy settings should be to get downloading to work from a TSG-adminsitered machine, but at least now GLI doesn't hang requiring a ctrl-C to terminate it.

  • 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 connection.setConnectTimeout(5 * 1000); // ms
617
618 // now check for whether we get a redirect response
619 // HTTP Codes 3xx are redirects, http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
620 int responseCode = connection.getResponseCode();
621 if(responseCode >= 300 && responseCode < 400) {
622 String responseMsg = connection.getResponseMessage();
623
624 // Get the Location header since this specifies the new location of the resource
625 String location = connection.getHeaderField("Location");
626
627 // this becomes the url that wget should download from
628 url_str = location.trim();
629 }
630
631 connection.disconnect();
632 } catch(Exception e) {
633 if(connection != null) {
634 connection.disconnect();
635 }
636 System.err.println("Checking redirection. Tried to connect to "
637 + url_str + ",\nbut got exception: " + e);
638 }
639 }
640
641 return url_str;
642 }
643
644
645 /** For a string-based Argument whose value has changed, this method
646 * updates the GUI ArgumentControl's value correspondingly. */
647 private void updateArgument(Argument arg, String value) {
648 for(int i = 0; i < options_pane.getComponentCount(); i++) {
649 Component component = options_pane.getComponent(i);
650 if(component instanceof ArgumentControl) {
651 ArgumentControl control = (ArgumentControl)component;
652 if(control.getArgument() == arg) {
653 control.setValue(value);
654 control.repaint();
655 }
656 }
657 }
658 }
659
660 private boolean checkURL(boolean checkRequired){
661
662 if (!updateArguments(checkRequired)){
663 return false;
664 }
665
666 Download current_download = (Download)download_map.get(mode);
667 Argument arg_url = current_download.getArgument("url");
668
669 if (arg_url == null) return true;
670
671 String url_str = arg_url.getValue();
672 URL url = null;
673 try {
674 url = new URL(url_str);
675 }
676 catch(MalformedURLException error) {
677 JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("Mirroring.Invalid_URL"), Dictionary.get("Mirroring.Invalid_URL_Title"), JOptionPane.ERROR_MESSAGE);
678 return false;
679 }
680
681 return true;
682 }
683
684
685 private boolean checkProxy(){
686
687 proxy_url = null;
688
689 Download current_download = (Download)download_map.get(mode);
690
691 Argument arg = current_download.getArgument("proxy_on");
692
693 if (arg == null) return true;
694
695 // Determine if we have to use a proxy.
696 if(Configuration.get("general.use_proxy", true)) {
697
698 String proxy_host = Configuration.getString("general.proxy_host", true);
699 String proxy_port = Configuration.getString("general.proxy_port", true);
700 // Find out whether the user has already authenticated themselves
701 String user_pass = "";
702 String address = proxy_host + ":" + proxy_port;
703
704 int count = 0;
705 // Only for wget, need to avoid a second automatic authentication popup (first asks
706 // the proxy authentication for wget, and the second will ask the same for the realm)
707 // Once the authentication has been reused, it will set the GAuthenticator state back to REGULAR
708 GAuthenticator.setMode(GAuthenticator.DOWNLOAD);
709 while(count < 3 && (user_pass = (String) GAuthenticator.authentications.get(address)) == null) {
710 Authenticator.requestPasswordAuthentication(proxy_host, null, Integer.parseInt(proxy_port), "http://", Dictionary.get("WGet.Prompt"), "HTTP");
711 count++;
712 }
713 if(count >= 3) {
714 return false;
715 }
716
717 if(user_pass.indexOf("@") != -1) {
718
719 // 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
720 if (Utility.isWindows()) {
721
722 arg.setValue("true");
723 arg.setAssigned(true);
724
725 arg = current_download.getArgument("proxy_host");
726 arg.setValue(proxy_host);
727 arg.setAssigned(true);
728
729 arg = current_download.getArgument("proxy_port");
730 arg.setValue(proxy_port);
731 arg.setAssigned(true);
732
733 arg = current_download.getArgument("user_name");
734 arg.setValue(user_pass.substring(0, user_pass.indexOf("@")));
735 arg.setAssigned(true);
736
737 arg = current_download.getArgument("user_password");
738 arg.setValue(user_pass.substring(user_pass.indexOf("@") + 1));
739 arg.setAssigned(true);
740 }
741 else{
742 String user_name = user_pass.substring(0, user_pass.indexOf("@"));
743 String user_pwd = user_pass.substring(user_pass.indexOf("@") + 1);
744 proxy_url = user_name+":"+user_pwd+"@"+proxy_host+":"+proxy_port+"/";
745
746 }
747
748 return true;
749 }
750 else{
751 return false;
752 }
753
754 }
755
756 return true;
757 }
758
759 /*
760 private class PreferencesButtonActionListener
761 implements ActionListener {
762 public void actionPerformed(ActionEvent event) {
763 new Preferences(Preferences.CONNECTION_PREFS);
764 }
765 }*/
766
767 private class InformationButtonActionListener
768 implements ActionListener {
769 public void actionPerformed(ActionEvent event) {
770 //turn off the check for find argument
771 Download current_download = (Download)download_map.get(mode);
772
773 if (!checkProxy() || !checkURL(false) )return;
774
775
776 if(server_info != null) {
777 server_info.dispose();
778 }
779
780
781 Argument arg_url = current_download.getArgument("url");
782 String str_url = "";
783
784 if( arg_url!= null && arg_url.isAssigned()) {
785 str_url = arg_url.getValue();
786 }
787
788
789 server_info = new ServerInfoDialog(str_url ,proxy_url, mode,(Download)download_map.get(mode));
790
791 }
792 }
793
794 private class PreferencesButtonActionListener
795 implements ActionListener {
796 public void actionPerformed(ActionEvent event) {
797 new Preferences(Preferences.CONNECTION_PREFS);
798 }
799 }
800}
Note: See TracBrowser for help on using the repository browser.