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