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 2004 Sun Microsystems, Inc. All rights reserved. 26 * Use is subject to license terms. 27 */ 28 package com.sun.dhcpmgr.client; 29 30 import java.awt.*; 31 import java.awt.event.*; 32 import java.util.*; 33 import java.net.*; 34 import java.rmi.RemoteException; 35 import java.rmi.NotBoundException; 36 import javax.swing.*; 37 import java.text.MessageFormat; 38 import java.applet.AppletContext; 39 40 import com.sun.dhcpmgr.ui.*; 41 import com.sun.dhcpmgr.data.*; 42 import com.sun.dhcpmgr.server.DhcpMgr; 43 import com.sun.dhcpmgr.server.DhcpServiceMgr; 44 import com.sun.dhcpmgr.bridge.BridgeException; 45 import com.sun.dhcpmgr.bridge.NotRunningException; 46 47 /** 48 * Main class for DHCP Manager. It is theoretically possible to run this 49 * application as a command managing the local system, a command managing a 50 * remote system using RMI, or as an applet managing the system from which it 51 * was downloaded. We presently only support the first option, but there is 52 * vestigial code here from when the other options were supported as they may 53 * be again. That's why we extend JApplet. 54 */ 55 public class DhcpmgrApplet extends JApplet { 56 private static MainFrame frame = null; 57 private JButton button; 58 public static boolean modeIsRelay; 59 private static HelpIds helpIds = null; 60 private static URL docBase = null; 61 private static AppletContext appletContext = null; 62 private AddressView addressView; 63 private RestartAction restartAction; 64 private StopAction stopAction; 65 private StartAction startAction; 66 private DisableAction disableAction; 67 private EnableAction enableAction; 68 69 // Handler for Help->Overview menu item 70 class OverviewAction extends MnemonicAction { 71 public OverviewAction() { 72 super(ResourceStrings.getString("overview_item")); 73 } 74 75 public void actionPerformed(ActionEvent e) { 76 showHelp("overview"); 77 } 78 } 79 80 // Handler for Help->How To menu item 81 class HowToAction extends MnemonicAction { 82 public HowToAction() { 83 super(ResourceStrings.getString("howto_item")); 84 } 85 86 public void actionPerformed(ActionEvent e) { 87 showHelp("howto"); 88 } 89 } 90 91 // Handler for Help->Index menu item 92 class IndexAction extends MnemonicAction { 93 public IndexAction() { 94 super(ResourceStrings.getString("index_item")); 95 } 96 97 public void actionPerformed(ActionEvent e) { 98 showHelp("index"); 99 } 100 } 101 102 // Handler for Help->On Service menu item 103 class ServiceAction extends MnemonicAction { 104 public ServiceAction() { 105 super(ResourceStrings.getString("on_service_item")); 106 } 107 108 public void actionPerformed(ActionEvent e) { 109 showHelp("service_reference"); 110 } 111 } 112 113 // Handler for the Service->Restart menu item 114 class RestartAction extends MnemonicAction { 115 public RestartAction() { 116 super(ResourceStrings.getString("restart_item")); 117 } 118 119 public void actionPerformed(ActionEvent e) { 120 try { 121 DataManager.get().getDhcpServiceMgr().reload(); 122 frame.setStatusText( 123 ResourceStrings.getString("service_restarted")); 124 } catch (NotRunningException ex) { 125 // Server not running, ignore the error and just start it 126 startAction.actionPerformed(e); 127 } catch (Throwable t) { 128 Object [] args = new Object[1]; 129 MessageFormat form = new MessageFormat( 130 ResourceStrings.getString("restart_server_error")); 131 args[0] = t.getMessage(); 132 JOptionPane.showMessageDialog(frame, form.format(args), 133 ResourceStrings.getString("server_error_title"), 134 JOptionPane.ERROR_MESSAGE); 135 } 136 } 137 } 138 139 // Handler for the Service->Stop menu item 140 class StopAction extends MnemonicAction { 141 public StopAction() { 142 super(ResourceStrings.getString("stop_item")); 143 } 144 145 public void actionPerformed(ActionEvent e) { 146 try { 147 DataManager.get().getDhcpServiceMgr().shutdown(); 148 frame.setStatusText( 149 ResourceStrings.getString("service_stopped")); 150 startAction.setEnabled(true); 151 restartAction.setEnabled(false); 152 setEnabled(false); 153 } catch (Throwable t) { 154 Object [] args = new Object[1]; 155 MessageFormat form = new MessageFormat( 156 ResourceStrings.getString("shutdown_server_error")); 157 args[0] = t.getMessage(); 158 JOptionPane.showMessageDialog(frame, form.format(args), 159 ResourceStrings.getString("server_error_title"), 160 JOptionPane.ERROR_MESSAGE); 161 } 162 } 163 } 164 165 // Handler for the Service->Restart menu item 166 class StartAction extends MnemonicAction { 167 public StartAction() { 168 super(ResourceStrings.getString("start_item")); 169 } 170 171 public void actionPerformed(ActionEvent e) { 172 try { 173 DataManager.get().getDhcpServiceMgr().startup(); 174 frame.setStatusText( 175 ResourceStrings.getString("service_started")); 176 stopAction.setEnabled(true); 177 restartAction.setEnabled(true); 178 setEnabled(false); 179 } catch (Throwable t) { 180 Object [] args = new Object[1]; 181 MessageFormat form = new MessageFormat( 182 ResourceStrings.getString("startup_server_error")); 183 args[0] = t.getMessage(); 184 JOptionPane.showMessageDialog(frame, form.format(args), 185 ResourceStrings.getString("server_error_title"), 186 JOptionPane.ERROR_MESSAGE); 187 } 188 } 189 } 190 191 // handler for the Service->Disable service menu item 192 class DisableAction extends MnemonicAction { 193 public DisableAction() { 194 super(ResourceStrings.getString("disable_item")); 195 } 196 197 public void actionPerformed(ActionEvent e) { 198 DisableServiceDialog d = new DisableServiceDialog(frame, true); 199 d.addActionListener(new ActionListener() { 200 public void actionPerformed(ActionEvent e) { 201 // Update menu item state once we've disabled it 202 enableAction.setEnabled(true); 203 disableAction.setEnabled(false); 204 stopAction.setEnabled(false); 205 startAction.setEnabled(false); 206 restartAction.setEnabled(false); 207 } 208 }); 209 d.pack(); 210 d.setVisible(true); 211 } 212 } 213 214 // handler for the Service->Enable service menu item 215 class EnableAction extends MnemonicAction { 216 public EnableAction() { 217 super(ResourceStrings.getString("enable_item")); 218 } 219 220 public void actionPerformed(ActionEvent e) { 221 DisableServiceDialog d = new DisableServiceDialog(frame, false); 222 d.addActionListener(new ActionListener() { 223 public void actionPerformed(ActionEvent e) { 224 // Update menu item state once we've enabled it 225 disableAction.setEnabled(true); 226 enableAction.setEnabled(false); 227 stopAction.setEnabled(true); 228 startAction.setEnabled(false); 229 restartAction.setEnabled(true); 230 } 231 }); 232 d.pack(); 233 d.setVisible(true); 234 } 235 } 236 237 // handler for the Service->Modify service menu item 238 class ModifyServiceAction extends MnemonicAction { 239 public ModifyServiceAction() { 240 super(ResourceStrings.getString("modify_service_item")); 241 } 242 243 public void actionPerformed(ActionEvent e) { 244 try { 245 DhcpdOptions opts = 246 DataManager.get().getDhcpServiceMgr().readDefaults(); 247 ServerOptionsDialog d = new ServerOptionsDialog(frame, opts); 248 d.pack(); 249 d.setVisible(true); 250 } catch (BridgeException ex) { 251 // Error reading options 252 MessageFormat form = new MessageFormat( 253 ResourceStrings.getString("err_reading_options")); 254 Object [] args = new Object[] { ex.getMessage() }; 255 JOptionPane.showMessageDialog(frame, form.format(args), 256 ResourceStrings.getString("server_error_title"), 257 JOptionPane.ERROR_MESSAGE); 258 } 259 } 260 } 261 262 // handler for the Service->Convert service menu item 263 class ConvertAction extends MnemonicAction { 264 public ConvertAction() { 265 super(ResourceStrings.getString("cvt_service_item")); 266 267 } 268 269 public void actionPerformed(ActionEvent e) { 270 ConvertWizard wiz = new ConvertWizard(frame, 271 ResourceStrings.getString("cvt_wiz_title")); 272 wiz.addActionListener(new ActionListener() { 273 public void actionPerformed(ActionEvent e) { 274 if (e.getActionCommand().equals("finished")) { 275 frame.refreshAllViews(); 276 showFrame(); 277 } 278 } 279 }); 280 wiz.pack(); 281 wiz.setModal(true); 282 wiz.setVisible(true); 283 } 284 285 public void setEnabled(boolean b) { 286 if (!modeIsRelay) { 287 super.setEnabled(b); 288 } else { 289 super.setEnabled(false); 290 } 291 } 292 } 293 294 // handler for the Service->Unconfigure service menu item 295 class UnconfigureServiceAction extends MnemonicAction { 296 public UnconfigureServiceAction() { 297 super(ResourceStrings.getString("unconfigure_service_item")); 298 } 299 300 public void actionPerformed(ActionEvent e) { 301 UnconfigureDialog d = new UnconfigureDialog(frame); 302 d.addActionListener(new ActionListener() { 303 public void actionPerformed(ActionEvent e) { 304 if (e.getActionCommand().equals(DialogActions.OK)) { 305 /* 306 * User unconfigured the service; there's nothing 307 * else to do so just get rid of the frame which 308 * will as a side effect shut us down. 309 */ 310 frame.setVisible(false); 311 frame.dispose(); 312 frame = null; 313 } 314 } 315 }); 316 d.pack(); 317 d.setVisible(true); 318 } 319 } 320 321 // Action for Service->Export data 322 class ExportAction extends MnemonicAction { 323 public ExportAction() { 324 super(ResourceStrings.getString("export_item")); 325 } 326 public void actionPerformed(ActionEvent e) { 327 ExportWizard wiz = new ExportWizard(frame); 328 wiz.addActionListener(new ActionListener() { 329 public void actionPerformed(ActionEvent e) { 330 if (e.getActionCommand().equals("finished")) { 331 frame.refreshAllViews(); 332 showFrame(); 333 } 334 } 335 }); 336 wiz.pack(); 337 wiz.setVisible(true); 338 } 339 } 340 341 // Action for Service->Import data 342 class ImportAction extends MnemonicAction { 343 public ImportAction() { 344 super(ResourceStrings.getString("import_item")); 345 } 346 347 public void actionPerformed(ActionEvent e) { 348 ImportWizard wiz = new ImportWizard(frame); 349 wiz.addActionListener(new ActionListener() { 350 public void actionPerformed(ActionEvent e) { 351 if (e.getActionCommand().equals("finished")) { 352 frame.refreshAllViews(); 353 showFrame(); 354 } 355 } 356 }); 357 wiz.pack(); 358 wiz.setVisible(true); 359 } 360 } 361 362 /* 363 * This class provides a transition dialog which allows the user 364 * to initiate the address wizard immediately upon startup. It's 365 * done this way so that the startMeUp() method can use invokeLater() 366 * to cause it to be displayed after the config wizard exit event 367 * has been processed rather than during that event's processing; 368 * otherwise the wizard doesn't disappear until after the user presses 369 * Yes or No in this dialog. 370 */ 371 class WizardTransition implements Runnable { 372 public void run() { 373 // Now transition to configuring addresses 374 int status = JOptionPane.showConfirmDialog(frame, 375 ResourceStrings.getString("start_address_wizard"), 376 ResourceStrings.getString("start_address_wizard_title"), 377 JOptionPane.YES_NO_OPTION); 378 if (status == JOptionPane.YES_OPTION) { 379 addressView.startAddressWizard(); 380 } 381 } 382 } 383 384 /* 385 * This class provides a transition dialog which allows the user 386 * to initiate the conversion wizard immediately upon startup if a 387 * version mismatch exists (a data store upgrade is necessary). 388 */ 389 class ConversionTransition implements Runnable { 390 public void run() { 391 try { 392 DhcpServiceMgr svcMgr = DataManager.get().getDhcpServiceMgr(); 393 while (!svcMgr.isVersionCurrent()) { 394 int status = JOptionPane.showConfirmDialog(frame, 395 ResourceStrings.getString("start_cvt_wizard"), 396 ResourceStrings.getString("start_cvt_wizard_title"), 397 JOptionPane.YES_NO_OPTION); 398 if (status == JOptionPane.YES_OPTION) { 399 ConvertAction converter = new ConvertAction(); 400 ActionEvent e = new ActionEvent(this, 401 ActionEvent.ACTION_PERFORMED, ""); 402 converter.actionPerformed(e); 403 } else { 404 frame = null; 405 DataManager.get().reset(); 406 requestExit(); 407 } 408 } 409 } catch (Throwable e) { 410 System.err.println( 411 ResourceStrings.getString("err_initializing_program")); 412 System.err.println(e.getMessage()); 413 requestExit(); 414 } 415 } 416 } 417 418 // Create the frame within which the UI will live 419 private void createFrame() { 420 if (frame == null) { 421 422 frame = new MainFrame(ResourceStrings.getString("dhcp_manager")); 423 424 // Create the views for this tool 425 if (modeIsRelay) { 426 frame.addView(new RelayView(), true); 427 } else { 428 addressView = new AddressView(); 429 frame.addView(addressView, true); 430 frame.addView(new MacroView(), false); 431 frame.addView(new OptionView(), false); 432 } 433 434 // Set up the services menu 435 frame.addMenuAction(MainFrame.ACTIONS_MENU, 436 (restartAction = new RestartAction())); 437 frame.addMenuAction(MainFrame.ACTIONS_MENU, 438 (stopAction = new StopAction())); 439 frame.addMenuAction(MainFrame.ACTIONS_MENU, 440 (startAction = new StartAction())); 441 frame.addMenuAction(MainFrame.ACTIONS_MENU, 442 (disableAction = new DisableAction())); 443 frame.addMenuAction(MainFrame.ACTIONS_MENU, 444 (enableAction = new EnableAction())); 445 frame.addMenuAction(MainFrame.ACTIONS_MENU, 446 new ModifyServiceAction()); 447 if (!modeIsRelay) { 448 frame.addMenuAction(MainFrame.ACTIONS_MENU, 449 new ExportAction()); 450 frame.addMenuAction(MainFrame.ACTIONS_MENU, 451 new ImportAction()); 452 frame.addMenuAction(MainFrame.ACTIONS_MENU, 453 new ConvertAction()); 454 } 455 frame.addMenuAction(MainFrame.ACTIONS_MENU, 456 new UnconfigureServiceAction()); 457 458 // Set up the Help menu 459 frame.addMenuAction(MainFrame.HELP_MENU, new OverviewAction()); 460 frame.addMenuAction(MainFrame.HELP_MENU, new HowToAction()); 461 frame.addMenuAction(MainFrame.HELP_MENU, new IndexAction()); 462 frame.addMenuAction(MainFrame.HELP_MENU, new ServiceAction()); 463 464 // In relay mode, let it size itself (quite small) 465 if (modeIsRelay) { 466 frame.pack(); 467 } else { 468 /* 469 * Normal mode set it to a reasonable size. This ought to be 470 * a user preference, but until we run as something other than 471 * root it's not really a useful idea. 472 */ 473 frame.setSize(800, 600); 474 } 475 476 // Listen for closing events 477 frame.addWindowListener(new WindowAdapter() { 478 public void windowClosing(WindowEvent e) { 479 /* 480 * This is here to work around the Close selection frame 481 * menu on Solaris not causing the closed function to be 482 * called 483 */ 484 windowClosed(e); 485 } 486 public void windowClosed(WindowEvent e) { 487 // Dispose of all data and exit when window goes away. 488 frame = null; 489 DataManager.get().reset(); 490 requestExit(); 491 } 492 }); 493 } 494 } 495 496 // Show the frame 497 private void showFrame() { 498 if (frame == null) { 499 createFrame(); 500 } 501 frame.initialize(); 502 if (modeIsRelay) { 503 // Disable edit & view menus in the relay case 504 frame.setMenuEnabled(MainFrame.EDIT_MENU, false); 505 frame.setMenuEnabled(MainFrame.VIEW_MENU, false); 506 } 507 try { 508 // Set status of service menu options based on server state 509 DhcpdOptions opts = 510 DataManager.get().getDhcpServiceMgr().readDefaults(); 511 boolean enabled = opts.isDaemonEnabled(); 512 enableAction.setEnabled(!enabled); 513 disableAction.setEnabled(enabled); 514 boolean running = 515 DataManager.get().getDhcpServiceMgr().isServerRunning(); 516 restartAction.setEnabled(running && enabled); 517 stopAction.setEnabled(running); 518 startAction.setEnabled(!running && enabled); 519 } catch (Throwable e) { 520 // Enable all the menu items, as something went wrong 521 restartAction.setEnabled(true); 522 stopAction.setEnabled(true); 523 startAction.setEnabled(true); 524 enableAction.setEnabled(true); 525 disableAction.setEnabled(true); 526 } 527 frame.setVisible(true); 528 } 529 530 /* 531 * main startup code; checks whether server is already configured, and if 532 * not runs through the config wizard sequence in order to get the server 533 * configured. 534 */ 535 private void startMeUp() { 536 try { 537 if (DataManager.get().getServer() == null) { 538 DataManager.get().setServer(getCodeBase().getHost()); 539 } 540 541 // See if server is already configured, and start up 542 DhcpServiceMgr svcMgr = DataManager.get().getDhcpServiceMgr(); 543 DhcpdOptions opts = svcMgr.readDefaults(); 544 modeIsRelay = opts.isRelay(); 545 // If server mode, ensure RESOURCE and PATH were set 546 if (!modeIsRelay) { 547 if ((opts.getResource() == null) || (opts.getPath() == null)) { 548 System.err.println( 549 ResourceStrings.getString("err_initializing_options")); 550 requestExit(); 551 } 552 } 553 554 showFrame(); 555 556 // Check to make sure that the data store version is up to date. 557 // If not, inform the user and present them with the conversion 558 // wizard so that they can upgrade. 559 if (!modeIsRelay && !svcMgr.isVersionCurrent()) { 560 SwingUtilities.invokeLater(new ConversionTransition()); 561 } 562 563 } catch (BridgeException e) { 564 // Let user select which type of service to configure 565 int choice = ConfigureChoiceDialog.showDialog(frame); 566 if (choice == ConfigureChoiceDialog.DHCP) { 567 // DHCP; run the wizard 568 ConfigWizard wiz = new ConfigWizard(frame, 569 ResourceStrings.getString("cfg_wiz_title"), true); 570 wiz.addActionListener(new ActionListener() { 571 public void actionPerformed(ActionEvent e) { 572 if (e.getActionCommand().equals("finished")) { 573 // Service config completed, start up 574 modeIsRelay = false; 575 showFrame(); 576 // Now transition to configuring addresses 577 SwingUtilities.invokeLater(new WizardTransition()); 578 } else { 579 // User cancelled the wizard, exit 580 requestExit(); 581 } 582 } 583 }); 584 wiz.pack(); 585 wiz.setVisible(true); 586 } else if (choice == ConfigureChoiceDialog.BOOTP) { 587 // Wants to configure a relay, show the dialog for that 588 ConfigureRelayDialog d = new ConfigureRelayDialog(frame); 589 d.addActionListener(new ActionListener() { 590 public void actionPerformed(ActionEvent e) { 591 if (e.getActionCommand().equals(DialogActions.OK)) { 592 // Relay configuration completed, start up 593 modeIsRelay = true; 594 showFrame(); 595 } else { 596 // User cancelled, exit 597 requestExit(); 598 } 599 } 600 }); 601 d.pack(); 602 d.setVisible(true); 603 } else { 604 // User cancelled; exit 605 requestExit(); 606 } 607 } catch (Throwable e) { 608 // Couldn't really get started, dump the stack and exit 609 System.err.println( 610 ResourceStrings.getString("err_initializing_program")); 611 System.err.println(e.getMessage()); 612 e.printStackTrace(); 613 requestExit(); 614 } 615 } 616 617 // Show a help file referenced by tag 618 public static void showHelp(String helpId) { 619 // If help tag mapping table not loaded yet, then load it 620 if (helpIds == null) { 621 try { 622 helpIds = new HelpIds("com.sun.dhcpmgr.client.HelpBundle"); 623 } catch (Throwable e) { 624 // Error initializing help system 625 JOptionPane.showMessageDialog(frame, 626 ResourceStrings.getString("err_initializing_help"), 627 ResourceStrings.getString("server_error_title"), 628 JOptionPane.ERROR_MESSAGE); 629 return; 630 } 631 } 632 // Ask browser to display 633 try { 634 Runtime.getRuntime().exec( 635 "/usr/sfw/bin/mozilla file:" 636 + helpIds.getFilePath(helpId)); 637 } catch (java.io.IOException e) { 638 JOptionPane.showMessageDialog(frame, 639 ResourceStrings.getString("err_starting_help"), 640 ResourceStrings.getString("server_error_title"), 641 JOptionPane.ERROR_MESSAGE); 642 } 643 } 644 645 // Exit the application 646 private void requestExit() { 647 System.exit(0); 648 } 649 650 // Main function when we're run as an application 651 public static void main(String [] args) { 652 653 // Ensure that we're running as root; exit if not 654 if (!System.getProperty("user.name").equals("root")) { 655 System.err.println(ResourceStrings.getString("err_must_be_root")); 656 System.exit(0); 657 } 658 659 DhcpmgrApplet applet = new DhcpmgrApplet(); 660 applet.startMeUp(); 661 } 662 }