ConfigWizard.java revision 11262:b7ebfbf2359e
124113Skato/*
224113Skato * CDDL HEADER START
324113Skato *
424113Skato * The contents of this file are subject to the terms of the
524113Skato * Common Development and Distribution License (the "License").
624113Skato * You may not use this file except in compliance with the License.
724113Skato *
824113Skato * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
924113Skato * or http://www.opensolaris.org/os/licensing.
1024113Skato * See the License for the specific language governing permissions
1124113Skato * and limitations under the License.
1224113Skato *
1324113Skato * When distributing Covered Code, include this CDDL HEADER in each
1424113Skato * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1524113Skato * If applicable, add the following below this CDDL HEADER, with the
1624113Skato * fields enclosed by brackets "[]" replaced with your own identifying
1724113Skato * information: Portions Copyright [yyyy] [name of copyright owner]
1824113Skato *
1924113Skato * CDDL HEADER END
2024113Skato */
2124113Skato/*
2224113Skato * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
2324113Skato * Use is subject to license terms.
2424113Skato */
2524113Skatopackage com.sun.dhcpmgr.client;
2624113Skato
2724113Skatoimport java.awt.*;
2824113Skatoimport java.awt.event.*;
2924113Skatoimport java.util.*;
3024113Skatoimport java.text.MessageFormat;
3124113Skatoimport java.net.*;
3224113Skato
3324113Skatoimport javax.swing.*;
3424113Skatoimport javax.swing.table.*;
3524113Skatoimport javax.swing.event.*;
3624113Skatoimport javax.swing.border.*;
3724113Skato
3824113Skatoimport com.sun.dhcpmgr.ui.*;
3924113Skatoimport com.sun.dhcpmgr.data.*;
4024113Skatoimport com.sun.dhcpmgr.server.*;
4124113Skatoimport com.sun.dhcpmgr.bridge.BridgeException;
4224113Skatoimport com.sun.dhcpmgr.bridge.ExistsException;
4324113Skato
4424113Skato/**
4524113Skato * This wizard configures the DHCP service.  It also has a mode switch so
4624113Skato * that it is also usable for just adding a single network, so that in
4724113Skato * the tool it actually performs the Network Wizard function as well.
4824113Skato */
4924113Skatopublic class ConfigWizard extends DSWizard {
5024113Skato    private boolean fullConfig;
5124113Skato    private DhcpServiceMgr server;
5224113Skato    private int leaseLength = 3600*24;
5324113Skato    private boolean leaseNegotiable = true;
5424113Skato    private String dnsDomain;
5524113Skato    private Vector dnsServs;
5624113Skato    private Network network;
5724113Skato    private boolean isLan = true;
5824113Skato    private boolean routerDiscovery = true;
5924113Skato    private IPAddress router = null;
6024113Skato    private String nisDomain;
6124113Skato    private Vector nisServs;
6224113Skato    private static final String [] unitChoices = {
6324113Skato	ResourceStrings.getString("cfg_wiz_hours"),
6424113Skato	ResourceStrings.getString("cfg_wiz_days"),
6524113Skato	ResourceStrings.getString("cfg_wiz_weeks") };
6624113Skato    private static final int [] unitMultiples = { 60*60, 24*60*60, 7*24*60*60 };
6724113Skato    private HostResource hostResource = null;
6824113Skato
6924113Skato    /**
7024113Skato     * This class defines a host resource component.
7124113Skato     */
7224113Skato    private class HostResource extends Box {
7324113Skato
7424113Skato	/**
7524113Skato	 * The host resource(eg., files, dns).
7624113Skato	 */
7724113Skato	private String resource = null;
7824113Skato
7924113Skato	/**
8024113Skato	 * The description of the resource.
8124113Skato	 */
8224113Skato	private String description = null;
8324113Skato
8424113Skato	/**
8524113Skato	 * The button for the resource.
8624113Skato	 */
8724113Skato	private HostButton hostButton = null;
8824113Skato
8924113Skato	/**
9024113Skato	 * The domain field for the resource (if any)
9124113Skato	 */
9224113Skato	private NoSpaceField domainField = null;
9324113Skato
9424113Skato	/**
9524113Skato	 * The constructor.
9624113Skato	 * @param resource the resource value for the config file
9724113Skato	 * @param description description of the resource
9824113Skato	 * @param defaultdomain default domain (if any) for the resource
9924113Skato	 * @param enabled determines whether resource is selectable
10024113Skato	 */
10124113Skato	public HostResource(String resource, String description,
10224113Skato	    String defaultDomain, String domainDescription, boolean enabled) {
10324113Skato
10424113Skato	    super(BoxLayout.X_AXIS);
10524113Skato
10624113Skato	    this.resource = resource;
10724113Skato	    this.description = description;
10824113Skato
10924113Skato	    // Every host resource needs a button even if the resource
11024113Skato	    // isn't one that will be selectable.
11124113Skato	    //
11224113Skato	    hostButton = new HostButton(this, false);
11324113Skato	    hostButton.setAlignmentX(Component.LEFT_ALIGNMENT);
11424113Skato	    add(hostButton);
11524113Skato	    if (!enabled) {
11624113Skato		hostButton.setEnabled(false);
11724113Skato		defaultDomain = new String();
11824113Skato	    }
11924113Skato
12024113Skato	    // If the defaultDomain is null, then the host resource
12124113Skato	    // does not require a domain. Otherwise, the resource
12224113Skato	    // must have a text field so that the user can supply
12324113Skato	    // a domain.
12424113Skato	    //
12524113Skato	    if (defaultDomain != null) {
12624113Skato		add(Box.createHorizontalStrut(20));
12724113Skato
12824113Skato		Box domainBox = Box.createHorizontalBox();
12924113Skato
13024113Skato		JLabel label = new JLabel(domainDescription);
13124113Skato		label.setForeground(Color.black);
13224113Skato		domainBox.add(label);
13324113Skato
13424113Skato		domainField = new NoSpaceField(defaultDomain, 10);
13524113Skato		domainField.setEnabled(false);
13624113Skato		domainField.setMaximumSize(domainField.getPreferredSize());
13724113Skato
13824113Skato		label.setLabelFor(domainField);
13924113Skato		domainBox.add(domainField);
14024113Skato		label.setToolTipText(description);
14124113Skato
14224113Skato		add(domainBox);
14324113Skato
14424113Skato		if (!enabled) {
14524113Skato		    domainField.setEditable(false);
14624113Skato		    label.setEnabled(false);
14724113Skato		} else {
14824113Skato		    // Disable the forward button if domain empty.
14924113Skato		    DocumentListener listener = new DocumentListener() {
15024113Skato			public void insertUpdate(DocumentEvent e) {
15124113Skato			    setForwardEnabled(
15224113Skato				domainField.getText().length() != 0);
15324113Skato			}
15424113Skato			public void changedUpdate(DocumentEvent e) {
15524113Skato			    insertUpdate(e);
15624113Skato			}
15724113Skato			public void removeUpdate(DocumentEvent e) {
15824113Skato			    insertUpdate(e);
15924113Skato			}
16024113Skato		    };
16124113Skato		    domainField.getDocument().addDocumentListener(listener);
16224113Skato		}
16324113Skato
16424113Skato	    }
16524113Skato
16624113Skato	} // constructor
16724113Skato
16824113Skato	/**
16924113Skato	 * Sets or unsets the host resource.
17024113Skato	 * @param isSelected if true, sets the resource, else unsets it
17124113Skato	 */
17224113Skato	public void setSelected(boolean isSelected) {
17324113Skato	    if (isSelected) {
17424113Skato		setHostResource(this);
17524113Skato		if (!hostButton.isSelected()) {
17624113Skato		    hostButton.setSelected(true);
17724113Skato		}
17824113Skato		if (domainField != null) {
17924113Skato		    domainField.setEnabled(true);
18024113Skato		    setForwardEnabled(domainField.getText().length() != 0);
18124113Skato		} else {
18224113Skato		    setForwardEnabled(true);
18324113Skato		}
18424113Skato	    } else {
18524113Skato		if (domainField != null) {
18624113Skato		    domainField.setEnabled(false);
18724113Skato		}
18824113Skato	    }
18924113Skato	} // setSelected
19024113Skato
19124113Skato	/**
19224113Skato	 * Returns the host resource.
19324113Skato	 * @return the host resource.
19424113Skato	 */
19524113Skato	public String getResource() {
19624113Skato	    return resource;
19724113Skato	} // getResource
19824113Skato
19924113Skato	/**
20024113Skato	 * Returns the resource description.
20124113Skato	 * @return the resource description.
20224113Skato	 */
20324113Skato	public String getDescription() {
20424113Skato	    return description;
20524113Skato	} // getDescription
20624113Skato
20724113Skato	/**
20824113Skato	 * Returns the domain for this component.
20924113Skato	 * @return the domain for this component.
21024113Skato	 */
21124113Skato	public String getDomain() {
21224113Skato	    if (domainField == null) {
21324113Skato		return null;
21424113Skato	    } else {
21524113Skato		return domainField.getText();
21624113Skato	    }
21724113Skato	} // getDomain
21824113Skato
21924113Skato	/**
22024113Skato	 * Returns the HostButton contained in this component.
22124113Skato	 * @return the HostButton contained in this component.
22224113Skato	 */
22324113Skato	public HostButton getHostButton() {
22424113Skato	    return hostButton;
22524113Skato	} // getHostButton
22624113Skato
22724113Skato    } // hostResource
22824113Skato
22924113Skato    /**
23024113Skato     * This class maps a radio button to its HostResource
23124113Skato     */
23224113Skato    private class HostButton extends JRadioButton {
23324113Skato
23424113Skato	/**
23524113Skato	 * The HostResource to link to the radio button.
23624113Skato	 */
23724113Skato	private HostResource hostResource = null;
23824113Skato
23924113Skato	/**
24024113Skato	 * Constructs a HostButton from a HostResource and determines
24124113Skato	 * whether the button should be selected using the boolean argument.
24224113Skato	 * @param hostResource the HostResource to map to the radio button.
24324113Skato	 * @param selected select the radio button?
24424113Skato	 */
24524113Skato	public HostButton(HostResource hostResource, boolean selected) {
24624113Skato	    super(hostResource.getDescription(), selected);
24724113Skato	    this.hostResource = hostResource;
24824113Skato	} // constructor
24924113Skato
25024113Skato	/**
25124113Skato	 * Returns the HostResource mapped to the radio button.
25224113Skato	 * @return the HostResource mapped to the radio button.
25324113Skato	 */
25424113Skato	public HostResource getHostResource() {
25524113Skato	    return hostResource;
25624113Skato	} // getHostResource
25724113Skato
25824113Skato    } // HostButton
25924113Skato
26024113Skato    // Select where host data will be stored.
26124113Skato    class HostDataStep implements WizardStep {
26224113Skato
26324113Skato	/**
26424113Skato	 * The component provided to the wizard.
26524113Skato	 */
26624113Skato	private Box stepBox;
26724113Skato
26824113Skato	/**
26924113Skato	 * The basic constructor for the wizard step.
27024113Skato	 */
27124113Skato	public HostDataStep() {
27224113Skato
27324113Skato	    stepBox = Box.createVerticalBox();
27424113Skato
27524113Skato	    // Explanatory step text
27624113Skato	    //
27724113Skato	    JComponent c = Wizard.createTextArea(
27824113Skato		ResourceStrings.getString("cfg_wiz_host_explain"), 2, 45);
27924113Skato	    c.setAlignmentX(Component.LEFT_ALIGNMENT);
28024113Skato	    stepBox.add(c);
28124113Skato	    stepBox.add(Box.createVerticalStrut(5));
28224113Skato
28324113Skato	    // Create button listener, that will set the selected
28424113Skato	    // host resource when the button is selected.
28524113Skato	    //
28624113Skato	    ChangeListener buttonListener = new ChangeListener() {
28724113Skato		public void stateChanged(ChangeEvent e) {
28824113Skato		    HostButton button = (HostButton)e.getSource();
28924113Skato		    HostResource hostResource = button.getHostResource();
29024113Skato		    hostResource.setSelected(button.isSelected());
29124113Skato		}
29224113Skato	    };
29324113Skato
29424113Skato	    // Create panel that will contain the buttons.
29524113Skato	    //
29624113Skato	    JPanel boxPanel = new JPanel();
29724113Skato	    boxPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
29824113Skato	    boxPanel.setLayout(new GridLayout(4, 1));
29924113Skato
30024113Skato	    // List the host resource choices.
30124113Skato	    //
30224113Skato	    ButtonGroup buttonGroup = new ButtonGroup();
30324113Skato
30424113Skato	    // The "do not manage hosts" option.
30524113Skato	    //
30624113Skato	    String hostDescription =
30724113Skato		ResourceStrings.getString("cfg_wiz_no_host_management");
30824113Skato	    HostResource hostResource = new HostResource(null,
30924113Skato		hostDescription, null, null, true);
31024113Skato	    HostButton hbMgt = hostResource.getHostButton();
31124113Skato            hbMgt.setToolTipText(hostDescription);
31224113Skato	    hostResource.setSelected(true);
31324113Skato	    hostResource.getHostButton().addChangeListener(buttonListener);
31424113Skato	    buttonGroup.add(hostResource.getHostButton());
31524113Skato	    boxPanel.add(hostResource);
31624113Skato
31724113Skato	    // The "files" option.
31824113Skato	    //
31924113Skato	    hostDescription =
32024113Skato		ResourceStrings.getString("cfg_wiz_files");
32124113Skato	    hostResource = new HostResource(DhcpConfigOpts.DSVC_CV_FILES,
32224113Skato		hostDescription, null, null, true);
32324113Skato	    HostButton hb = hostResource.getHostButton();
32424113Skato	    hb.setToolTipText(hostDescription);
32524113Skato	    hostResource.getHostButton().addChangeListener(buttonListener);
32624113Skato	    buttonGroup.add(hostResource.getHostButton());
32724113Skato	    boxPanel.add(hostResource);
32824113Skato
32924113Skato	    // The "dns" option. Only enabled if it can be managed
33024113Skato	    // from the selected server.
33124113Skato	    //
33224113Skato	    String domainDefault = null;
33324113Skato	    boolean enabled = false;
33424113Skato	    String domainDescription =
33524113Skato		ResourceStrings.getString("cfg_wiz_domain") + " ";
33624113Skato	    try {
33724113Skato		domainDefault =
33824113Skato		    server.getStringOption(StandardOptions.CD_DNSDOMAIN, "");
33924113Skato	    } catch (Throwable e) {
34024113Skato		domainDefault = new String();
34124113Skato	    }
34224113Skato
34324113Skato	    try {
34424113Skato		enabled =
34524113Skato		    server.isHostsValid(DhcpConfigOpts.DSVC_CV_DNS, "");
34624113Skato	    } catch (Throwable e) {
34724113Skato		enabled = false;
34824113Skato	    }
34924113Skato
35024113Skato	    hostDescription =
35124113Skato		ResourceStrings.getString("cfg_wiz_dns");
35224113Skato
35324113Skato	    hostResource = new HostResource(DhcpConfigOpts.DSVC_CV_DNS,
35424113Skato		hostDescription, domainDefault, domainDescription, enabled);
35524113Skato	    HostButton hbDNS = hostResource.getHostButton();
35624113Skato            hbDNS.setToolTipText(hostDescription);
35724113Skato	    hostResource.getHostButton().addChangeListener(buttonListener);
35824113Skato	    buttonGroup.add(hostResource.getHostButton());
35924113Skato	    boxPanel.add(hostResource);
36024113Skato
36124113Skato	    // Add the panel to the stepBox component.
36224113Skato	    //
36324113Skato	    stepBox.add(boxPanel);
36424113Skato	    stepBox.add(Box.createVerticalStrut(10));
36524113Skato	    stepBox.add(Box.createVerticalGlue());
36624113Skato
36724113Skato	} // constructor
36824113Skato
36924113Skato	public String getDescription() {
37024113Skato	    return ResourceStrings.getString("cfg_wiz_hostdata_desc");
37124113Skato	} // getDescription
37224113Skato
37324113Skato	public Component getComponent() {
37424113Skato	    return stepBox;
37524113Skato	} // getComponent
37624113Skato
37724113Skato	public void setActive(int direction) {
37824113Skato	    setForwardEnabled(true);
37924113Skato	} // setActive
38024113Skato
38124113Skato	public boolean setInactive(int direction) {
38224113Skato
38324113Skato	    // If moving forward, validate that the host resource/domain
38424113Skato	    // input by the user is manageable from the selected server.
38524113Skato	    //
38624113Skato	    boolean valid = true;
38724113Skato	    if (direction == FORWARD) {
38824113Skato		String resource = getHostResource().getResource();
38924113Skato		String domain = getHostResource().getDomain();
39024113Skato		if (resource != null) {
39124113Skato		    try {
39224113Skato			valid = server.isHostsValid(resource, domain);
39324113Skato		    } catch (Throwable e) {
39424113Skato			valid = false;
39524113Skato		    }
39624113Skato		}
39724113Skato		if (!valid) {
39824113Skato		    JOptionPane.showMessageDialog(ConfigWizard.this,
39924113Skato			ResourceStrings.getString("cfg_wiz_invalid_host"),
40024113Skato			ResourceStrings.getString("input_error"),
40124113Skato			JOptionPane.ERROR_MESSAGE);
40224113Skato		}
40324113Skato	    }
40424113Skato	    return (valid);
40524113Skato	} // setInactive
40624113Skato
40724113Skato    } // HostDataStep
40824113Skato
40924113Skato    // This step specifies lease length and renewal policies for the server
41024113Skato    class LeaseStep implements WizardStep {
41124113Skato	private IntegerField length;
41224113Skato	private JComboBox units;
41324113Skato	private JCheckBox negotiable;
41424113Skato	private Box stepBox;
41524113Skato
41624113Skato	public LeaseStep() {
41724113Skato	    stepBox = Box.createVerticalBox();
41824113Skato
41924113Skato	    // Explanatory text
42024113Skato	    stepBox.add(Wizard.createTextArea(
42124113Skato		ResourceStrings.getString("cfg_wiz_lease_explain"), 3, 45));
42224113Skato
42324113Skato	    // Need to input a number together with units
42424113Skato	    JPanel flowPanel = new JPanel();
42524113Skato
42624113Skato	    Mnemonic mnLease =
42724113Skato                new Mnemonic(ResourceStrings.getString("cfg_wiz_lease_length"));
42824113Skato            JLabel lblLeaseLen = new JLabel(
42924113Skato                mnLease.getString());
43024113Skato
43124113Skato	    flowPanel.add(lblLeaseLen);
43224113Skato
43324113Skato	    // Use a box for the value and units to keep together in layout
43424113Skato	    Box leaseBox = Box.createHorizontalBox();
43524113Skato	    length = new IntegerField();
43624113Skato	    leaseBox.add(length);
43724113Skato	    leaseBox.add(Box.createHorizontalStrut(5));
43824113Skato
43924113Skato	    lblLeaseLen.setLabelFor(length);
44024113Skato	    lblLeaseLen.setToolTipText(mnLease.getString());
44124113Skato	    lblLeaseLen.setDisplayedMnemonic(mnLease.getMnemonic());
44224113Skato
44324113Skato	    units = new JComboBox(unitChoices);
44424113Skato	    leaseBox.add(units);
445	    flowPanel.add(leaseBox);
446	    stepBox.add(flowPanel);
447	    stepBox.add(Box.createVerticalStrut(10));
448
449	    // Explain negotiable, provide selection for it
450	    stepBox.add(Wizard.createTextArea(
451		ResourceStrings.getString("cfg_wiz_negotiable_explain"), 6,
452		45));
453
454	    negotiable = new JCheckBox(
455		ResourceStrings.getString("cfg_wiz_negotiable"), true);
456	    negotiable.setToolTipText(
457		ResourceStrings.getString("cfg_wiz_negotiable"));
458	    negotiable.setAlignmentX(Component.CENTER_ALIGNMENT);
459	    stepBox.add(negotiable);
460	    stepBox.add(Box.createVerticalGlue());
461	}
462
463	public String getDescription() {
464	    return ResourceStrings.getString("cfg_wiz_lease_desc");
465	}
466
467	public Component getComponent() {
468	    return stepBox;
469	}
470
471	public void setActive(int direction) {
472	    setForwardEnabled(true);
473	    // Set the units field to the maximum unit this value expresses
474	    int lengthVal = 0;
475	    int i;
476	    for (i = unitMultiples.length - 1; i >= 0; --i) {
477		lengthVal = leaseLength / unitMultiples[i];
478		if (lengthVal != 0) {
479		    if (leaseLength % unitMultiples[i] == 0) {
480			break;
481		    }
482		}
483	    }
484	    if (i == -1) {
485		i = 0;
486	    }
487	    units.setSelectedIndex(i);
488	    length.setValue(lengthVal);
489	    negotiable.setSelected(leaseNegotiable);
490	}
491
492	public boolean setInactive(int direction) {
493	    // Leases cannot be zero length
494	    long lease = (long)length.getValue();
495	    if (lease == 0) {
496		JOptionPane.showMessageDialog(ConfigWizard.this,
497		    ResourceStrings.getString("cfg_wiz_zero_lease"),
498		    ResourceStrings.getString("input_error"),
499		    JOptionPane.ERROR_MESSAGE);
500		return false;
501	    }
502	    int multiplier = unitMultiples[units.getSelectedIndex()];
503	    lease *= multiplier;
504	    if (lease > Integer.MAX_VALUE) {
505		// Value is too large
506		MessageFormat form = new MessageFormat(
507		    ResourceStrings.getString("cfg_wiz_lease_overflow"));
508		Object args = new Object[] {
509		    new Integer(Integer.MAX_VALUE / multiplier),
510		    units.getSelectedItem()
511		};
512		JOptionPane.showMessageDialog(ConfigWizard.this,
513		    form.format(args), ResourceStrings.getString("input_error"),
514		    JOptionPane.ERROR_MESSAGE);
515		return false;
516	    }
517	    leaseLength = (int)lease;
518	    leaseNegotiable = negotiable.isSelected();
519	    return true;
520	}
521    }
522
523    // Step to configure DNS
524    class DnsStep implements WizardStep {
525	private NoSpaceField domain;
526	private IPAddressList serverList;
527	private Box stepBox;
528	private boolean firstActive = true;
529
530	public DnsStep() {
531	    stepBox = Box.createVerticalBox();
532
533	    // Explanatory text
534	    stepBox.add(Wizard.createTextArea(
535		ResourceStrings.getString("cfg_wiz_dns_explain"), 5, 45));
536	    stepBox.add(Box.createVerticalStrut(10));
537
538	    // Domain first
539	    JPanel fieldPanel = new JPanel(new FieldLayout());
540
541	    Mnemonic mnDNS =
542                new Mnemonic(ResourceStrings.getString("cfg_wiz_dns_domain"));
543            JLabel jlDNSDomain = new JLabel(mnDNS.getString());
544            fieldPanel.add(FieldLayout.LABEL, jlDNSDomain);
545
546	    domain = new NoSpaceField();
547	    jlDNSDomain.setLabelFor(domain);
548	    jlDNSDomain.setToolTipText(mnDNS.getString());
549	    jlDNSDomain.setDisplayedMnemonic(mnDNS.getMnemonic());
550	    fieldPanel.add(FieldLayout.FIELD, domain);
551	    stepBox.add(fieldPanel);
552
553	    serverList = new IPAddressList();
554	    Border tb = BorderFactory.createTitledBorder(
555		BorderFactory.createLineBorder(Color.black),
556		ResourceStrings.getString("cfg_wiz_dns_servers"));
557	    serverList.setBorder(BorderFactory.createCompoundBorder(tb,
558		BorderFactory.createEmptyBorder(5, 5, 5, 5)));
559	    stepBox.add(serverList);
560	}
561
562	public String getDescription() {
563	    return ResourceStrings.getString("cfg_wiz_dns_desc");
564	}
565
566	public Component getComponent() {
567	    return stepBox;
568	}
569
570	public void setActive(int direction) {
571	    setForwardEnabled(true);
572
573	    // First time through, ask the server for the defaults
574	    if (firstActive) {
575		firstActive = false;
576		try {
577		    domain.setText(
578			server.getStringOption(StandardOptions.CD_DNSDOMAIN,
579			""));
580		    serverList.setAddressList(
581			server.getIPOption(StandardOptions.CD_DNSSERV, ""));
582		} catch (Throwable e) {
583		    // Ignore errors, we're just supplying defaults
584		}
585	    }
586	}
587
588	public boolean setInactive(int direction) {
589	    if (direction == FORWARD) {
590		/*
591		 * Either must supply both a domain and a list of servers, or
592		 * neither
593		 */
594		if ((domain.getText().length() == 0)
595			!= (serverList.getListSize() == 0)) {
596		    JOptionPane.showMessageDialog(ConfigWizard.this,
597			ResourceStrings.getString("cfg_wiz_dns_both"),
598			ResourceStrings.getString("input_error"),
599			JOptionPane.ERROR_MESSAGE);
600		    return false;
601		}
602	    }
603	    dnsDomain = domain.getText();
604	    dnsServs = serverList.getAddressList();
605	    return true;
606	}
607    }
608
609    // Select the network to configure
610    class NetworkStep implements WizardStep {
611	private JComboBox networkBox;
612	private NetworkListModel networkListModel;
613	private IPAddressField mask;
614	private Box stepBox;
615	private boolean firstActive = true;
616	private Hashtable maskTable;
617
618	// Model for the list of networks
619	class NetworkListModel extends AbstractListModel
620		implements ComboBoxModel {
621	    private Object currentValue;
622	    private String [] data = null;
623
624	    public int getSize() {
625		if (data == null) {
626		    return 0;
627		} else {
628		    return data.length;
629		}
630	    }
631
632	    public Object getElementAt(int index) {
633		if (data == null) {
634		    return null;
635		} else {
636		    return data[index];
637		}
638	    }
639
640	    public void setSelectedItem(Object anItem) {
641		currentValue = anItem;
642		fireContentsChanged(this, -1, -1);
643	    }
644
645	    public Object getSelectedItem() {
646		return currentValue;
647	    }
648
649	    public void setData(Vector addrs) {
650		data = new String[addrs.size()];
651		addrs.copyInto(data);
652		fireContentsChanged(this, 0, data.length);
653	    }
654	}
655
656	/*
657	 * Editor for the Network combo box, ensures that a valid IP address
658	 * is entered. This implementation cribbed from Swing's
659	 * BasicComboBoxEditor in plaf/basic
660	 */
661	class NetworkComboBoxEditor implements ComboBoxEditor, FocusListener {
662	    private IPAddressField editor;
663
664	    public NetworkComboBoxEditor() {
665		editor = new IPAddressField();
666		editor.addFocusListener(this);
667	    }
668
669	    public Component getEditorComponent() {
670		return editor;
671	    }
672
673	    public void setItem(Object obj) {
674		if (obj != null) {
675		    editor.setText((String)obj);
676		} else {
677		    editor.setText("");
678		}
679	    }
680
681	    public Object getItem() {
682		return editor.getText();
683	    }
684
685	    public void selectAll() {
686		editor.selectAll();
687		editor.requestFocus();
688	    }
689
690	    public void focusGained(FocusEvent e) {
691	    }
692
693	    public void focusLost(FocusEvent e) {
694	    }
695
696	    public void addActionListener(ActionListener l) {
697		editor.addActionListener(l);
698	    }
699
700	    public void removeActionListener(ActionListener l) {
701		editor.removeActionListener(l);
702	    }
703	}
704
705	public NetworkStep() {
706	    stepBox = Box.createVerticalBox();
707
708	    // Start with intro text, depending on mode.
709	    if (fullConfig) {
710		stepBox.add(Wizard.createTextArea(
711		    ResourceStrings.getString("cfg_wiz_network_explain"), 4,
712		    45));
713	    } else {
714		stepBox.add(Wizard.createTextArea(
715		    ResourceStrings.getString("net_wiz_net_explain"), 6, 45));
716	    }
717	    stepBox.add(Box.createVerticalStrut(10));
718
719            JPanel panel = new JPanel(new FieldLayout());
720	    Mnemonic mnAddr =
721                new Mnemonic(ResourceStrings.getString("cfg_wiz_network"));
722	    JLabel jlNetworkAddr = new JLabel(mnAddr.getString());
723            panel.add(FieldLayout.LABEL, jlNetworkAddr);
724            networkListModel = new NetworkListModel();
725            networkBox = new JComboBox(networkListModel);
726            networkBox.setEditable(true);
727            networkBox.setEditor(new NetworkComboBoxEditor());
728            panel.add(FieldLayout.FIELD, networkBox);
729	    jlNetworkAddr.setLabelFor(networkBox);
730            jlNetworkAddr.setToolTipText(mnAddr.getString());
731	    jlNetworkAddr.setDisplayedMnemonic(mnAddr.getMnemonic());
732
733	    // Label and text field for subnet mask
734	    Mnemonic mnMask =
735            new Mnemonic(ResourceStrings.getString("cfg_wiz_mask"));
736	    JLabel addrLbl =
737                new JLabel(mnMask.getString());
738            addrLbl.setToolTipText(mnMask.getString());
739            panel.add(FieldLayout.LABEL, addrLbl);
740            mask = new IPAddressField();
741            addrLbl.setLabelFor(mask);
742	    addrLbl.setDisplayedMnemonic(mnMask.getMnemonic());
743
744	    panel.add(FieldLayout.FIELD, mask);
745	    stepBox.add(panel);
746
747	    stepBox.add(Box.createVerticalStrut(10));
748
749	    if (fullConfig) {
750		stepBox.add(Wizard.createTextArea(
751		    ResourceStrings.getString("cfg_wiz_network_explainmore"), 4,
752		    45));
753	    }
754	    stepBox.add(Box.createVerticalGlue());
755
756	    /*
757	     * Listen to selection changes on the network box and change the
758	     * netmask accordingly.
759	     */
760	    networkBox.addItemListener(new ItemListener() {
761		public void itemStateChanged(ItemEvent e) {
762		    if (e.getStateChange() == ItemEvent.SELECTED) {
763			String s = (String)e.getItem();
764			IPAddress a = (IPAddress)maskTable.get(s);
765			if (a != null) {
766			    // We know the correct value, so set it
767			    mask.setValue(a);
768			}
769		    }
770		}
771	    });
772	}
773
774	public String getDescription() {
775	    return ResourceStrings.getString("cfg_wiz_network_desc");
776	}
777
778	public Component getComponent() {
779	    return stepBox;
780	}
781
782	public void setActive(int direction) {
783	    setForwardEnabled(true);
784	    if (firstActive) {
785		firstActive = false;
786		maskTable = new Hashtable();
787		try {
788		    /*
789		     * Initialize list to all networks directly attached to
790		     * the server
791		     */
792		    IPInterface[] ifs = new IPInterface[0];
793		    try {
794			ifs = server.getInterfaces();
795		    } catch (BridgeException e) {
796			// we're not configured yet, apparently
797			ifs = null;
798		    }
799		    Vector addrs = new Vector();
800
801		    // Get list of already-configured networks
802		    Network [] nets = new Network[0];
803		    try {
804			nets = DataManager.get().getNetworks(true);
805		    } catch (BridgeException e) {
806			// Ignore; we're not configured yet, apparently
807		    }
808		    /*
809		     * Now filter the list so only unconfigured networks
810		     * show up in the selection list.
811		     */
812		    if (ifs != null) {
813		    for (int i = 0; i < ifs.length; ++i) {
814			boolean alreadyConfigured = false;
815			for (int j = 0; j < nets.length; ++j) {
816			    if (ifs[i].getNetwork().equals(nets[j])) {
817				alreadyConfigured = true;
818				break;
819			    }
820			}
821			if (!alreadyConfigured) {
822			    // Add to list
823			    String s = ifs[i].getNetwork().
824				getNetworkNumber().getHostAddress();
825			    addrs.addElement(s);
826			    // Save netmask for retrieval later
827			    maskTable.put(s, ifs[i].getNetwork().getMask());
828			}
829		    }
830		    }
831		    networkListModel.setData(addrs);
832		    if (networkBox.getItemCount() > 0) {
833			networkBox.setSelectedIndex(0);
834		    }
835		} catch (Throwable e) {
836		    // Do nothing, we're just setting defaults
837		    e.printStackTrace();
838		}
839	    }
840	}
841
842	public boolean setInactive(int direction) {
843	    if (direction == FORWARD) {
844		try {
845		    network = new Network((String)networkBox.getSelectedItem());
846		    if (mask.getValue() == null) {
847			/*
848			 * Check for empty, in which case we just let the
849			 * default happen
850			 */
851			if (mask.getText().length() != 0) {
852			    // Not a valid subnet mask
853			    MessageFormat form = new MessageFormat(
854				ResourceStrings.getString("cfg_wiz_bad_mask"));
855			    Object [] args = new Object[1];
856			    args[0] = mask.getText();
857			    JOptionPane.showMessageDialog(ConfigWizard.this,
858				form.format(args),
859				ResourceStrings.getString("input_error"),
860				JOptionPane.ERROR_MESSAGE);
861			    return false;
862			}
863		    } else {
864			network.setMask(mask.getValue());
865		    }
866
867		    // Check for network already configured, error if so
868		    Network [] nets = new Network[0];
869		    try {
870			nets = DataManager.get().getNetworks(false);
871		    } catch (BridgeException e) {
872			// Ignore; must not be configured yet
873		    }
874		    for (int i = 0; i < nets.length; ++i) {
875			if (network.equals(nets[i])) {
876			    MessageFormat form = new MessageFormat(
877				ResourceStrings.getString(
878				"cfg_wiz_network_configured"));
879			    Object [] args = new Object[1];
880			    args[0] = network.getAddress().getHostAddress();
881			    JOptionPane.showMessageDialog(ConfigWizard.this,
882				form.format(args),
883				ResourceStrings.getString("input_error"),
884				JOptionPane.ERROR_MESSAGE);
885			    return false;
886			}
887		    }
888		} catch (ValidationException e) {
889		    // Not a valid IP address
890		    MessageFormat form = new MessageFormat(
891			ResourceStrings.getString("cfg_wiz_bad_network"));
892		    Object [] args = new Object[1];
893		    args[0] = (String)networkBox.getSelectedItem();
894		    if (args[0] == null) {
895			args[0] = "";
896		    }
897		    JOptionPane.showMessageDialog(ConfigWizard.this,
898			form.format(args),
899			ResourceStrings.getString("input_error"),
900			JOptionPane.ERROR_MESSAGE);
901		    return false;
902		} catch (Throwable e) {
903		    e.printStackTrace();
904		    // Ignore other exceptions
905		}
906	    }
907	    return true;
908	}
909    }
910
911    // Get the type of network and routing policy
912    class NetTypeStep implements WizardStep {
913	private JRadioButton lan, ptp;
914	private ButtonGroup typeGroup, routingGroup;
915	private JRadioButton discover, specify;
916	private IPAddressField address;
917	private Box stepBox;
918	private boolean firstTime = true;
919
920	public NetTypeStep() {
921	    stepBox = Box.createVerticalBox();
922
923	    // Explanatory text at the top
924	    stepBox.add(Wizard.createTextArea(
925		ResourceStrings.getString("cfg_wiz_nettype_explain"), 2, 45));
926	    stepBox.add(Box.createVerticalStrut(10));
927
928	    // Label and radio buttons for type of network
929	    JPanel panel = new JPanel(new GridLayout(2, 1));
930	    /*
931	     * Create a compound border with empty space on the outside and
932	     * a line border on the inside, then title it amd put a space
933	     * around the outside.
934	     */
935	    Border b = BorderFactory.createCompoundBorder(
936		BorderFactory.createEmptyBorder(0, 5, 0, 5),
937		BorderFactory.createLineBorder(Color.black));
938	    Border tb = BorderFactory.createTitledBorder(b,
939		ResourceStrings.getString("cfg_wiz_nettype_label"));
940	    panel.setBorder(BorderFactory.createCompoundBorder(tb,
941		BorderFactory.createEmptyBorder(0, 5, 0, 5)));
942
943            lan = new JRadioButton(ResourceStrings.getString("cfg_wiz_lan"),
944                true);
945            lan.setToolTipText(ResourceStrings.getString("cfg_wiz_lan"));
946            typeGroup = new ButtonGroup();
947            typeGroup.add(lan);
948            panel.add(lan);
949            ptp = new JRadioButton(ResourceStrings.getString("cfg_wiz_point"),
950                false);
951            ptp.setToolTipText(ResourceStrings.getString("cfg_wiz_point"));
952            typeGroup.add(ptp);
953            panel.add(ptp);
954            stepBox.add(panel);
955            stepBox.add(Box.createVerticalStrut(20));
956
957	    // Routing policy
958	    panel = new JPanel(new GridLayout(2, 1));
959	    tb = BorderFactory.createTitledBorder(b,
960		ResourceStrings.getString("cfg_wiz_routing_label"));
961	    panel.setBorder(BorderFactory.createCompoundBorder(tb,
962		BorderFactory.createEmptyBorder(0, 5, 0, 5)));
963
964	    discover = new JRadioButton(
965		ResourceStrings.getString("cfg_wiz_router_discovery"), true);
966	    discover.setToolTipText(ResourceStrings.getString(
967		"cfg_wiz_router_discovery"));
968	    routingGroup = new ButtonGroup();
969	    routingGroup.add(discover);
970	    panel.add(discover);
971
972	    Box routerBox = Box.createHorizontalBox();
973	    specify = new JRadioButton(
974		ResourceStrings.getString("cfg_wiz_router_specify"), false);
975	    specify.setToolTipText(ResourceStrings.getString(
976		"cfg_wiz_router_specify"));
977	    routingGroup.add(specify);
978	    routerBox.add(specify);
979	    routerBox.add(Box.createHorizontalStrut(2));
980	    address = new IPAddressField();
981	    address.setEnabled(false); // Start off disabled
982	    address.setMaximumSize(address.getPreferredSize());
983
984	    // Box is sensitive to alignment, make sure they all agree
985	    address.setAlignmentY(specify.getAlignmentY());
986
987	    routerBox.add(address);
988	    panel.add(routerBox);
989	    stepBox.add(panel);
990
991	    stepBox.add(Box.createVerticalStrut(10));
992	    stepBox.add(Box.createVerticalGlue());
993
994	    /*
995	     * Enable forward if router discovery, or if specifying router and
996	     * address is not empty.
997	     */
998	    specify.addChangeListener(new ChangeListener() {
999		public void stateChanged(ChangeEvent e) {
1000		    address.setEnabled(specify.isSelected());
1001		    setForwardEnabled(!specify.isSelected()
1002			|| (address.getText().length() != 0));
1003		}
1004	    });
1005
1006	    // Enable forward when address is not empty.
1007	    address.getDocument().addDocumentListener(new DocumentListener() {
1008		public void insertUpdate(DocumentEvent e) {
1009		    setForwardEnabled(address.getText().length() != 0);
1010		}
1011		public void changedUpdate(DocumentEvent e) {
1012		    insertUpdate(e);
1013		}
1014		public void removeUpdate(DocumentEvent e) {
1015		    insertUpdate(e);
1016		}
1017	    });
1018	}
1019
1020	public String getDescription() {
1021	    return ResourceStrings.getString("cfg_wiz_nettype_desc");
1022	}
1023
1024	public Component getComponent() {
1025	    return stepBox;
1026	}
1027
1028	public void setActive(int direction) {
1029	    setForwardEnabled(true);
1030	    lan.setSelected(isLan);
1031	    discover.setSelected(routerDiscovery);
1032	    address.setValue(router);
1033	}
1034
1035	public boolean setInactive(int direction) {
1036	    isLan = lan.isSelected();
1037	    if (direction == FORWARD) {
1038		routerDiscovery = discover.isSelected();
1039		if (!routerDiscovery) {
1040		    IPAddress addr = address.getValue();
1041		    if (addr == null) {
1042			// Invalid IP address
1043			MessageFormat form = new MessageFormat(
1044			    ResourceStrings.getString(
1045			    "cfg_wiz_router_addr_err"));
1046			Object [] args = new Object[1];
1047			args[0] = address.getText();
1048			JOptionPane.showMessageDialog(ConfigWizard.this,
1049				form.format(args),
1050				ResourceStrings.getString("input_error"),
1051				JOptionPane.ERROR_MESSAGE);
1052			return false;
1053		    } else if (!network.containsAddress(addr)) {
1054			// Router is not on the network we're configuring
1055			MessageFormat form = new MessageFormat(
1056			    ResourceStrings.getString(
1057			    "cfg_wiz_router_net_err"));
1058			Object [] args = new Object[2];
1059			args[0] = address.getText();
1060			args[1] = network.toString();
1061			JOptionPane.showMessageDialog(ConfigWizard.this,
1062			    form.format(args),
1063			    ResourceStrings.getString("input_error"),
1064			    JOptionPane.ERROR_MESSAGE);
1065			return false;
1066		    }
1067		    router = addr;
1068		}
1069	    }
1070	    return true;
1071	}
1072    }
1073
1074    // Get the NIS configuration
1075    class NisStep implements WizardStep {
1076	private NoSpaceField domain;
1077	private Box stepBox;
1078	private IPAddressField address;
1079	private JButton add, delete, moveUp, moveDown;
1080	private IPAddressList serverList;
1081	boolean firstActive = true;
1082
1083	public NisStep() {
1084	    stepBox = Box.createVerticalBox();
1085
1086	    stepBox.add(Wizard.createTextArea(
1087		ResourceStrings.getString("cfg_wiz_nis_explain"), 6, 45));
1088	    stepBox.add(Box.createVerticalStrut(10));
1089
1090            JPanel fieldPanel = new JPanel(new FieldLayout());
1091	    Mnemonic mnNis =
1092		new Mnemonic(ResourceStrings.getString("cfg_wiz_nis_domain"));
1093            JLabel jlNISDomain =
1094		new JLabel(mnNis.getString());
1095	    fieldPanel.add(FieldLayout.LABEL, jlNISDomain);
1096	    domain = new NoSpaceField();
1097	    jlNISDomain.setLabelFor(domain);
1098	    jlNISDomain.setToolTipText(mnNis.getString());
1099	    jlNISDomain.setDisplayedMnemonic(mnNis.getMnemonic());
1100	    fieldPanel.add(FieldLayout.FIELD, domain);
1101            stepBox.add(fieldPanel);
1102
1103	    serverList = new IPAddressList();
1104	    Border tb = BorderFactory.createTitledBorder(
1105		BorderFactory.createLineBorder(Color.black),
1106		ResourceStrings.getString("cfg_wiz_nis_servers"));
1107	    serverList.setBorder(BorderFactory.createCompoundBorder(tb,
1108		BorderFactory.createEmptyBorder(5, 5, 5, 5)));
1109	    stepBox.add(serverList);
1110	}
1111
1112	public String getDescription() {
1113	    return ResourceStrings.getString("cfg_wiz_nis_desc");
1114	}
1115
1116	public Component getComponent() {
1117	    return stepBox;
1118	}
1119
1120	public void setActive(int direction) {
1121	    setForwardEnabled(true);
1122	    if (firstActive) {
1123		firstActive = false;
1124		try {
1125		    /*
1126		     * Order here is important; do the servers first because if
1127		     * there's an error, we don't retrieve a domain name, which
1128		     * appears to never fail.
1129		     */
1130		    serverList.setAddressList(
1131			server.getIPOption(StandardOptions.CD_NIS_SERV, ""));
1132		    domain.setText(
1133			server.getStringOption(StandardOptions.CD_NIS_DOMAIN,
1134			""));
1135		} catch (Throwable e) {
1136		    // Do nothing, just setting defaults
1137		}
1138	    }
1139	}
1140
1141	public boolean setInactive(int direction) {
1142	    if (direction == FORWARD) {
1143		/*
1144		 * Either must supply both a domain and a list of servers, or
1145		 * neither
1146		 */
1147		if ((domain.getText().length() == 0)
1148			!= (serverList.getListSize() == 0)) {
1149		    JOptionPane.showMessageDialog(ConfigWizard.this,
1150			ResourceStrings.getString("cfg_wiz_nis_both"),
1151			ResourceStrings.getString("input_error"),
1152			JOptionPane.ERROR_MESSAGE);
1153		    return false;
1154		}
1155	    }
1156	    nisDomain = domain.getText();
1157	    nisServs = serverList.getAddressList();
1158	    return true;
1159	}
1160    }
1161
1162    class ReviewStep implements WizardStep {
1163	private JLabel storeLabel;
1164	private JLabel hostLabel;
1165	private JLabel leaseLabel;
1166	private JLabel networkLabel;
1167	private JLabel netTypeLabel;
1168	private JLabel netmaskLabel;
1169	private JLabel routerLabel;
1170	private JLabel dnsLabel;
1171	private JLabel dnsServLabel;
1172	private JLabel nisLabel;
1173	private JLabel nisServLabel;
1174	private JPanel panel;
1175	private JScrollPane scrollPane;
1176
1177	public ReviewStep() {
1178	    Box stepBox = Box.createVerticalBox();
1179	    if (fullConfig) {
1180		stepBox.add(Wizard.createTextArea(
1181		    ResourceStrings.getString("cfg_wiz_review_explain"), 3,
1182		    45));
1183	    } else {
1184		stepBox.add(Wizard.createTextArea(
1185		    ResourceStrings.getString("net_wiz_review_explain"), 3,
1186		    45));
1187	    }
1188
1189	    panel = new JPanel(new FieldLayout());
1190	    JLabel jlTmp;
1191
1192	    if (fullConfig) {
1193		addLabel("cfg_wiz_datastore");
1194		storeLabel = addField("uninitialized");
1195
1196		addLabel("cfg_wiz_hosts_resource");
1197		hostLabel = addField("uninitialized");
1198
1199		jlTmp = addLabelMnemonic("cfg_wiz_lease_length");
1200		leaseLabel = addField("1 day");
1201
1202		jlTmp = addLabelMnemonic("cfg_wiz_dns_domain");
1203		dnsLabel = addField("Bar.Sun.COM");
1204
1205		addLabel("cfg_wiz_dns_servers");
1206		dnsServLabel = addField("109.151.1.15, 109.148.144.2");
1207	    }
1208
1209	    jlTmp = addLabelMnemonic("cfg_wiz_network");
1210	    networkLabel = addField("109.148.21.0");
1211	    jlTmp.setLabelFor(networkLabel);
1212
1213	    jlTmp = addLabelMnemonic("cfg_wiz_mask");
1214	    netmaskLabel = addField("255.255.255.0");
1215	    jlTmp.setLabelFor(netmaskLabel);
1216
1217	    addLabel("cfg_wiz_nettype");
1218	    netTypeLabel = addField(ResourceStrings.getString("cfg_wiz_lan"));
1219
1220	    addLabel("cfg_wiz_router");
1221	    routerLabel = addField(
1222		ResourceStrings.getString("cfg_wiz_router_discovery"));
1223
1224	    jlTmp = addLabelMnemonic("cfg_wiz_nis_domain");
1225	    nisLabel = addField("Foo.Bar.Sun.COM");
1226	    jlTmp.setLabelFor(nisLabel);
1227
1228	    addLabel("cfg_wiz_nis_servers");
1229	    nisServLabel = addField("109.148.21.21, 109.148.21.44");
1230
1231	    stepBox.add(panel);
1232	    stepBox.add(Box.createVerticalGlue());
1233
1234	    scrollPane = new JScrollPane(stepBox,
1235		JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
1236		JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
1237	}
1238
1239	private void addLabel(String s) {
1240	    JLabel jl;
1241	    jl = new JLabel(ResourceStrings.getString(s));
1242	    panel.add(FieldLayout.LABEL, jl);
1243	    jl.setLabelFor(panel);
1244	    jl.setToolTipText(ResourceStrings.getString(s));
1245	}
1246
1247	private JLabel addLabelMnemonic(String s) {
1248	    JLabel jl;
1249	    Mnemonic mnStr =
1250                new Mnemonic(ResourceStrings.getString(s));
1251	    jl = new JLabel(mnStr.getString());
1252	    panel.add(FieldLayout.LABEL, jl);
1253            jl.setToolTipText(mnStr.getString());
1254	    return jl;
1255        }
1256
1257	private JLabel addField(String s) {
1258	    JLabel l = new JLabel(s);
1259	    l.setForeground(Color.black);
1260	    panel.add(FieldLayout.FIELD, l);
1261	    l.setLabelFor(panel);
1262	    l.setToolTipText(s);
1263	    return l;
1264	}
1265
1266	public String getDescription() {
1267	    return ResourceStrings.getString("cfg_wiz_review_desc");
1268	}
1269
1270	public Component getComponent() {
1271	    return scrollPane;
1272	}
1273
1274	public void setActive(int direction) {
1275	    StringBuffer b = new StringBuffer();
1276	    setFinishEnabled(true);
1277	    if (fullConfig) {
1278		storeLabel.setText(getDsconf().getModule().getDescription());
1279		hostLabel.setText(getHostResource().getDescription());
1280
1281		// Display lease length, reducing to largest units possible
1282		int lengthVal = 0;
1283		int i;
1284		for (i = unitMultiples.length - 1; i >= 0; --i) {
1285		    lengthVal = leaseLength / unitMultiples[i];
1286		    if ((lengthVal != 0)
1287			    && (leaseLength % unitMultiples[i] == 0)) {
1288			break;
1289		    }
1290		}
1291		if (i == -1) {
1292		    i = 0;
1293		}
1294		Object [] objs = new Object[3];
1295		objs[0] = new Integer(lengthVal);
1296		objs[1] = unitChoices[i];
1297		if (leaseNegotiable) {
1298		    objs[2] = ResourceStrings.getString("cfg_wiz_renewable");
1299		} else {
1300		    objs[2] = ResourceStrings.getString("cfg_wiz_nonrenewable");
1301		}
1302		leaseLabel.setText(MessageFormat.format(
1303		    ResourceStrings.getString("cfg_wiz_lease_fmt"), objs));
1304
1305		// Set DNS info
1306		dnsLabel.setText(dnsDomain);
1307		b.setLength(0);
1308		Enumeration en = dnsServs.elements();
1309		while (en.hasMoreElements()) {
1310		    IPAddress a = (IPAddress)en.nextElement();
1311		    if (b.length() != 0) {
1312			b.append(", ");
1313		    }
1314		    b.append(a.getHostAddress());
1315		}
1316		dnsServLabel.setText(b.toString());
1317	    }
1318
1319	    // Set network address
1320	    networkLabel.setText(network.toString());
1321	    // Set subnet mask
1322	    netmaskLabel.setText(network.getMask().getHostAddress());
1323
1324	    // Set network type
1325	    if (isLan) {
1326		netTypeLabel.setText(ResourceStrings.getString("cfg_wiz_lan"));
1327	    } else {
1328		netTypeLabel.setText(
1329		    ResourceStrings.getString("cfg_wiz_point"));
1330	    }
1331
1332	    // Set router
1333	    if (routerDiscovery) {
1334		routerLabel.setText(
1335		    ResourceStrings.getString("cfg_wiz_router_discovery"));
1336	    } else {
1337		routerLabel.setText(router.getHostAddress());
1338	    }
1339
1340	    // Set NIS info
1341	    nisLabel.setText(nisDomain);
1342	    b.setLength(0);
1343	    Enumeration en = nisServs.elements();
1344	    while (en.hasMoreElements()) {
1345		IPAddress a = (IPAddress)en.nextElement();
1346		if (b.length() != 0) {
1347		    b.append(", ");
1348		}
1349		b.append(a.getHostAddress());
1350	    }
1351	    nisServLabel.setText(b.toString());
1352	}
1353
1354	public boolean setInactive(int direction) {
1355	    return true;
1356	}
1357    }
1358
1359    public ConfigWizard(Frame owner, String title, boolean fullConfig) {
1360	super(owner, title);
1361
1362	try {
1363	    server = DataManager.get().getDhcpServiceMgr();
1364	    if (fullConfig) {
1365		dsconfList = new DSConfList();
1366		dsconfList.init(server);
1367	    }
1368	} catch (Throwable e) {
1369	    e.printStackTrace(); // XXX Need to do something to handle this...
1370	    return;
1371	}
1372
1373	this.fullConfig = fullConfig;
1374
1375	// If running as Config Wizard, put in the initial steps.
1376	if (fullConfig) {
1377	    addStep(new DatastoreStep(
1378		ResourceStrings.getString("cfg_wiz_explain"),
1379		ResourceStrings.getString("cfg_wiz_store_explain")));
1380	    addStep(new DatastoreModuleStep());
1381	    addStep(new HostDataStep());
1382	    addStep(new LeaseStep());
1383	    addStep(new DnsStep());
1384	}
1385	// Now the steps that are common to both wizards.
1386	addStep(new NetworkStep());
1387	addStep(new NetTypeStep());
1388	addStep(new NisStep());
1389	addStep(new ReviewStep());
1390	showFirstStep();
1391    }
1392
1393    public void doFinish() {
1394	/*
1395	 * To activate the server, we have to do the following items:
1396	 * 1. Create the location/path if necessary.
1397	 * 2. Create the defaults file.
1398	 * 3. Create the dhcptab; ignore errors if it already exists
1399	 *    (as in NIS+ case)
1400	 * 4. Create the Locale macro; ignore the error if it already exists
1401	 * 5. Create the server macro; if it exists we just overwrite it
1402	 * 6. Create the network macro;
1403	 * 7. Create the network table
1404	 * 8. Start the service
1405	 */
1406	if (fullConfig) {
1407	    getDsconf().setConfig();
1408	    getDsconf().setLocation();
1409	    // Create the location/path.
1410	    try {
1411		server.makeLocation(getDsconf().getDS());
1412	    } catch (ExistsException e) {
1413		// this is o.k.
1414	    } catch (Throwable e) {
1415		MessageFormat form = new MessageFormat(
1416		    ResourceStrings.getString("create_location_error"));
1417		Object [] args = new Object[1];
1418		args[0] = getDsconf().getDS().getLocation();
1419		String msg = form.format(args);
1420		JOptionPane.showMessageDialog(ConfigWizard.this,
1421		    msg,
1422		    ResourceStrings.getString("server_error_title"),
1423		    JOptionPane.ERROR_MESSAGE);
1424		return;
1425	    }
1426
1427	    // Create the defaults file.
1428	    DhcpdOptions options = new DhcpdOptions();
1429	    options.setDaemonEnabled(true);
1430	    options.setDhcpDatastore(getDsconf().getDS());
1431	    if (getHostResource().getResource() != null) {
1432		options.setHostsResource(getHostResource().getResource());
1433	    }
1434	    if (getHostResource().getDomain() != null) {
1435		options.setHostsDomain(getHostResource().getDomain());
1436	    }
1437	    try {
1438		server.writeDefaults(options);
1439	    } catch (Throwable e) {
1440		e.printStackTrace();
1441		return;
1442	    }
1443
1444	    // Create the dhcptab
1445	    try {
1446		DataManager.get().getDhcptabMgr().createDhcptab();
1447	    } catch (Throwable e) {
1448		// Not an error; some data stores are shared by multiple servers
1449	    }
1450	}
1451
1452	if (fullConfig) {
1453	    try {
1454		DataManager.get().getDhcptabMgr().createLocaleMacro();
1455	    } catch (Throwable e) {
1456		/*
1457		 * Ignore this error, if one's already there we'll assume
1458		 * it's correct
1459		 */
1460	    }
1461
1462	    // Create the Server macro
1463	    try {
1464		String svrName =
1465		    DataManager.get().getDhcpServiceMgr().getShortServerName();
1466		InetAddress svrAddress =
1467		    DataManager.get().getDhcpServiceMgr().getServerAddress();
1468		DataManager.get().getDhcptabMgr().createServerMacro(svrName,
1469		    svrAddress, leaseLength, leaseNegotiable, dnsDomain,
1470		    dnsServs);
1471	    } catch (Throwable e) {
1472		// Couldn't create it; inform user because this is serious
1473		Object [] args = new Object[2];
1474		MessageFormat form = new MessageFormat(
1475		    ResourceStrings.getString("create_macro_error"));
1476		args[0] = DataManager.get().getShortServerName();
1477		args[1] = e.getMessage();
1478		JOptionPane.showMessageDialog(this, form.format(args),
1479		    ResourceStrings.getString("server_error_title"),
1480		    JOptionPane.ERROR_MESSAGE);
1481		return;
1482	    }
1483	}
1484
1485	// Create the network macro
1486	IPAddress [] routers = null;
1487	if (router != null) {
1488	    routers = new IPAddress[] { router };
1489	}
1490	try {
1491	    DataManager.get().getDhcptabMgr().createNetworkMacro(network,
1492		routers, isLan, nisDomain, nisServs);
1493	} catch (Throwable e) {
1494	    // Ignore this error? dhcpconfig gives a merge option
1495	}
1496
1497	// Create the network table
1498	try {
1499	    DataManager.get().getDhcpNetMgr().createNetwork(network.toString());
1500	} catch (BridgeException e) {
1501	    // This indicates table existed; no error
1502	} catch (Throwable e) {
1503	    Object [] args = new Object[2];
1504	    MessageFormat form = new MessageFormat(
1505		ResourceStrings.getString("create_network_table_error"));
1506	    args[0] = network.toString();
1507	    args[1] = e.getMessage();
1508	    JOptionPane.showMessageDialog(this, form.format(args),
1509		ResourceStrings.getString("server_error_title"),
1510		JOptionPane.ERROR_MESSAGE);
1511	    return;
1512	}
1513
1514	// Start the server in the initial configuration case
1515	if (fullConfig) {
1516	    try {
1517		DataManager.get().getDhcpServiceMgr().startup();
1518	    } catch (Throwable e) {
1519		// Just warn user; this isn't disastrous
1520		Object [] args = new Object[1];
1521		MessageFormat form = new MessageFormat(
1522		    ResourceStrings.getString("startup_server_error"));
1523		args[0] = e.getMessage();
1524		JOptionPane.showMessageDialog(this, form.format(args),
1525		    ResourceStrings.getString("server_error_title"),
1526		    JOptionPane.WARNING_MESSAGE);
1527	    }
1528	}
1529
1530	super.doFinish();
1531    }
1532
1533    public void doHelp() {
1534	if (fullConfig) {
1535	    DhcpmgrApplet.showHelp("config_wizard");
1536	} else {
1537	    DhcpmgrApplet.showHelp("network_wizard");
1538	}
1539    }
1540
1541    /**
1542     * Sets hostResource.
1543     * @param hostResource the host resource value.
1544     */
1545    public void setHostResource(HostResource hostResource) {
1546	this.hostResource = hostResource;
1547    } // setHostResource
1548
1549    /**
1550     * Returns the hostResource.
1551     * @return the hostResource.
1552     */
1553    public HostResource getHostResource() {
1554	return hostResource;
1555    } // getHostResource
1556
1557}
1558