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

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

GLI's DownloadPane.java now also uses SafeProcess.java when running a perl process from Java.

  • Property svn:keywords set to Author Date Id Revision
File size: 28.5 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 StringReader xmlStrReader = new StringReader(errStreamOutput);
283 document = XMLTools.parseXML(xmlStrReader);
284 xmlStrReader.close();
285
286 }
287
288
289 }
290 catch (Exception error) {
291 System.err.println("Failed when trying to parse downloadinfo.pl -describeall");
292 error.printStackTrace();
293 }
294
295 if(document != null) {
296 return parseXML(document.getDocumentElement());
297 }
298
299 return null;
300 }
301
302 private ArrayList<String> parseXML(Node root) {
303 ArrayList<String> downloaders = null;
304 Element downloadList = (Element)root;
305 int length = -1;
306 if(downloadList.hasAttribute("length")) {
307 length = Integer.parseInt(downloadList.getAttribute("length"));
308 downloaders = new ArrayList<String>(length);
309
310 for (Node node = downloadList.getFirstChild(); node != null; node = node.getNextSibling()) {
311 // goes through each <DownloadInfo> of describeAll
312
313 String download_name = null;
314
315 for(Node infoNode = node.getFirstChild();
316 infoNode != null; infoNode = infoNode.getNextSibling()) {
317
318 String node_name = infoNode.getNodeName();
319 if(node_name.equalsIgnoreCase("Name")) { // <Name>WebDownload</Name>
320 download_name = XMLTools.getValue(infoNode); // e.g. WebDownload
321 }
322
323 // At this top level of <DownloadInfo> elements,
324 // skip all the downloaders that are Abstract, as these are pure superclasses
325 else if(node_name.equalsIgnoreCase("Abstract")) {
326 String isAbstract = XMLTools.getValue(infoNode);
327
328 if(isAbstract.equalsIgnoreCase("no") && download_name != null) {
329 downloaders.add(download_name);
330 Download downloader = parseDownloadInfoXML(node); // parse the <DownloadInfo> node properly
331 // now embedded references to abstract superclasses (embedded <DownloadInfo> nodes)
332 // will be handled
333
334 String shortName = download_name.replace("Download", ""); // e.g. "Web"
335 download_map.put(shortName, downloader);
336 }
337 }
338 }
339 }
340 }
341
342 return downloaders;
343 }
344
345 private Download parseDownloadInfoXML(Node root) {
346
347 Download download = new Download();
348 String node_name = null;
349 for (Node node = root.getFirstChild(); node != null; node = node.getNextSibling()) {
350 node_name = node.getNodeName();
351 if(node_name.equalsIgnoreCase("Name")) {
352 String name = XMLTools.getValue(node);
353 download.setName(name);
354 }
355 else if (node_name.equalsIgnoreCase("Desc")) {
356 download.setDescription(XMLTools.getValue(node));
357 }
358 else if (node_name.equalsIgnoreCase("Abstract")) {
359 download.setIsAbstract(XMLTools.getValue(node).equalsIgnoreCase(StaticStrings.YES_STR));
360 }
361 else if(node_name.equalsIgnoreCase("Arguments")) {
362 for(Node arg = node.getFirstChild(); arg != null; arg = arg.getNextSibling()) {
363 node_name = arg.getNodeName();
364 if(node_name.equalsIgnoreCase("Option")) {
365 Argument argument = new Argument((Element)arg);
366 argument.parseXML((Element)arg);
367 argument.setValue(argument.getDefaultValue());
368 download.addArgument(argument);
369 }
370
371 }
372 }
373 else if(node_name.equalsIgnoreCase("DownloadInfo")) {
374 Download super_download = parseDownloadInfoXML(node);
375 download.setSuper(super_download);
376 }
377 }
378
379 if(download.getName() != null) {
380 return download;
381 }
382 return null;
383 }
384
385 /** Update the previous setup */
386 private boolean updateArguments(boolean checkRequired)
387 {
388 boolean cont = true;
389 for(int i = 0; i < options_pane.getComponentCount(); i++) {
390
391 Component component = options_pane.getComponent(i);
392 if(component instanceof ArgumentControl) {
393 cont = cont && ((ArgumentControl)component).updateArgument(checkRequired);
394 }
395 }
396
397 if(cont){return true; }
398
399 return false;
400 }
401
402 /** Generate Controls for Options */
403 /* at some stage we should think about which options should be shown for
404 * different modes. Currently, always show all options (unless hidden)*/
405 private void generateOptions(JPanel options_pane, ArgumentContainer data) {
406 options_pane.removeAll();
407 /** Create the current option panel */
408
409 ArrayList arguments = data.getArguments(true, false);
410 int mode = Configuration.getMode();
411 ArrayList added_arguments = new ArrayList();
412
413 for(int i = 0; i < arguments.size(); i++) {
414 Argument argument = (Argument) arguments.get(i);
415
416 if (argument.isHiddenGLI()) continue;
417 ArgumentControl argument_control = new ArgumentControl(argument,false,null);
418 added_arguments.add(argument_control);
419 }
420
421
422 options_pane.setLayout(new GridLayout(added_arguments.size(),1));
423 for(int i = 0; i < added_arguments.size(); i++) {
424 options_pane.add((ArgumentControl)added_arguments.get(i));
425
426 }
427 }
428
429 /** Behaviour Functions */
430 public void afterDisplay() {
431 ready = true;
432 }
433
434
435 public void gainFocus() {
436 if(!ready) {
437 return;
438 }
439
440 // 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.
441 download_button_enabled = true;
442 //download_button.setEnabled(download_button_enabled);
443 }
444
445
446
447 public void refresh(int refresh_reason, boolean ready)
448 {
449 }
450
451 /** Private classes */
452 /** This tree provides a 'table of contents' for the various components of the design process (collection configuration in more technical terms). */
453 private class DesignTree extends JTree {
454
455 private DesignNode root = null;
456 /** Constructor. Automatically generates all of the nodes, in the order of CONTENTS. */
457 public DesignTree() {
458 super();
459 this.setComponentOrientation(Dictionary.getOrientation());
460 resetModel(Configuration.getMode());
461 expandRow(0);
462 setRootVisible(false);
463 setSelectionRow(0);
464 }
465
466 /** Reset the model used by the design page contents tree. This is necessary to hide the partitions entry when in lower detail modes
467 * @param mode the current detail mode as an int
468 */
469 public void resetModel(int mode) {
470 root = new DesignNode("DOWNLOAD.MODE.Root");
471 // Now add the design categories.
472 for(int i = 0; i < CONTENTS.length; i++) {
473 root.add(new DesignNode(CONTENTS[i]));
474 }
475 this.setModel(new DefaultTreeModel(root));
476 updateUI();
477 }
478 /** Set the current view to the one specified.
479 * @param type the name of the desired view as a String
480 */
481 public void setSelectedView(String type) {
482 type = Dictionary.get(type);
483 for(int i = 0; i < root.getChildCount(); i++) {
484 DesignNode child = (DesignNode) root.getChildAt(i);
485 if(child.toString().equals(type)) {
486 TreePath path = new TreePath(child.getPath());
487 setSelectionPath(path);
488 }
489 }
490 }
491 }
492
493 /** A tree node that retains a reference to one of the possible design sub-views relating to the different sub-managers. */
494 private class DesignNode extends DefaultMutableTreeNode {
495 /** Constructor.
496 * @param object The <strong>Object</strong> assigned to this node.
497 */
498 public DesignNode(String object) {
499 super(object);
500 }
501 /** Retrieve a textual representation of the object.
502 * @return a String
503 */
504 public String toString() {
505 // return Dictionary.get("CDM.GUI." + (String)getUserObject());
506 return Dictionary.get((String) getUserObject());
507 }
508 }
509
510 /** Listens for selection changes in the 'contents' tree, and switches to the appropriate view. */
511 private class TreeListener
512 implements TreeSelectionListener {
513 /** Called whenever the selection changes, we must update the view so it matches the node selected.
514 * @param event A <strong>TreeSelectionEvent</strong> containing more information about the tree selection.
515 * @see org.greenstone.gatherer.cdm.ClassifierManager
516 * @see org.greenstone.gatherer.cdm.CollectionDesignManager
517 * @see org.greenstone.gatherer.cdm.CollectionMetaManager
518 * @see org.greenstone.gatherer.cdm.FormatManager
519 * @see org.greenstone.gatherer.cdm.LanguageManager
520 * @see org.greenstone.gatherer.cdm.MetadataSetView
521 * @see org.greenstone.gatherer.cdm.SubcollectionManager
522 * @see org.greenstone.gatherer.cdm.TranslationView
523 * @see org.greenstone.gatherer.cdm.PlugInManager
524 */
525 public void valueChanged(TreeSelectionEvent event) {
526 if(!tree.isSelectionEmpty()) {
527 TreePath path = tree.getSelectionPath();
528
529 DesignNode node = (DesignNode)path.getLastPathComponent();
530 String type = (String)node.getUserObject();
531 Gatherer.g_man.wait(true);
532
533 // type has the value DOWNLOAD.MODE.<downloader>Download,
534 // mode should then be of the form <downloader>
535 mode = convertCONTENTStoMode(type);
536 generateOptions(options_pane,(Download)download_map.get(mode));
537
538 tree.setSelectionPath(path);
539 previous_path = path;
540 repaint();
541
542 Gatherer.g_man.wait(false);
543 }
544 }
545 }
546
547 private String convertCONTENTStoMode(String content) {
548 return content.replace("DOWNLOAD.MODE.", "").replace("ZDownload", "Z3950").replace("Download", "");
549 }
550
551 private class ClearCacheListener
552 implements ActionListener {
553 public void actionPerformed(ActionEvent event) {
554 // Retrieve the cache folder and delete it.
555 Utility.delete(Utility.getCacheDir());
556 // ...and refresh the node in the workspace tree to show it's all gone
557 Gatherer.g_man.refreshWorkspaceTree(WorkspaceTree.DOWNLOADED_FILES_CHANGED);
558 }
559 }
560
561 private class DownloadButtonListener
562 implements ActionListener {
563 public void actionPerformed(ActionEvent event) {
564
565 if(checkURL(true) && checkProxy() == true) {
566
567 // Proxy settings are now set. Check that the url is not a redirect, else get
568 // redirect url (we do this step in order to avoid some unintuitive behaviour from wget)
569 Download current_download = (Download)download_map.get(mode);
570 Argument arg_url = current_download.getArgument("url");
571 if(arg_url != null) { // it's null for z3950 and possibly for other downloaders
572 String url_str = arg_url.getValue();
573 String redirect_url_str = getRedirectURL(url_str);
574
575 // only update the Argument and its GUI ArgumentControl if the URL
576 // has in fact changed
577 if(!url_str.equals(redirect_url_str)) {
578 arg_url.setValue(redirect_url_str);
579 updateArgument(arg_url, redirect_url_str);
580 }
581 }
582 getter.newDownloadJob((Download)download_map.get(mode) ,mode,proxy_url);
583 }
584 }
585 }
586
587 /**
588 * The Java code here will retrieve the page at the given url. If the response code is
589 * a redirect, it will get the redirect url so that wget may be called with the proper url.
590 * This preprocessing of the URL is necessary because:
591 * Wget does not behave the way the browser does when faced with urls of the form
592 * http://www.englishhistory.net/tudor/citizens and if that page does not exist.
593 * The directory listing with a slash at the end (http://www.englishhistory.net/tudor/citizens/)
594 * does exist, however. In order to prevent wget from assuming that the root URL
595 * to traverse is http://www.englishhistory.net/tudor/ instead of the intended
596 * http://www.englishhistory.net/tudor/citizens/, we need give wget the redirect location
597 * that's returned when we initially make a request for http://www.englishhistory.net/tudor/citizens
598 * The proper url is sent back in the Location header, allowing us to bypass wget's
599 * unexpected behaviour.
600 * This method ensures that urls like http://www.nzdl.org/niupepa also continue to work:
601 * there is no http://www.nzdl.org/niupepa/ page, because this url actually redirects to an
602 * entirely different URL.
603 * @return the redirect url for the given url if any redirection is involved, or the
604 * url_str.
605 */
606 private String getRedirectURL(String url_str) {
607 HttpURLConnection connection = null;
608 if(url_str.startsWith("http:")) { // only test http urls
609 try {
610 URL url = new URL(url_str);
611 connection = (HttpURLConnection)url.openConnection(); //new HttpURLConnection(url);
612 // don't let it automatically follow redirects, since we want to
613 // find out whether we are dealing with redirects in the first place
614 connection.setInstanceFollowRedirects(false);
615
616 // now check for whether we get a redirect response
617 // HTTP Codes 3xx are redirects, http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
618 int responseCode = connection.getResponseCode();
619 if(responseCode >= 300 && responseCode < 400) {
620 String responseMsg = connection.getResponseMessage();
621
622 // Get the Location header since this specifies the new location of the resource
623 String location = connection.getHeaderField("Location");
624
625 // this becomes the url that wget should download from
626 url_str = location.trim();
627 }
628
629 connection.disconnect();
630 } catch(Exception e) {
631 if(connection != null) {
632 connection.disconnect();
633 }
634 System.err.println("Checking redirection. Tried to connect to "
635 + url_str + ",\nbut got exception: " + e);
636 }
637 }
638
639 return url_str;
640 }
641
642
643 /** For a string-based Argument whose value has changed, this method
644 * updates the GUI ArgumentControl's value correspondingly. */
645 private void updateArgument(Argument arg, String value) {
646 for(int i = 0; i < options_pane.getComponentCount(); i++) {
647 Component component = options_pane.getComponent(i);
648 if(component instanceof ArgumentControl) {
649 ArgumentControl control = (ArgumentControl)component;
650 if(control.getArgument() == arg) {
651 control.setValue(value);
652 control.repaint();
653 }
654 }
655 }
656 }
657
658 private boolean checkURL(boolean checkRequired){
659
660 if (!updateArguments(checkRequired)){
661 return false;
662 }
663
664 Download current_download = (Download)download_map.get(mode);
665 Argument arg_url = current_download.getArgument("url");
666
667 if (arg_url == null) return true;
668
669 String url_str = arg_url.getValue();
670 URL url = null;
671 try {
672 url = new URL(url_str);
673 }
674 catch(MalformedURLException error) {
675 JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("Mirroring.Invalid_URL"), Dictionary.get("Mirroring.Invalid_URL_Title"), JOptionPane.ERROR_MESSAGE);
676 return false;
677 }
678
679 return true;
680 }
681
682
683 private boolean checkProxy(){
684
685 proxy_url = null;
686
687 Download current_download = (Download)download_map.get(mode);
688
689 Argument arg = current_download.getArgument("proxy_on");
690
691 if (arg == null) return true;
692
693 // Determine if we have to use a proxy.
694 if(Configuration.get("general.use_proxy", true)) {
695
696 String proxy_host = Configuration.getString("general.proxy_host", true);
697 String proxy_port = Configuration.getString("general.proxy_port", true);
698 // Find out whether the user has already authenticated themselves
699 String user_pass = "";
700 String address = proxy_host + ":" + proxy_port;
701
702 int count = 0;
703 // Only for wget, need to avoid a second automatic authentication popup (first asks
704 // the proxy authentication for wget, and the second will ask the same for the realm)
705 // Once the authentication has been reused, it will set the GAuthenticator state back to REGULAR
706 GAuthenticator.setMode(GAuthenticator.DOWNLOAD);
707 while(count < 3 && (user_pass = (String) GAuthenticator.authentications.get(address)) == null) {
708 Authenticator.requestPasswordAuthentication(proxy_host, null, Integer.parseInt(proxy_port), "http://", Dictionary.get("WGet.Prompt"), "HTTP");
709 count++;
710 }
711 if(count >= 3) {
712 return false;
713 }
714
715 if(user_pass.indexOf("@") != -1) {
716
717 // 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
718 if (Utility.isWindows()) {
719
720 arg.setValue("true");
721 arg.setAssigned(true);
722
723 arg = current_download.getArgument("proxy_host");
724 arg.setValue(proxy_host);
725 arg.setAssigned(true);
726
727 arg = current_download.getArgument("proxy_port");
728 arg.setValue(proxy_port);
729 arg.setAssigned(true);
730
731 arg = current_download.getArgument("user_name");
732 arg.setValue(user_pass.substring(0, user_pass.indexOf("@")));
733 arg.setAssigned(true);
734
735 arg = current_download.getArgument("user_password");
736 arg.setValue(user_pass.substring(user_pass.indexOf("@") + 1));
737 arg.setAssigned(true);
738 }
739 else{
740 String user_name = user_pass.substring(0, user_pass.indexOf("@"));
741 String user_pwd = user_pass.substring(user_pass.indexOf("@") + 1);
742 proxy_url = user_name+":"+user_pwd+"@"+proxy_host+":"+proxy_port+"/";
743
744 }
745
746 return true;
747 }
748 else{
749 return false;
750 }
751
752 }
753
754 return true;
755 }
756
757 /*
758 private class PreferencesButtonActionListener
759 implements ActionListener {
760 public void actionPerformed(ActionEvent event) {
761 new Preferences(Preferences.CONNECTION_PREFS);
762 }
763 }*/
764
765 private class InformationButtonActionListener
766 implements ActionListener {
767 public void actionPerformed(ActionEvent event) {
768 //turn off the check for find argument
769 Download current_download = (Download)download_map.get(mode);
770
771 if (!checkProxy() || !checkURL(false) )return;
772
773
774 if(server_info != null) {
775 server_info.dispose();
776 }
777
778
779 Argument arg_url = current_download.getArgument("url");
780 String str_url = "";
781
782 if( arg_url!= null && arg_url.isAssigned()) {
783 str_url = arg_url.getValue();
784 }
785
786
787 server_info = new ServerInfoDialog(str_url ,proxy_url, mode,(Download)download_map.get(mode));
788
789 }
790 }
791
792 private class PreferencesButtonActionListener
793 implements ActionListener {
794 public void actionPerformed(ActionEvent event) {
795 new Preferences(Preferences.CONNECTION_PREFS);
796 }
797 }
798}
Note: See TracBrowser for help on using the repository browser.