Statistics
| Revision:

svn-gvsig-desktop / trunk / build / distribution / IzPack / src / lib / com / izforge / izpack / installer / WebAccessor.java @ 21757

History | View | Annotate | Download (10.3 KB)

1
/*
2
 *  $Id: WebAccessor.java 5819 2006-06-14 07:29:09Z cesar $
3
 *  IzPack
4
 *  Copyright (C) 2002 Johannes Lehtinen
5
 *
6
 *  File :               WebAccessor.java
7
 *  Description :        Prompt user for proxies and passwords
8
 *  Author's email :     mchenryc@acm.org
9
 *  Author's Website :   http://www.izforge.com
10
 *
11
 *  This program is free software; you can redistribute it and/or
12
 *  modify it under the terms of the GNU General Public License
13
 *  as published by the Free Software Foundation; either version 2
14
 *  of the License, or any later version.
15
 *
16
 *  This program is distributed in the hope that it will be useful,
17
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
 *  GNU General Public License for more details.
20
 *
21
 *  You should have received a copy of the GNU General Public License
22
 *  along with this program; if not, write to the Free Software
23
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24
 */
25
package com.izforge.izpack.installer;
26

    
27
import java.awt.BorderLayout;
28
import java.awt.Component;
29
import java.awt.Cursor;
30
import java.awt.GridLayout;
31
import java.awt.Toolkit;
32
import java.io.InputStream;
33
import java.net.Authenticator;
34
import java.net.ConnectException;
35
import java.net.InetAddress;
36
import java.net.PasswordAuthentication;
37
import java.net.URL;
38
import java.net.URLConnection;
39
import java.util.Locale;
40

    
41
import javax.swing.JDialog;
42
import javax.swing.JLabel;
43
import javax.swing.JOptionPane;
44
import javax.swing.JPanel;
45
import javax.swing.JPasswordField;
46
import javax.swing.JTextField;
47
import javax.swing.UIManager;
48

    
49

    
50
/**
51
 * Dialogs for password authentication and firewall specification, when needed,
52
 * during web installation.
53
 *
54
 * @author  Chadwick McHenry
55
 * @version 1.0
56
 */
