1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License, Version 1.0 only
   6  * (the "License").  You may not use this file except in compliance
   7  * with the License.
   8  *
   9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10  * or http://www.opensolaris.org/os/licensing.
  11  * See the License for the specific language governing permissions
  12  * and limitations under the License.
  13  *
  14  * When distributing Covered Code, include this CDDL HEADER in each
  15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16  * If applicable, add the following below this CDDL HEADER, with the
  17  * fields enclosed by brackets "[]" replaced with your own identifying
  18  * information: Portions Copyright [yyyy] [name of copyright owner]
  19  *
  20  * CDDL HEADER END
  21  */
  22 /*
  23  * ident        "%Z%%M% %I%     %E% SMI"
  24  *
  25  * Copyright 2001-2002 by Sun Microsystems, Inc.  All rights reserved.
  26  * Use is subject to license terms.
  27  */
  28 
  29 package com.sun.dhcpmgr.client;
  30 
  31 import javax.swing.*;
  32 import javax.swing.event.*;
  33 import java.awt.*;
  34 import java.util.Date;
  35 import java.text.SimpleDateFormat;
  36 import java.text.MessageFormat;
  37 import java.lang.reflect.InvocationTargetException;
  38 import java.io.FileNotFoundException;
  39 
  40 import com.sun.dhcpmgr.ui.*;
  41 import com.sun.dhcpmgr.data.ActionError;
  42 import com.sun.dhcpmgr.data.ExportHeader;
  43 import com.sun.dhcpmgr.common.*;
  44 
  45 /**
  46  * ImportWizard provides an easy-to-use interface for importing configuration
  47  * data from one DHCP server to another.
  48  *
  49  * @see ExportWizard
  50  */
  51 public class ImportWizard extends Wizard {
  52 
  53     // Step to get the location of the export file
  54     class LocationStep implements WizardStep {
  55         JPanel stepPanel;
  56         JTextField pathField;
  57         JCheckBox overrideBox;
  58 
  59         public LocationStep() {
  60             GridBagLayout bag = new GridBagLayout();
  61             GridBagConstraints con = new GridBagConstraints();
  62             con.insets = new Insets(2, 2, 2, 2);
  63             con.gridx = con.gridy = 0;
  64             con.gridwidth = 2;
  65             con.gridheight = 1;
  66             con.weightx = 0;
  67             con.weighty = 1.0;
  68             con.fill = GridBagConstraints.BOTH;
  69             con.anchor = GridBagConstraints.NORTHWEST;
  70 
  71             stepPanel = new JPanel(bag);
  72 
  73             Component c = Wizard.createTextArea(
  74                 ResourceStrings.getString("imp_wiz_location_explain"), 8, 45);
  75             bag.setConstraints(c, con);
  76             stepPanel.add(c);
  77 
  78             Mnemonic mnFile =
  79                 new Mnemonic(ResourceStrings.getString("imp_wiz_file_label"));
  80             JLabel l = new JLabel(mnFile.getString());
  81             l.setToolTipText(mnFile.getString());
  82             l.setDisplayedMnemonic(mnFile.getMnemonic());
  83 
  84             ++con.gridy;
  85             con.gridwidth = 1;
  86             con.weighty = 0;
  87             con.fill = GridBagConstraints.HORIZONTAL;
  88             bag.setConstraints(l, con);
  89             stepPanel.add(l);
  90 
  91             pathField = new JTextField(importPath);
  92             l.setLabelFor(pathField);
  93             ++con.gridx;
  94             con.weightx = 1.0;
  95             bag.setConstraints(pathField, con);
  96             stepPanel.add(pathField);
  97 
  98             c = Wizard.createTextArea(
  99                 ResourceStrings.getString("imp_wiz_override_explain"), 4, 45);
 100             con.gridx = 0;
 101             ++con.gridy;
 102             con.weighty = 0.5;
 103             con.weightx = 0;
 104             con.fill = GridBagConstraints.BOTH;
 105             con.gridwidth = 2;
 106             bag.setConstraints(c, con);
 107             stepPanel.add(c);
 108 
 109             overrideBox = new JCheckBox(
 110                 ResourceStrings.getString("imp_wiz_override_data"), false);
 111             overrideBox.setToolTipText(
 112                 ResourceStrings.getString("imp_wiz_override_data"));
 113             con.gridx = 0;
 114             ++con.gridy;
 115             con.gridwidth = 2;
 116             con.weighty = 0;
 117             con.weightx = 1.0;
 118             con.fill = GridBagConstraints.HORIZONTAL;
 119             bag.setConstraints(overrideBox, con);
 120             stepPanel.add(overrideBox);
 121 
 122             c = Box.createVerticalGlue();
 123             ++con.gridy;
 124             con.weighty = 1.0;
 125             con.weightx = 0;
 126             con.fill = GridBagConstraints.VERTICAL;
 127             bag.setConstraints(c, con);
 128             stepPanel.add(c);
 129 
 130             // Enable forward only if something is entered in the file field
 131             pathField.getDocument().addDocumentListener(new DocumentListener() {
 132                 public void insertUpdate(DocumentEvent e) {
 133                     setForwardEnabled(pathField.getText().length() != 0);
 134                 }
 135                 public void changedUpdate(DocumentEvent e) {
 136                     insertUpdate(e);
 137                 }
 138                 public void removeUpdate(DocumentEvent e) {
 139                     insertUpdate(e);
 140                 }
 141             });
 142         }
 143 
 144         public String getDescription() {
 145             return ResourceStrings.getString("imp_wiz_file_desc");
 146         }
 147 
 148         public Component getComponent() {
 149             return stepPanel;
 150         }
 151 
 152         public void setActive(int direction) {
 153             pathField.setText(importPath);
 154             overrideBox.setSelected(conflictImport);
 155             setForwardEnabled(importPath.length() != 0);
 156         }
 157 
 158         public boolean setInactive(int direction) {
 159             importPath = pathField.getText();
 160             conflictImport = overrideBox.isSelected();
 161             /*
 162              * Read the file header for display in next step; if we can't read
 163              * it, display the errors and veto the forward step.
 164              */
 165             if (direction == FORWARD) {
 166                 importController.setFile(importPath);
 167                 try {
 168                     header = importController.getHeader();
 169                     if (header == null) {
 170                         // Something wrong, but controller already displayed err
 171                         return false;
 172                     }
 173                 } catch (FileNotFoundException e) {
 174                     JOptionPane.showMessageDialog(ImportWizard.this,
 175                         ResourceStrings.getString("imp_err_file_not_found"),
 176                         ResourceStrings.getString("server_error_title"),
 177                         JOptionPane.ERROR_MESSAGE);
 178                     return false;
 179                 } catch (Exception e) {
 180                     String [] msgs = new String [] {
 181                         ResourceStrings.getString("imp_err_reading_header"),
 182                         e.getMessage()
 183                     };
 184                     JOptionPane.showMessageDialog(ImportWizard.this, msgs,
 185                         ResourceStrings.getString("server_error_title"),
 186                         JOptionPane.ERROR_MESSAGE);
 187                     return false;
 188                 }
 189             }
 190             return true;
 191         }
 192     }
 193 
 194     // Allow user to review summary of file contents before proceeding.
 195     class ReviewStep implements WizardStep {
 196         private Box stepBox;
 197         private JLabel fileLabel, srcLabel, userLabel, dateLabel, overrideLabel;
 198         private JLabel infoLabel;
 199         private SimpleDateFormat dateFormat = new SimpleDateFormat();
 200         private MessageFormat infoFormat =
 201             new MessageFormat(ResourceStrings.getString("imp_wiz_review_info"));
 202 
 203         public ReviewStep() {
 204             stepBox = Box.createVerticalBox();
 205             JComponent jc = Wizard.createTextArea(
 206                 ResourceStrings.getString("imp_wiz_review_explain"), 6, 45);
 207             jc.setAlignmentX(Component.LEFT_ALIGNMENT);
 208             stepBox.add(jc);
 209 
 210             Mnemonic mnFl =
 211                 new Mnemonic(ResourceStrings.getString("imp_wiz_file_label"));
 212             JPanel fieldPanel = new JPanel(new FieldLayout());
 213             JLabel l = new JLabel(mnFl.getString());
 214             l.setLabelFor(fieldPanel);
 215             l.setToolTipText(mnFl.getString());
 216             fieldPanel.add(l, FieldLayout.LABEL);
 217 
 218             fileLabel = new JLabel();
 219             fileLabel.setForeground(Color.black);
 220             fieldPanel.add(fileLabel, FieldLayout.FIELD);
 221 
 222             l = new JLabel(
 223                 ResourceStrings.getString("imp_wiz_review_override"));
 224             fieldPanel.add(l, FieldLayout.LABEL);
 225             l.setToolTipText(
 226                 ResourceStrings.getString("imp_wiz_review_override"));
 227 
 228             overrideLabel = new JLabel();
 229             l.setLabelFor(overrideLabel);
 230             overrideLabel.setForeground(Color.black);
 231             fieldPanel.add(overrideLabel, FieldLayout.FIELD);
 232 
 233             fieldPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
 234             stepBox.add(fieldPanel);
 235 
 236             stepBox.add(Box.createVerticalStrut(5));
 237 
 238             infoLabel = new JLabel();
 239             infoLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
 240             stepBox.add(infoLabel);
 241 
 242             l = new JLabel(
 243                 ResourceStrings.getString("imp_wiz_review_src"));
 244             fieldPanel = new JPanel(new FieldLayout());
 245             fieldPanel.add(l, FieldLayout.LABEL);
 246             l.setToolTipText(ResourceStrings.getString("imp_wiz_review_src"));
 247 
 248             srcLabel = new JLabel();
 249             l.setLabelFor(srcLabel);
 250             fieldPanel.add(srcLabel, FieldLayout.FIELD);
 251            
 252             l = new JLabel(
 253                 ResourceStrings.getString("imp_wiz_review_user"));
 254             fieldPanel.add(l, FieldLayout.LABEL);
 255             l.setToolTipText(ResourceStrings.getString("imp_wiz_review_user"));
 256 
 257             userLabel = new JLabel();
 258             l.setLabelFor(userLabel);
 259             fieldPanel.add(userLabel, FieldLayout.FIELD);
 260 
 261             l = new JLabel(
 262                 ResourceStrings.getString("imp_wiz_review_date"));
 263             fieldPanel.add(l, FieldLayout.LABEL);
 264             l.setToolTipText(ResourceStrings.getString("imp_wiz_review_date"));
 265 
 266             dateLabel = new JLabel(dateFormat.format(new Date()));
 267             l.setLabelFor(dateLabel);
 268             fieldPanel.add(dateLabel, FieldLayout.FIELD);
 269 
 270             fieldPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
 271             stepBox.add(fieldPanel);
 272 
 273             stepBox.add(Box.createVerticalGlue());
 274         }
 275 
 276         public String getDescription() {
 277             return ResourceStrings.getString("imp_wiz_review_desc");
 278         }
 279 
 280         public Component getComponent() {
 281             return stepBox;
 282         }
 283 
 284         public void setActive(int direction) {
 285             fileLabel.setText(importPath);
 286             if (conflictImport) {
 287                 overrideLabel.setText(ResourceStrings.getString("yes"));
 288             } else {
 289                 overrideLabel.setText(ResourceStrings.getString("no"));
 290             }
 291             Object [] objs = new Object [] { importPath };
 292             infoLabel.setText(infoFormat.format(objs));
 293             // Set values from file header
 294             srcLabel.setText(header.getServer());
 295             userLabel.setText(header.getUser());
 296             dateLabel.setText(dateFormat.format(header.getDate()));
 297             
 298             setFinishEnabled(true);
 299         }
 300 
 301         public boolean setInactive(int direction) {
 302             return true;
 303         }
 304     }
 305 
 306     /*
 307      * Display an error message inside a separate thread so that background
 308      * threads may interact with the user via SwingUtilities.invoke*
 309      */
 310     class ErrorDisplay implements Runnable {
 311         Object [] objs;
 312 
 313         public ErrorDisplay(Object [] objs) {
 314             this.objs = objs;
 315         }
 316 
 317         public void run() {
 318             JOptionPane.showMessageDialog(ImportWizard.this, objs,
 319                 ResourceStrings.getString("server_error_title"),
 320                 JOptionPane.ERROR_MESSAGE);
 321         }
 322     }
 323 
 324     private String importPath = "";
 325     private boolean conflictImport = false;
 326     private ImportController importController;
 327     private ExportHeader header;
 328     /*
 329      * The Importer allows the ImportController, which contains all of the
 330      * actual import logic, to interact with the user as the import proceeds.
 331      * Since we run the import in a background thread to keep the GUI live,
 332      * the interactions must use SwingUtilities.invoke* to control the GUI.
 333      * Progress updates via ProgressManager don't need special logic here as
 334      * ProgressManager already handles the threading work for us.
 335      */
 336     private Importer importer = new Importer() {
 337         ProgressManager progress;
 338         String [] errObjs = new String [] {
 339             ResourceStrings.getString("imp_error"), ""
 340         };
 341 
 342         // Create progress display
 343         public void initializeProgress(int length) {
 344             progress = new ProgressManager(ImportWizard.this,
 345                 ResourceStrings.getString("imp_progress_title"), "", 0,
 346                 length);
 347         }
 348 
 349         // Update progress display with current completion level and message
 350         public void updateProgress(int done, String message)
 351                 throws InterruptedException {
 352             progress.update(done, message);
 353         }
 354 
 355         // Display a single error message
 356         public void displayError(String message) {
 357             errObjs[1] = message;
 358             displayError(errObjs);
 359         }
 360 
 361         // Display a group of error messages using a table.
 362         public void displayErrors(String msg, String label,
 363                 ActionError [] errors) {
 364             ErrorTable errTable = new ErrorTable(label);
 365             errTable.setErrors(errors);
 366             JScrollPane scrollPane = new JScrollPane(errTable);
 367             Object [] errObjs = new Object [] { msg, scrollPane };
 368             displayError(errObjs);
 369         }
 370 
 371         // Display an error in the GUI
 372         private void displayError(Object [] errObjs) {
 373             // If we're on the event dispatch thread already then display now
 374             ErrorDisplay ed = new ErrorDisplay(errObjs);
 375             if (SwingUtilities.isEventDispatchThread()) {
 376                 ed.run();
 377             } else {
 378                 try {
 379                     SwingUtilities.invokeAndWait(ed);
 380                 } catch (Exception e) {
 381                     // Errors here are fairly serious; dump the stack
 382                     e.printStackTrace();
 383                 }
 384             }
 385         }
 386     };
 387 
 388     public ImportWizard(Frame owner) {
 389         super(owner, "");
 390         setTitle(ResourceStrings.getString("import_wiz_title"));
 391 
 392         addStep(new LocationStep());
 393         addStep(new ReviewStep());
 394 
 395         importController = new ImportController(importer,
 396             DataManager.get().getServer());
 397         showFirstStep();
 398     }
 399 
 400     public void doFinish() {
 401         /*
 402          * Runnable which the importThread can call to tear down the display
 403          * when it's completed.
 404          */
 405         final Runnable finisher = new Runnable() {
 406             public void run() {
 407                 reallyFinish();
 408             }
 409         };
 410 
 411         // Create the thread in which to execute the import
 412         Thread importThread = new Thread() {
 413             public void run() {     
 414                 if (importController.importData(conflictImport)) {
 415                     // Only exit if import successful
 416                     SwingUtilities.invokeLater(finisher);
 417                 }
 418             }
 419         };
 420         // Run the import thread
 421         importThread.start();
 422     }
 423 
 424     public void doCancel() {
 425         // Close file if there is one open
 426         importController.closeFile();
 427         super.doCancel();
 428     }
 429 
 430     protected void reallyFinish() {
 431         super.doFinish();
 432     }
 433 
 434     public void doHelp() {
 435         DhcpmgrApplet.showHelp("import_wizard");
 436     }
 437 }