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

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

In place of the Input- and OutputStreamGobbler classes, am now shifting GLI code to use SafeProcess too, copied across from GS3 src code. Class SafeProcess includes the two streamgobblers as static inner classes and some more functionality with safely running an external process from Java.

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