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 
LocationStep()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 
getDescription()144 	public String getDescription() {
145 	    return ResourceStrings.getString("imp_wiz_file_desc");
146 	}
147 
getComponent()148 	public Component getComponent() {
149 	    return stepPanel;
150 	}
151 
setActive(int direction)152 	public void setActive(int direction) {
153 	    pathField.setText(importPath);
154 	    overrideBox.setSelected(conflictImport);
155 	    setForwardEnabled(importPath.length() != 0);
156 	}
157 
setInactive(int direction)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 
ReviewStep()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 
getDescription()276 	public String getDescription() {
277 	    return ResourceStrings.getString("imp_wiz_review_desc");
278 	}
279 
getComponent()280 	public Component getComponent() {
281 	    return stepBox;
282 	}
283 
setActive(int direction)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 
setInactive(int direction)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 
ErrorDisplay(Object [] objs)313 	public ErrorDisplay(Object [] objs) {
314 	    this.objs = objs;
315 	}
316 
run()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 
ImportWizard(Frame owner)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 
doFinish()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 
doCancel()424     public void doCancel() {
425 	// Close file if there is one open
426 	importController.closeFile();
427 	super.doCancel();
428     }
429 
reallyFinish()430     protected void reallyFinish() {
431 	super.doFinish();
432     }
433 
doHelp()434     public void doHelp() {
435 	DhcpmgrApplet.showHelp("import_wizard");
436     }
437 }
438