57
public class WebAccessor
58
{
59
  private Thread openerThread = null;
60
  private InputStream iStream = null;
61
  private Exception exception = null;
62
  
63
  private Object soloCancelOption = null;
64
  private Component parent = null;
65
  private JDialog dialog = null;
66
  private boolean tryProxy = false;
67

    
68
  private JPanel passwordPanel = null;
69
  private JLabel promptLabel;
70
  private JTextField nameField;
71
  private JPasswordField passField;
72

    
73
  private JPanel proxyPanel = null;
74
  private JLabel errorLabel;
75
  private JTextField hostField;
76
  private JTextField portField;
77

    
78
  /**
79
   * Not yet Implemented: placeholder for headless installs.
80
   *
81
   * @throws UnsupportedOperationException
82
   */
83
  public WebAccessor()
84
  {
85
    // the class should probably be rearranged to do this.
86
    throw new UnsupportedOperationException();
87
  }
88

    
89
  /**
90
   * Create a WebAccessor that prompts for proxies and passwords using a
91
   * JDialog.
92
   *
93
   * @param parent determines the frame in which the dialog is displayed; if
94
   * the parentComponent has no Frame, a default Frame is used
95
   */
96
  public WebAccessor(Component parent)
97
  {
98
    this.parent = parent;
99
    Locale l = null;
100
    if (parent != null)
101
      parent.getLocale();
102
    soloCancelOption = UIManager.get("OptionPane.cancelButtonText",l);// TODO: i18n?
103
    Authenticator.setDefault(new MyDialogAuthenticator());
104
  }
105

    
106
  /**
107
   * Opens a URL connection and returns it's InputStream for the specified URL.
108
   *
109
   * @param url the url to open the stream to.
110
   * @return an input stream ready to read, or null on failure
111
   */
112
  public InputStream openInputStream(URL url)
113
  {
114
    // TODO: i18n everything
115
    Object[] options = {soloCancelOption};
116
    JOptionPane pane = new JOptionPane("Connecting to the Internet",
117
                                       JOptionPane.INFORMATION_MESSAGE,
118
                                       JOptionPane.DEFAULT_OPTION,
119
                                       null, options, options[0]);
120
    dialog = pane.createDialog(parent, "Accessing Install Files");
121
    pane.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
122

    
123
    Object value = null;
124
  OPEN_URL:
125
    while (true)
126
    {
127
      startOpening(url); // this starts a thread that may dismiss the dialog before user
128
      dialog.setVisible(true);
129
      value = pane.getValue();
130
      
131
      // dialog closed or canceled (by widget)
132
      if (value == null || value == soloCancelOption)
133
      {
134
        try {
135
          openerThread.interrupt();// stop the connection
136
        } catch (Exception e) {
137
        }
138
        iStream = null; // even if connection was made just after cancel
139
        break;
140
      }
141
      
142
      // dialog closed by thread so either a connection error or success!
143
      else if (value == JOptionPane.UNINITIALIZED_VALUE)
144
      {
145
        // success!
146
        if (iStream != null)
147
          break;
148

    
149
        //System.err.println(exception);
150

    
151
        // an exception we don't expect setting a proxy to fix
152
        if (! tryProxy)
153
          break;
154

    
155
        // else (exception != null)
156
        // show proxy dialog until valid values or cancel
157
        JPanel panel = getProxyPanel();
158
        errorLabel.setText("Unable to connect: " +exception.getMessage());
159
        while (true)
160
        {
161
          int result = JOptionPane.showConfirmDialog(parent, panel,
162
                                                     "Proxy Configuration",
163
                                                     JOptionPane.OK_CANCEL_OPTION,
164
                                                     JOptionPane.QUESTION_MESSAGE);
165
          if (result != JOptionPane.OK_OPTION) // canceled
166
            break OPEN_URL;
167

    
168
          String host = null;
169
          String port = null;
170
          
171
          try {
172
            InetAddress addr = InetAddress.getByName(hostField.getText());
173
            host = addr.getHostName();
174
          } catch (Exception x) {
175
            errorLabel.setText("Unable to resolve Host");
176
            Toolkit.getDefaultToolkit().beep();
177
          }
178
          
179
          try {
180
            if (host != null)
181
              port = Integer.valueOf(portField.getText()).toString();
182
          } catch (NumberFormatException x) {
183
            errorLabel.setText("Invalid Port");
184
            Toolkit.getDefaultToolkit().beep();
185
          }
186
          
187
          if (host != null && port != null) {
188
            //System.err.println ("Setting http proxy: "+ host +":"+ port);
189
            System.getProperties().put ("proxySet", "true");
190
            System.getProperties().put ("proxyHost", host);
191
            System.getProperties().put ("proxyPort", port);
192
            break;
193
          }
194
        }
195
      }
196
    }
197
    return iStream;
198
  }
199
  
200
  private void startOpening(final URL url)
201
  {
202
    openerThread = new Thread()
203
      {
204
        public void run() {
205
          iStream = null;
206
          try {
207
            tryProxy = false;
208
            URLConnection connection = url.openConnection();
209
            iStream = connection.getInputStream(); // just to make connection
210
            
211
          } catch (ConnectException x) { // could be an incorrect proxy
212
            tryProxy = true;
213
            exception = x;
214
            
215
          } catch (Exception x) {
216
            // Exceptions that get here are considered cancels or missing
217
            // pages, eg 401 if user finally cancels auth
218
            exception = x;
219
            
220
          } finally {
221
            // if dialog is in use, allow it to become visible /before/ closing
222
            // it, else on /fast/ connectinos, it may open later and hang!
223
            if (dialog != null)
224
            {
225
              Thread.yield();
226
              dialog.setVisible(false);
227
            }
228
          }
229
        }
230
      };
231
    openerThread.start();
232
  }
233

    
234
  /**
235
   * Only to be called after an initial error has indicated a connection problem
236
   */
237
  private JPanel getProxyPanel()
238
  {
239
    if (proxyPanel == null)
240
    {
241
      proxyPanel = new JPanel(new BorderLayout(5,5));
242

    
243
      errorLabel = new JLabel();
244
      
245
      JPanel fields = new JPanel(new GridLayout(2,2));
246
      String h = (String)System.getProperties().get ("proxyHost");
247
      String p = (String)System.getProperties().get ("proxyPort");
248
      hostField = new JTextField(h != null ? h : "");
249
      portField = new JTextField(p != null ? p : "");
250
      JLabel host = new JLabel("Host: "); // TODO: i18n
251
      JLabel port = new JLabel("Port: "); // TODO: i18n
252
      fields.add(host);
253
      fields.add(hostField);
254
      fields.add(port);
255
      fields.add(portField);
256

    
257
      JLabel exampleLabel =
258
        new JLabel("e.g. host=\"gatekeeper.example.com\" port=\"80\"");
259

    
260
      proxyPanel.add(errorLabel, BorderLayout.NORTH);
261
      proxyPanel.add(fields, BorderLayout.CENTER);
262
      proxyPanel.add(exampleLabel, BorderLayout.SOUTH);
263
    }
264
    proxyPanel.validate();
265
    
266
    return proxyPanel;
267
  }
268
  
269
  private JPanel getPasswordPanel()
270
  {
271
    if (passwordPanel == null)
272
    {
273
      passwordPanel = new JPanel(new BorderLayout(5,5));
274

    
275
      promptLabel = new JLabel();
276
      
277
      JPanel fields = new JPanel(new GridLayout(2,2));
278
      nameField = new JTextField();
279
      passField = new JPasswordField();
280
      JLabel name = new JLabel("Name: "); // TODO: i18n
281
      JLabel pass = new JLabel("Password: "); // TODO: i18n
282
      fields.add(name);
283
      fields.add(nameField);
284
      fields.add(pass);
285
      fields.add(passField);
286

    
287
      passwordPanel.add(promptLabel, BorderLayout.NORTH);
288
      passwordPanel.add(fields, BorderLayout.CENTER);
289
    }
290
    passField.setText("");
291

    
292
    return passwordPanel;
293
  }
294

    
295
  /**
296
   * Authenticates via dialog when needed.
297
   */
298
  private class MyDialogAuthenticator extends Authenticator
299
  {
300
    public PasswordAuthentication getPasswordAuthentication()
301
    {
302
      // TODO: i18n
303
      JPanel p = getPasswordPanel();
304
      String prompt = getRequestingPrompt();
305
      InetAddress addr = getRequestingSite();
306
      if (addr != null)
307
        prompt += " (" + addr.getHostName() + ")";
308
      promptLabel.setText(prompt);
309
      int result = JOptionPane.showConfirmDialog(parent, p, "Enter Password",
310
                                                 JOptionPane.OK_CANCEL_OPTION,
311
                                                 JOptionPane.QUESTION_MESSAGE);
312
      if (result != JOptionPane.OK_OPTION)
313
        return null;
314

    
315
      return new PasswordAuthentication(nameField.getText(),
316
                                        passField.getPassword());
317
    }
318
  };
319
}
320