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 * Copyright 2001-2002 by Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26 package com.sun.dhcpmgr.client;
27
28 import java.awt.*;
29 import java.awt.event.*;
30 import java.util.*;
31 import java.text.MessageFormat;
32 import java.net.*;
33
34 import javax.swing.*;
35 import javax.swing.table.*;
36 import javax.swing.event.*;
37 import javax.swing.border.*;
38
39 import com.sun.dhcpmgr.ui.*;
40 import com.sun.dhcpmgr.data.*;
41 import com.sun.dhcpmgr.server.*;
42 import com.sun.dhcpmgr.bridge.BridgeException;
43 import com.sun.dhcpmgr.bridge.ExistsException;
44
45 /**
46 * This wizard converts the DHCP service data store.
47 */
48 public class ConvertWizard extends DSWizard {
49
50 /**
51 * Handle to the service server.
52 */
53 private DhcpServiceMgr svcServer;
54
55 /**
56 * Handle to the dhcptab table server.
57 */
58 private DhcptabMgr dhcptabServer;
59
60 /**
61 * Handle to the network tables server.
62 */
63 private DhcpNetMgr netServer;
64
65 /**
66 * The DHCP defaults.
67 */
68 private DhcpdOptions dhcpdOptions;
69
70 /**
71 * The old data store config.
72 */
73 private DSConf defaultDsconf;
74
75 /**
76 * The save tables wizard step
77 */
78 private SaveTablesStep saveTablesStep;
79
80 /**
81 * List of networks to be converted.
82 */
83 private Network[] networks = null;
84
85 /**
86 * This class is the wizard step that presents the user with
87 * the option to save the tables after conversion.
88 */
89 protected class SaveTablesStep implements WizardStep {
90
91 /**
92 * The component provided to the wizard.
93 */
94 private Box stepBox;
95
96 /**
97 * The checkbox that determines whether the DHCP tables should be
98 * saved after conversion.
99 */
100 private JCheckBox saveTables;
101
102 /**
103 * Basic constructor.
104 */
105 public SaveTablesStep() {
106
107 stepBox = Box.createVerticalBox();
108
109 // Explanatory text at the top
110 //
111 stepBox.add(Wizard.createTextArea(
112 ResourceStrings.getString("cvt_wiz_save_explain"), 4, 45));
113 stepBox.add(Box.createVerticalStrut(10));
114 stepBox.add(Box.createVerticalGlue());
115
116 // Add the checkbox.
117 //
118 saveTables = new JCheckBox(
119 ResourceStrings.getString("cvt_wiz_save_label"), false);
120 saveTables.setToolTipText(
121 ResourceStrings.getString("cvt_wiz_save_label"));
122 saveTables.setAlignmentX(Component.LEFT_ALIGNMENT);
123 stepBox.add(saveTables);
124 stepBox.add(Box.createVerticalGlue());
125
126 stepBox.add(Wizard.createTextArea(
127 ResourceStrings.getString("cvt_wiz_save_note"), 4, 45));
128 stepBox.add(Box.createVerticalStrut(10));
129 stepBox.add(Box.createVerticalGlue());
130
131 } // constructor
132
133 public String getDescription() {
134 return ResourceStrings.getString("cvt_wiz_save_tables_desc");
135 } // getDescription
136
137 public Component getComponent() {
138 return stepBox;
139 } // getComponent
140
141 public void setActive(int direction) {
142 setForwardEnabled(true);
143 } // setActive
144
145 public boolean setInactive(int direction) {
146 return true;
147 } // setInactive
148
149 public boolean isSaveTablesSelected() {
150 return saveTables.isSelected();
151 }
152
153 } // SaveTablesStep
154
155 /**
156 * This class provides the review step for the conversion wizard.
157 */
158 class ReviewStep implements WizardStep {
159
160 /**
161 * The label for the old data store.
162 */
163 private JLabel oldStoreLabel;
164
165 /**
166 * The label for the new data store.
167 */
168 private JLabel newStoreLabel;
169
170 /**
171 * The label for saving tables.
172 */
173 private JLabel saveLabel;
174
175 /**
176 * The component to provide to the conversion wizard.
177 */
178 private Box stepBox;
179
180 /**
181 * The panel used to create the review information.
182 */
183 private JPanel panel;
184
185 /**
186 * The constructor for the step.
187 */
188 public ReviewStep() {
189
190 stepBox = Box.createVerticalBox();
191 stepBox.add(Wizard.createTextArea(
192 ResourceStrings.getString("cvt_wiz_review_explain"),
193 3, 45));
194
195 panel = new JPanel(new FieldLayout());
196
197 addLabel("cvt_wiz_old_datastore").setToolTipText(
198 ResourceStrings.getString("cvt_wiz_old_datastore"));
199 oldStoreLabel = addField("uninitialized");
200
201 addLabel("cvt_wiz_new_datastore").setToolTipText(
202 ResourceStrings.getString("cvt_wiz_new_datastore"));
203 newStoreLabel = addField("uninitialized");
204
205 addLabel("cvt_wiz_save_tables").setToolTipText(
206 ResourceStrings.getString("cvt_wiz_save_tables"));
207 saveLabel = addField("uninitialized");
208
209 stepBox.add(panel);
210 stepBox.add(Box.createVerticalGlue());
211
212 stepBox.add(Wizard.createTextArea(
213 ResourceStrings.getString("cvt_wiz_review_note"), 4, 45));
214 stepBox.add(Box.createVerticalStrut(10));
215 stepBox.add(Box.createVerticalGlue());
216
217 } // constructor
218
219 /**
220 * Adds a label to the review panel.
221 * @param s the label string.
222 */
223 private JLabel addLabel(String s) {
224 JLabel addLbl =
225 new JLabel(ResourceStrings.getString(s));
226 panel.add(FieldLayout.LABEL, addLbl);
227 return addLbl;
228 } // addLabel
229
230 /**
231 * Adds a field to the review panel.
232 * @param s the field value.
233 * @return the label of which the field consists.
234 */
235 private JLabel addField(String s) {
236 JLabel l = new JLabel(s);
237 l.setForeground(Color.black);
238 panel.add(FieldLayout.FIELD, l);
239 return l;
240 } // addField
241
242 public String getDescription() {
243 return ResourceStrings.getString("cvt_wiz_review_desc");
244 } // getDescription
245
246 public Component getComponent() {
247 return stepBox;
248 } // getComponent
249
250 public void setActive(int direction) {
251
252 setFinishEnabled(true);
253
254 /**
255 * If no bean exists for the default data store, then use the
256 * name of the data store as the description.
257 */
258 String description = null;
259 if (defaultDsconf != null) {
260 description = defaultDsconf.getModule().getDescription();
261 } else {
262 description = dhcpdOptions.getResource();
263 }
264
265 oldStoreLabel.setText(description);
266 newStoreLabel.setText(getDsconf().getModule().getDescription());
267
268 String message = null;
269 if (saveTablesStep.isSaveTablesSelected()) {
270 message = ResourceStrings.getString("yes");
271 } else {
272 message = ResourceStrings.getString("no");
273 }
274 saveLabel.setText(message);
275
276 } // setActive
277
278 public boolean setInactive(int direction) {
279 return true;
280 } // setInactive
281
282 } // ReviewStep
283
284 /**
285 * Constructor for the ConvertWizard.
286 * @param owner owner of the wizard.
287 * @param title title of the wizard.
288 */
289 public ConvertWizard(Frame owner, String title) {
290
291 super(owner, title);
292
293 // Go ahead and grab handles to the different servers and
294 // read the server defaults.
295 //
296 try {
297 svcServer = DataManager.get().getDhcpServiceMgr();
298 dhcptabServer = DataManager.get().getDhcptabMgr();
299 netServer = DataManager.get().getDhcpNetMgr();
300 dhcpdOptions = svcServer.readDefaults();
301 } catch (Throwable e) {
302 e.printStackTrace();
303 return;
304 }
305
306 // Create the DSConfList and determine the default. Note that
307 // if the current data store has no management bean, then the
308 // defaultDsconf is null.
309 //
310 dsconfList = new DSConfList();
311 dsconfList.init(svcServer);
312 defaultDsconf =
313 dsconfList.findDsconf(dhcpdOptions.getResource());
314
315 // If no bean exists for the default data store, then use the
316 // name of the data store as the description.
317 //
318 String description = null;
319 if (defaultDsconf != null) {
320 description = defaultDsconf.getModule().getDescription();
321 } else {
322 description = dhcpdOptions.getResource();
323 }
324
325
326 // Build the wizard explanation message.
327 //
328 Object [] args = new Object[1];
329 args[0] = description;
330 MessageFormat form = new MessageFormat(
331 ResourceStrings.getString("cvt_wiz_explain"));
332 String wizExplain = form.format(args);
333
334 // Add the steps for the wizard.
335 //
336 DatastoreStep datastoreStep = new DatastoreStep(wizExplain,
337 ResourceStrings.getString("cvt_wiz_store_explain"));
338 addStep(datastoreStep);
339 addStep(new DatastoreModuleStep());
340 addStep(saveTablesStep = new SaveTablesStep());
341 addStep(new ReviewStep());
342 showFirstStep();
343 }
344
345 public void doFinish() {
346 /*
347 * To convert the data store, we have to do the following items:
348 * 1. Create the new location/path
349 * 2. Convert the dhcptab
350 * 3. Convert the network tables
351 * 4. Modify the DHCP defaults
352 * 5. Delete old tables if necessary
353 */
354
355 getDsconf().setLocation();
356 getDsconf().setConfig();
357 final DhcpDatastore newDhcpDatastore = getDsconf().getDS();
358 final DhcpDatastore oldDhcpDatastore = dhcpdOptions.getDhcpDatastore();
359
360 if (newDhcpDatastore.equals(oldDhcpDatastore)) {
361 JOptionPane.showMessageDialog(ConvertWizard.this,
362 ResourceStrings.getString("cvt_wiz_same_datastore_error"),
363 ResourceStrings.getString("cvt_wiz_error"),
364 JOptionPane.ERROR_MESSAGE);
365 return;
366 }
367
368 // Create the new location if it does not exist.
369 //
370 try {
371 svcServer.makeLocation(newDhcpDatastore);
372 } catch (ExistsException e) {
373 // this is o.k.
374 } catch (Throwable e) {
375 MessageFormat form = new MessageFormat(
376 ResourceStrings.getString("cvt_wiz_location_error"));
377 Object [] args = new Object[1];
378 args[0] = newDhcpDatastore.getLocation();
379 String msg = form.format(args);
380 JOptionPane.showMessageDialog(ConvertWizard.this,
381 msg,
382 ResourceStrings.getString("cvt_wiz_error"),
383 JOptionPane.ERROR_MESSAGE);
384
385 return;
386 }
387
388 // Go get a list of the network tables to convert.
389 //
390 try {
391 networks = netServer.getNetworks(oldDhcpDatastore);
392 if (networks == null) {
393 networks = new Network[0];
394 }
395 } catch (Throwable e) {
396 MessageFormat form = new MessageFormat(
397 ResourceStrings.getString("cvt_wiz_networks_error"));
398 Object [] args = new Object[1];
399 args[0] = e.getMessage();
400 String msg = form.format(args);
401 JOptionPane.showMessageDialog(ConvertWizard.this,
402 msg,
403 ResourceStrings.getString("cvt_wiz_error"),
404 JOptionPane.ERROR_MESSAGE);
405
406 reallyFinish();
407 return;
408 }
409
410 // Add 1 to tables count for dhcptab
411 final int tables = networks.length + 1;
412 // One update per table, plus one per table if deleting
413 int updates =
414 !saveTablesStep.isSaveTablesSelected() ? tables * 2 : tables;
415 // Add: one for shutdown, one for updating dhcpsvc.conf
416 updates += 2;
417 // If daemon will be restarted, then add 1 for start
418 if (dhcpdOptions.isDaemonEnabled()) {
419 ++updates;
420 }
421 final ProgressManager progress = new ProgressManager(this,
422 ResourceStrings.getString("cvt_wiz_progress"),
423 "", 0, updates);
424
425 // Called when doFinish() is really finished
426 // (i.e., the thread completes).
427 //
428 final Runnable finisher = new Runnable() {
429 public void run() {
430 reallyFinish();
431 }
432 };
433
434
435 // Here's the thread which does the conversion.
436 //
437 Thread convertThread = new Thread() {
438 public void run() {
439
440 String message = null;
441 MessageFormat form;
442 MessageFormat errForm;
443 Object [] args = new Object[1];
444 boolean saveTables =
445 saveTablesStep.isSaveTablesSelected();
446
447 // This is final so it can be used in the
448 // errorDisplay Runnable.
449 //
450 final ErrorTable failedTable = new ErrorTable(
451 ResourceStrings.getString("cvt_wiz_table"),
452 String.class);
453
454 // Shutdown the server.
455 //
456 int counter = 0;
457 try {
458 svcServer.shutdown();
459 message = ResourceStrings.getString(
460 "cvt_wiz_server_shutdown");
461 } catch (Throwable e) {
462 message =
463 ResourceStrings.getString("cvt_wiz_shutdown_err");
464 failedTable.addError("", e.getMessage());
465 saveTables = true;
466 } finally {
467 try {
468 progress.update(++counter, message);
469 } catch (InterruptedException e) {
470 SwingUtilities.invokeLater(finisher);
471 return;
472 }
473 }
474
475 // Convert the dhcptab.
476 //
477 try {
478 dhcptabServer.cvtDhcptab(newDhcpDatastore);
479 message = ResourceStrings.getString(
480 "cvt_wiz_progress_dhcptab_cvt");
481 } catch (Throwable e) {
482 message = ResourceStrings.getString(
483 "cvt_wiz_progress_dhcptab_cvt_err");
484 failedTable.addError(ResourceStrings.getString(
485 "cvt_wiz_dhcptab"), e.getMessage());
486 saveTables = true;
487 } finally {
488 try {
489 progress.update(++counter, message);
490 } catch (InterruptedException e) {
491 SwingUtilities.invokeLater(finisher);
492 return;
493 }
494 }
495
496 // Convert the network tables.
497 //
498 form = new MessageFormat(ResourceStrings.getString(
499 "cvt_wiz_progress_network_cvt"));
500 errForm = new MessageFormat(ResourceStrings.getString(
501 "cvt_wiz_progress_network_cvt_err"));
502
503 for (int i = 0; i < networks.length; ++i) {
504 String netString = networks[i].toString();
505 args[0] = netString;
506 try {
507 netServer.cvtNetwork(netString, newDhcpDatastore);
508 message = form.format(args);
509 } catch (Throwable e) {
510 message = errForm.format(args);
511 failedTable.addError(netString, e.getMessage());
512 saveTables = true;
513 } finally {
514 try {
515 progress.update(++counter, message);
516 } catch (InterruptedException e) {
517 SwingUtilities.invokeLater(finisher);
518 return;
519 }
520 }
521 }
522
523 // Update the DHCP defaults file with the new values.
524 //
525 dhcpdOptions.setDhcpDatastore(newDhcpDatastore);
526 try {
527 svcServer.writeDefaults(dhcpdOptions);
528 message = ResourceStrings.getString(
529 "cvt_wiz_progress_defaults");
530 } catch (Throwable e) {
531 message = ResourceStrings.getString(
532 "cvt_wiz_progress_defaults_err");
533 failedTable.addError(ResourceStrings.getString(
534 "cvt_wiz_defaults"), e.getMessage());
535 saveTables = true;
536 } finally {
537 try {
538 progress.update(++counter, message);
539 } catch (InterruptedException e) {
540 SwingUtilities.invokeLater(finisher);
541 return;
542 }
543 }
544
545 if (!saveTables) {
546 // Delete the network tables
547 //
548 form = new MessageFormat(ResourceStrings.getString(
549 "cvt_wiz_progress_network_del"));
550 errForm = new MessageFormat(ResourceStrings.getString(
551 "cvt_wiz_progress_network_del_err"));
552
553 for (int i = 0; i < networks.length; ++i) {
554 String netString = networks[i].toString();
555 args[0] = netString;
556 try {
557 netServer.deleteNetwork(netString, false,
558 oldDhcpDatastore);
559 message = form.format(args);
560 } catch (Throwable e) {
561 message = errForm.format(args);
562 failedTable.addError(netString, e.getMessage());
563 } finally {
564 try {
565 progress.update(++counter, message);
566 } catch (InterruptedException e) {
567 SwingUtilities.invokeLater(finisher);
568 return;
569 }
570 }
571 }
572
573 // Delete the dhcptab
574 //
575 try {
576 dhcptabServer.deleteDhcptab(oldDhcpDatastore);
577 message = ResourceStrings.getString(
578 "cvt_wiz_progress_dhcptab_del");
579 } catch (Throwable e) {
580 message = ResourceStrings.getString(
581 "cvt_wiz_progress_dhcptab_del_err");
582 failedTable.addError(ResourceStrings.getString(
583 "cvt_wiz_dhcptab"), e.getMessage());
584 } finally {
585 try {
586 progress.update(++counter, message);
587 } catch (InterruptedException e) {
588 SwingUtilities.invokeLater(finisher);
589 return;
590 }
591 }
592 } else if (!saveTablesStep.isSaveTablesSelected()) {
593 try {
594 counter += tables;
595 progress.update(counter, "");
596 } catch (InterruptedException e) {
597 SwingUtilities.invokeLater(finisher);
598 return;
599 }
600 }
601
602 // Start the server.
603 //
604 if (dhcpdOptions.isDaemonEnabled()) {
605 try {
606 svcServer.startup();
607 message = ResourceStrings.getString(
608 "cvt_wiz_server_started");
609 } catch (Throwable e) {
610 message =
611 ResourceStrings.getString("cvt_wiz_start_err");
612 failedTable.addError("", e.getMessage());
613 } finally {
614 try {
615 progress.update(++counter, message);
616 } catch (InterruptedException e) {
617 SwingUtilities.invokeLater(finisher);
618 return;
619 }
620 }
621 }
622
623 // If any errors occurred, display them all at once.
624 //
625 if (!failedTable.isEmpty()) {
626 Runnable errorDisplay = new Runnable() {
627 public void run() {
628 Object [] objs = new Object[2];
629 objs[0] =
630 ResourceStrings.getString("cvt_wiz_errors");
631 JScrollPane scrollPane =
632 new JScrollPane(failedTable);
633
634 // Resize the table to something kind of small
635 //
636 Dimension d =
637 failedTable.
638 getPreferredScrollableViewportSize();
639 d.height = 80;
640 failedTable.setPreferredScrollableViewportSize(d);
641 objs[1] = scrollPane;
642 JOptionPane.showMessageDialog(ConvertWizard.this,
643 objs,
644 ResourceStrings.getString("server_error_title"),
645 JOptionPane.ERROR_MESSAGE);
646 }
647 };
648 try {
649 SwingUtilities.invokeAndWait(errorDisplay);
650 } catch (Throwable e) {
651 e.printStackTrace();
652 }
653 }
654 SwingUtilities.invokeLater(finisher);
655 }
656 };
657 convertThread.start();
658 }
659
660 public void doHelp() {
661 DhcpmgrApplet.showHelp("convert_wizard");
662 }
663
664 /**
665 * Called by the worker thread upon completion to exec the Wizard
666 * doFinish().
667 */
668 protected void reallyFinish() {
669 super.doFinish();
670 } // reallyFinish
671
672 } // ConvertWizard