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 }