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 }