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 }