/* * IzPack - Copyright 2001-2008 Julien Ponge, All Rights Reserved. * * http://izpack.org/ * http://izpack.codehaus.org/ * * Copyright 2002 Johannes Lehtinen * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.izforge.izpack.installer; import javax.swing.*; import java.awt.*; import java.io.InputStream; import java.net.*; import java.util.Locale; /** * Dialogs for password authentication and firewall specification, when needed, during web * installation. * * @author Chadwick McHenry * @author <a href="vralev@redhat.com">Vladimir Ralev</a> * @version 1.0 */ public class WebAccessor { private Thread openerThread = null; private InputStream iStream = null; private Exception exception = null; private Object soloCancelOption = null; private Component parent = null; private JDialog dialog = null; private boolean tryProxy = false; private JPanel passwordPanel = null; private JLabel promptLabel; private JTextField nameField; private JPasswordField passField; private JPanel proxyPanel = null; private JLabel errorLabel; private JTextField hostField; private JTextField portField; private String url; private int contentLength = -1; /** * Not yet Implemented: placeholder for headless installs. * * @throws UnsupportedOperationException */ public WebAccessor() { // the class should probably be rearranged to do this. throw new UnsupportedOperationException(); } /** * Create a WebAccessor that prompts for proxies and passwords using a JDialog. * * @param parent determines the frame in which the dialog is displayed; if the parentComponent * has no Frame, a default Frame is used */ public WebAccessor(Component parent) { this.parent = parent; Locale l = null; if (parent != null) { parent.getLocale(); } soloCancelOption = UIManager.get("OptionPane.cancelButtonText", l);// TODO: // i18n? Authenticator.setDefault(new MyDialogAuthenticator()); } /** * Opens a URL connection and returns it's InputStream for the specified URL. * * @param url the url to open the stream to. * @return an input stream ready to read, or null on failure */ public InputStream openInputStream(URL url) { setUrl(url.toExternalForm()); OPEN_URL: while (true) { startOpening(url); // this starts a thread Thread.yield(); // Wait a bit to see if the stream comes up int retry = 28; while (exception == null && iStream == null && retry > 0) { try { Thread.sleep(200); retry--; } catch (Exception e) { System.out.println("In openInputStream: " + e); } } /* Try to find a proxy if that failed */ // success! if (iStream != null) { break; } // an exception we don't expect setting a proxy to fix if (!tryProxy) { break; } // else (exception != null) // show proxy dialog until valid values or cancel JPanel panel = getProxyPanel(); errorLabel.setText("Unable to connect: " + exception.getMessage()); while (true) { int result = JOptionPane.showConfirmDialog(parent, panel, "Proxy Configuration", JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE); if (result != JOptionPane.OK_OPTION) // canceled { break OPEN_URL; } String host = null; String port = null; try { InetAddress addr = InetAddress.getByName(hostField.getText()); host = addr.getHostName(); } catch (Exception x) { errorLabel.setText("Unable to resolve Host"); Toolkit.getDefaultToolkit().beep(); } try { if (host != null) { port = Integer.valueOf(portField.getText()).toString(); } } catch (NumberFormatException x) { errorLabel.setText("Invalid Port"); Toolkit.getDefaultToolkit().beep(); } if (host != null && port != null) { // System.err.println ("Setting http proxy: "+ host // +":"+ port); System.getProperties().put("proxySet", "true"); System.getProperties().put("proxyHost", host); System.getProperties().put("proxyPort", port); break; } } } if (iStream == null) { openerThread.interrupt(); } return iStream; } private void startOpening(final URL url) { final WebAccessor wa = this; openerThread = new Thread() { public void run() { iStream = null; try { tryProxy = false; URLConnection connection = url.openConnection(); if (connection instanceof HttpURLConnection) { HttpURLConnection htc = (HttpURLConnection) connection; contentLength = htc.getContentLength(); } //InputStream iii = echoSocket.getInputStream(); InputStream i = connection.getInputStream(); iStream = new LoggedInputStream(i, wa); // just to make } catch (ConnectException x) { // could be an incorrect proxy tryProxy = true; exception = x; } catch (Exception x) { // Exceptions that get here are considered cancels or // missing // pages, eg 401 if user finally cancels auth exception = x; } finally { // if dialog is in use, allow it to become visible /before/ // closing // it, else on /fast/ connectinos, it may open later and // hang! if (dialog != null) { Thread.yield(); dialog.setVisible(false); } } } }; openerThread.start(); } /** * Only to be called after an initial error has indicated a connection problem */ private JPanel getProxyPanel() { if (proxyPanel == null) { proxyPanel = new JPanel(new BorderLayout(5, 5)); errorLabel = new JLabel(); JPanel fields = new JPanel(new GridLayout(2, 2)); String h = (String) System.getProperties().get("proxyHost"); String p = (String) System.getProperties().get("proxyPort"); hostField = new JTextField(h != null ? h : ""); portField = new JTextField(p != null ? p : ""); JLabel host = new JLabel("Host: "); // TODO: i18n JLabel port = new JLabel("Port: "); // TODO: i18n fields.add(host); fields.add(hostField); fields.add(port); fields.add(portField); JLabel exampleLabel = new JLabel("e.g. host=\"gatekeeper.example.com\" port=\"80\""); proxyPanel.add(errorLabel, BorderLayout.NORTH); proxyPanel.add(fields, BorderLayout.CENTER); proxyPanel.add(exampleLabel, BorderLayout.SOUTH); } proxyPanel.validate(); return proxyPanel; } private JPanel getPasswordPanel() { if (passwordPanel == null) { passwordPanel = new JPanel(new BorderLayout(5, 5)); promptLabel = new JLabel(); JPanel fields = new JPanel(new GridLayout(2, 2)); nameField = new JTextField(); passField = new JPasswordField(); JLabel name = new JLabel("Name: "); // TODO: i18n JLabel pass = new JLabel("Password: "); // TODO: i18n fields.add(name); fields.add(nameField); fields.add(pass); fields.add(passField); passwordPanel.add(promptLabel, BorderLayout.NORTH); passwordPanel.add(fields, BorderLayout.CENTER); } passField.setText(""); return passwordPanel; } /** * Authenticates via dialog when needed. */ private class MyDialogAuthenticator extends Authenticator { public PasswordAuthentication getPasswordAuthentication() { // TODO: i18n JPanel p = getPasswordPanel(); String prompt = getRequestingPrompt(); InetAddress addr = getRequestingSite(); if (addr != null) { prompt += " (" + addr.getHostName() + ")"; } promptLabel.setText(prompt); int result = JOptionPane.showConfirmDialog(parent, p, "Enter Password", JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE); if (result != JOptionPane.OK_OPTION) { return null; } return new PasswordAuthentication(nameField.getText(), passField.getPassword()); } } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public int getContentLength() { return contentLength; } }