001: /*****************************************************************************
002: * Java Plug-in Framework (JPF)
003: * Copyright (C) 2004-2007 Dmitry Olshansky
004: *
005: * This library is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU Lesser General Public
007: * License as published by the Free Software Foundation; either
008: * version 2.1 of the License, or (at your option) any later version.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * Lesser General Public License for more details.
014: *
015: * You should have received a copy of the GNU Lesser General Public
016: * License along with this library; if not, write to the Free Software
017: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
018: *****************************************************************************/package org.java.plugin.boot;
019:
020: import java.io.File;
021: import java.io.FileInputStream;
022: import java.io.FileNotFoundException;
023: import java.io.FileOutputStream;
024: import java.io.IOException;
025: import java.io.InputStream;
026: import java.io.OutputStreamWriter;
027: import java.io.Writer;
028: import java.net.InetAddress;
029: import java.net.MalformedURLException;
030: import java.net.URL;
031: import java.util.Locale;
032:
033: import org.apache.commons.logging.LogFactory;
034: import org.java.plugin.PluginManager;
035: import org.java.plugin.util.ExtendedProperties;
036: import org.java.plugin.util.IoUtil;
037: import org.java.plugin.util.ResourceManager;
038:
039: /**
040: * Main class to get JPF based application running in different modes.
041: * Application mode may be specified as <code>jpf.boot.mode</code> configuration
042: * parameter or System property (via <code>-Djpf.boot.mode=</code> command line
043: * argument). Supported values are:
044: * <dl>
045: * <dt>start</dt>
046: * <dd>Runs application in "background" ("service") mode.</dd>
047: * <dt>stop</dt>
048: * <dd>Stops application, running in "background" mode.</dd>
049: * <dt>restart</dt>
050: * <dd>Restarts application, running in "background" mode. If it is not
051: * started, the action is the same as just starting application.</dd>
052: * <dt>shell</dt>
053: * <dd>Runs application in "shell" (or "interactive") mode. It is possible to
054: * control "service" style application from command line. Note, that
055: * already running application will be stopped first.</dd>
056: * <dt>load</dt>
057: * <dd>Only loads application but not starts it as in other modes. This mode
058: * is useful when doing application unit testing or when you only need to
059: * get initialized and ready to be started JPF environment.</dd>
060: * </dl>
061: * The "shell" mode is default. Application will be started in this mode if no
062: * <code>jpf.boot.mode</code> configuration parameter can be found.
063: * <p>
064: * Application configuration is expected to be in Java properties format file.
065: * File look-up procedure is the following:
066: * </p>
067: * <ul>
068: * <li>Check <code>jpf.boot.config</code> System property, if present, load
069: * configuration from that location</li>
070: * <li>Look for <code>boot.properties</code> file in the current folder.</li>
071: * <li>Look for <code>boot.properties</code> resource in classpath (using
072: * <code>Boot.class.getClassLoader().getResource("boot.properties")</code>
073: * and <code>Boot.class.getResource("boot.properties")</code> methods).</li>
074: * </ul>
075: * <p>
076: * If configuration could not be found, a warning will be printed to console.
077: * It is generally not an error to not use configuration file, you may provide
078: * JPF configuration parameters as System properties. They are always used as
079: * defaults for configuration properties.
080: * </p>
081: * <p>
082: * Note that configuration properties will be loaded using
083: * {@link org.java.plugin.util.ExtendedProperties specially extended}
084: * version of {@link java.util.Properties} class, which supports parameters
085: * substitution. If there is no <code>applicationRoot</code> property available
086: * in the given configuration, the current folder will be published as default
087: * value.
088: * </p>
089: * <p>
090: * Standard configuration parameters are (all are optional when application is
091: * running in "shell" mode):
092: * <dl>
093: * <dt>jpf.boot.mode</dt>
094: * <dd>Application boot mode. Always available as System property also.
095: * Default value is <code>shell</code>.</dd>
096: * <dt>org.java.plugin.boot.appInitializer</dt>
097: * <dd>Application initializer class, for details see
098: * {@link org.java.plugin.boot.ApplicationInitializer}. Default is
099: * {@link org.java.plugin.boot.DefaultApplicationInitializer}.</dd>
100: * <dt>org.java.plugin.boot.errorHandler</dt>
101: * <dd>Error handler class, for details see
102: * {@link org.java.plugin.boot.BootErrorHandler}. Default is
103: * {@link org.java.plugin.boot.BootErrorHandlerConsole} for "service" style
104: * applications and {@link org.java.plugin.boot.BootErrorHandlerGui} for
105: * "interactive" applications.</dd>
106: * <dt>org.java.plugin.boot.controlHost</dt>
107: * <dd>Host to be used by background control service, no default values.</dd>
108: * <dt>org.java.plugin.boot.controlPort</dt>
109: * <dd>Port number to be used by background control service, no default
110: * values.</dd>
111: * <dt>org.java.plugin.boot.splashHandler</dt>
112: * <dd>Splash screen handler class, for details see
113: * {@link org.java.plugin.boot.SplashHandler}. Default is simple splash
114: * handler that can only display an image.</dd>
115: * <dt>org.java.plugin.boot.splashImage</dt>
116: * <dd>Path to an image file to be shown as splash screen. This may be any
117: * valid URL. If no file and no handler given, the splash screen will not
118: * be shown.</dd>
119: * <dt>org.java.plugin.boot.splashLeaveVisible</dt>
120: * <dd>If set to <code>true</code>, the Boot class will not hide splash screen
121: * at the end of boot procedure but delegate this function to application
122: * code. Default value is <code>false</code>.</dd>
123: * <dt>org.java.plugin.boot.splashDisposeOnHide</dt>
124: * <dd>If set to <code>false</code>, the Boot class will not dispose splash
125: * screen handler when hiding it. This allows you to reuse handler and show
126: * splash screen back after it was hidden. Default value is
127: * <code>true</code>.</dd>
128: * </dl>
129: *
130: * @version $Id$
131: */
132: public final class Boot {
133: /**
134: * Name of the file, where to put boot error details.
135: */
136: public static final String BOOT_ERROR_FILE_NAME = "jpf-boot-error.txt"; //$NON-NLS-1$
137:
138: /**
139: * Boot configuration file location System property name.
140: */
141: public static final String PROP_BOOT_CONFIG = "jpf.boot.config"; //$NON-NLS-1$
142:
143: /**
144: * Boot mode System property name.
145: */
146: public static final String PROP_BOOT_MODE = "jpf.boot.mode"; //$NON-NLS-1$
147:
148: /**
149: * "shell" mode boot command value.
150: */
151: public static final String BOOT_MODE_SHELL = "shell"; //$NON-NLS-1$
152:
153: /**
154: * "start" mode boot command value.
155: */
156: public static final String BOOT_MODE_START = "start"; //$NON-NLS-1$
157:
158: /**
159: * "stop" mode boot command value.
160: */
161: public static final String BOOT_MODE_STOP = "stop"; //$NON-NLS-1$
162:
163: /**
164: * "restart" mode boot command value.
165: */
166: public static final String BOOT_MODE_RESTART = "restart"; //$NON-NLS-1$
167:
168: /**
169: * "load" mode boot command value.
170: */
171: public static final String BOOT_MODE_LOAD = "load"; //$NON-NLS-1$
172:
173: // This is for ResourceManager to look up resources.
174: static final String PACKAGE_NAME = "org.java.plugin.boot"; //$NON-NLS-1$
175:
176: // Application bootstrap configuration parameter names goes here
177: private static final String PARAM_CONTROL_HOST = "org.java.plugin.boot.controlHost"; //$NON-NLS-1$
178: private static final String PARAM_CONTROL_PORT = "org.java.plugin.boot.controlPort"; //$NON-NLS-1$
179: private static final String PARAM_ERROR_HANDLER = "org.java.plugin.boot.errorHandler"; //$NON-NLS-1$
180: private static final String PARAM_APP_INITIALIZER = "org.java.plugin.boot.appInitializer"; //$NON-NLS-1$
181: private static final String PARAM_SPLASH_HANDLER = "org.java.plugin.boot.splashHandler"; //$NON-NLS-1$
182: private static final String PARAM_SPLASH_IMAGE = "org.java.plugin.boot.splashImage"; //$NON-NLS-1$
183: private static final String PARAM_SPLASH_LEAVE_VISIBLE = "org.java.plugin.boot.splashLeaveVisible"; //$NON-NLS-1$
184: private static final String PARAM_SPLASH_DISPOSE_ON_HIDE = "org.java.plugin.boot.splashDisposeOnHide"; //$NON-NLS-1$
185: private static final String PARAM_SPLASH_CONFIG_PREFIX = "org.java.plugin.boot.splash."; //$NON-NLS-1$
186:
187: static SplashHandler splashHandler = null;
188:
189: /**
190: * Call this method to start/stop application.
191: * @param args command line arguments, not interpreted by this method but
192: * passed to
193: * {@link ApplicationPlugin#initApplication(ExtendedProperties, String[])}
194: * method
195: */
196: public static void main(final String[] args) {
197: clearBootLog();
198: // Load start-up configuration
199: ExtendedProperties props = new ExtendedProperties(System
200: .getProperties());
201: try {
202: InputStream strm = lookupConfig();
203: try {
204: props.load(strm);
205: } finally {
206: strm.close();
207: }
208: } catch (IOException ioe) {
209: ioe.printStackTrace();
210: }
211: String mode = props.getProperty(PROP_BOOT_MODE);
212: if (mode != null) {
213: mode = mode.trim().toLowerCase(Locale.ENGLISH);
214: } else {
215: // set SHELL mode by default
216: mode = BOOT_MODE_SHELL;
217: }
218: props.setProperty(PROP_BOOT_MODE, mode);
219: // Make sure that boot mode is always available as System property:
220: System.setProperty(PROP_BOOT_MODE, mode);
221: boolean useControlService = props
222: .containsKey(PARAM_CONTROL_HOST)
223: && props.containsKey(PARAM_CONTROL_PORT);
224: BootErrorHandler errorHandler = getErrorHandlerInstance(props
225: .getProperty(PARAM_ERROR_HANDLER), useControlService);
226: try {
227: if (props.getProperty("applicationRoot") == null) { //$NON-NLS-1$
228: // Publish current folder as configuration parameter
229: // to get it available as ${applicationRoot} variable
230: // in extended properties syntax.
231: String applicationRoot = new File(".").getCanonicalPath(); //$NON-NLS-1$
232: props.put("applicationRoot", applicationRoot); //$NON-NLS-1$
233: }
234: boot(props, useControlService, mode, errorHandler, args);
235: } catch (Throwable t) {
236: if (splashHandler != null) {
237: splashHandler.setVisible(false);
238: splashHandler = null;
239: }
240: bootLog(t);
241: errorHandler.handleFatalError(ResourceManager.getMessage(
242: Boot.PACKAGE_NAME, "bootFailed"), t); //$NON-NLS-1$
243: System.exit(1);
244: }
245: }
246:
247: /**
248: * Boots application according to given configuration data.
249: * @param config boot configuration data
250: * @param useControlService if <code>true</code>, the control service will
251: * started to allow handling application instance
252: * from another process
253: * @param mode application run mode
254: * @param errorHandler boot errors handler instance
255: * @param args command line arguments, not interpreted by this method but
256: * passed to
257: * {@link ApplicationPlugin#initApplication(ExtendedProperties, String[])}
258: * method
259: * @return initialized application instance or <code>null</code>
260: * @throws Exception if any un-handled error has occurred
261: */
262: public static Application boot(final ExtendedProperties config,
263: final boolean useControlService, final String mode,
264: final BootErrorHandler errorHandler, final String[] args)
265: throws Exception {
266: InetAddress controlHost = useControlService ? InetAddress
267: .getByName(config.getProperty(PARAM_CONTROL_HOST))
268: : null;
269: int controlPort = useControlService ? Integer.parseInt(config
270: .getProperty(PARAM_CONTROL_PORT), 10) : 0;
271: // handle given command
272: if (useControlService && BOOT_MODE_STOP.equals(mode)) {
273: if (!ControlThread.stopRunningApplication(controlHost,
274: controlPort)) {
275: System.out.println("application not running"); //$NON-NLS-1$
276: } else {
277: System.out.println("application stopped"); //$NON-NLS-1$
278: }
279: return null;
280: }
281: if (useControlService && BOOT_MODE_START.equals(mode)) {
282: if (ControlThread.isApplicationRunning(controlHost,
283: controlPort)) {
284: errorHandler
285: .handleFatalError("Application already running."); //$NON-NLS-1$
286: return null;
287: }
288: Application application = initApplication(errorHandler,
289: config, args);
290: if (!(application instanceof ServiceApplication)) {
291: errorHandler
292: .handleFatalError("Application is not a service."); //$NON-NLS-1$
293: return null;
294: }
295: ControlThread controlThread = new ControlThread(
296: controlHost, controlPort,
297: (ServiceApplication) application);
298: application.startApplication();
299: controlThread.start();
300: System.out
301: .println("application started in BACKGROUND mode"); //$NON-NLS-1$
302: return application;
303: }
304: if (useControlService && BOOT_MODE_RESTART.equals(mode)) {
305: if (ControlThread.stopRunningApplication(controlHost,
306: controlPort)) {
307: System.out
308: .println("another instance of application stopped"); //$NON-NLS-1$
309: }
310: Application application = initApplication(errorHandler,
311: config, args);
312: if (!(application instanceof ServiceApplication)) {
313: errorHandler
314: .handleFatalError("Application is not a service."); //$NON-NLS-1$
315: return null;
316: }
317: ControlThread controlThread = new ControlThread(
318: controlHost, controlPort,
319: (ServiceApplication) application);
320: application.startApplication();
321: controlThread.start();
322: System.out
323: .println("application started in BACKGROUND mode"); //$NON-NLS-1$
324: return application;
325: }
326: // SHELL or LOAD or an unknown modes
327: if (useControlService
328: && ControlThread.stopRunningApplication(controlHost,
329: controlPort)) {
330: System.out
331: .println("another instance of application stopped"); //$NON-NLS-1$
332: }
333: if (!BOOT_MODE_LOAD.equals(mode)) {
334: initSplashHandler(config);
335: if (splashHandler != null) {
336: splashHandler.setVisible(true);
337: }
338: }
339: Application application = initApplication(errorHandler, config,
340: args);
341: if (!BOOT_MODE_LOAD.equals(mode)) {
342: application.startApplication();
343: if ((splashHandler != null)
344: && !"true".equalsIgnoreCase(config.getProperty( //$NON-NLS-1$
345: PARAM_SPLASH_LEAVE_VISIBLE, "false"))) { //$NON-NLS-1$
346: splashHandler.setVisible(false);
347: }
348: if ((application instanceof ServiceApplication)
349: && BOOT_MODE_SHELL.equals(mode)) {
350: System.out.println("application started in SHELL mode"); //$NON-NLS-1$
351: runShell();
352: stopApplication(application);
353: }
354: }
355: return application;
356: }
357:
358: /**
359: * Stops the application, shuts down plug-in manager and disposes log
360: * service. Call this method before exiting interactive application. For
361: * service applications this method will be called automatically by control
362: * service or from shell.
363: * @param application application instance being stopped
364: * @throws Exception if any error has occurred during application stopping
365: */
366: public static void stopApplication(final Application application)
367: throws Exception {
368: if (application instanceof ServiceApplication) {
369: ((ServiceApplication) application).stopApplication();
370: }
371: PluginManager pluginManager = PluginManager.lookup(application);
372: if (pluginManager != null) {
373: pluginManager.shutdown();
374: }
375: LogFactory.getLog(Boot.class).info("logging system finalized"); //$NON-NLS-1$
376: LogFactory.getLog(Boot.class).info(
377: "---------------------------------"); //$NON-NLS-1$
378: LogFactory.releaseAll();
379: }
380:
381: /**
382: * Returns current instance of splash screen handler if it is available or
383: * <code>null</code>.
384: * @return instance of splash handler or <code>null</code> if no active
385: * instance available
386: */
387: public static SplashHandler getSplashHandler() {
388: return splashHandler;
389: }
390:
391: /**
392: * @param handler the new splash handler instance to set or
393: * <code>null</code> to dispose current handler directly
394: */
395: public static void setSplashHandler(final SplashHandler handler) {
396: if ((handler == null) && (splashHandler != null)) {
397: splashHandler.setVisible(false);
398: }
399: splashHandler = handler;
400: }
401:
402: private static InputStream lookupConfig() throws IOException {
403: String property = System.getProperty(PROP_BOOT_CONFIG);
404: if (property != null) {
405: return IoUtil.getResourceInputStream(str2url(property));
406: }
407: File file = new File("boot.properties"); //$NON-NLS-1$
408: if (file.isFile()) {
409: return new FileInputStream(file);
410: }
411: URL url = Boot.class.getClassLoader().getResource(
412: "boot.properties"); //$NON-NLS-1$
413: if (url != null) {
414: return IoUtil.getResourceInputStream(url);
415: }
416: url = Boot.class.getResource("boot.properties"); //$NON-NLS-1$
417: if (url != null) {
418: return IoUtil.getResourceInputStream(url);
419: }
420: throw new IOException(
421: "configuration file boot.properties not found"); //$NON-NLS-1$
422: }
423:
424: private static URL str2url(final String str)
425: throws MalformedURLException {
426: int p = str.indexOf("!/"); //$NON-NLS-1$
427: if (p == -1) {
428: try {
429: return new URL(str);
430: } catch (MalformedURLException mue) {
431: return IoUtil.file2url(new File(str));
432: }
433: }
434: if (str.startsWith("jar:")) { //$NON-NLS-1$
435: return new URL(str);
436: }
437: File file = new File(str.substring(0, p));
438: if (file.isFile()) {
439: return new URL(
440: "jar:" + IoUtil.file2url(file) + str.substring(p)); //$NON-NLS-1$
441: }
442: return new URL("jar:" + str); //$NON-NLS-1$
443: }
444:
445: private static BootErrorHandler getErrorHandlerInstance(
446: final String handler, final boolean isServiceApp) {
447: if (handler != null) {
448: try {
449: return (BootErrorHandler) Class.forName(handler)
450: .newInstance();
451: } catch (InstantiationException ie) {
452: System.err
453: .println("failed instantiating error handler " //$NON-NLS-1$
454: + handler);
455: ie.printStackTrace();
456: } catch (IllegalAccessException iae) {
457: System.err
458: .println("failed instantiating error handler " //$NON-NLS-1$
459: + handler);
460: iae.printStackTrace();
461: } catch (ClassNotFoundException cnfe) {
462: System.err
463: .println("failed instantiating error handler " //$NON-NLS-1$
464: + handler);
465: cnfe.printStackTrace();
466: }
467: }
468: return isServiceApp ? new BootErrorHandlerConsole()
469: : (BootErrorHandler) new BootErrorHandlerGui();
470: }
471:
472: private static void initSplashHandler(
473: final ExtendedProperties config) throws Exception {
474: String handlerClass = config.getProperty(PARAM_SPLASH_HANDLER);
475: String splashImage = config.getProperty(PARAM_SPLASH_IMAGE);
476: URL url = null;
477: if ((splashImage != null) && (splashImage.length() > 0)) {
478: try {
479: url = new URL(splashImage);
480: } catch (MalformedURLException mue) {
481: // ignore
482: }
483: if (url == null) {
484: File splashFile = new File(splashImage);
485: if (splashFile.isFile()) {
486: url = IoUtil.file2url(splashFile);
487: } else {
488: throw new FileNotFoundException(
489: "splash image file " //$NON-NLS-1$
490: + splashFile + " not found"); //$NON-NLS-1$
491: }
492: }
493: }
494: boolean disposeOnHide = !"false".equalsIgnoreCase( //$NON-NLS-1$
495: config
496: .getProperty(PARAM_SPLASH_DISPOSE_ON_HIDE,
497: "true")); //$NON-NLS-1$
498: if (handlerClass != null) {
499: splashHandler = new SplashHandlerWrapper(disposeOnHide,
500: (SplashHandler) Class.forName(handlerClass)
501: .newInstance());
502: }
503: if ((splashHandler == null) && (url != null)) {
504: splashHandler = new SplashHandlerWrapper(disposeOnHide,
505: new SimpleSplashHandler());
506: }
507: if (splashHandler != null) {
508: if (url != null) {
509: splashHandler.setImage(url);
510: }
511: splashHandler.configure(config
512: .getSubset(PARAM_SPLASH_CONFIG_PREFIX));
513: }
514: }
515:
516: private static Application initApplication(
517: final BootErrorHandler errorHandler,
518: final ExtendedProperties props, final String[] args)
519: throws Exception {
520: ApplicationInitializer appInitializer = null;
521: String className = props.getProperty(PARAM_APP_INITIALIZER);
522: if (className != null) {
523: try {
524: appInitializer = (ApplicationInitializer) Class
525: .forName(className).newInstance();
526: } catch (InstantiationException ie) {
527: System.err
528: .println("failed instantiating application initializer " //$NON-NLS-1$
529: + className);
530: ie.printStackTrace();
531: } catch (IllegalAccessException iae) {
532: System.err
533: .println("failed instantiating application initializer " //$NON-NLS-1$
534: + className);
535: iae.printStackTrace();
536: } catch (ClassNotFoundException cnfe) {
537: System.err
538: .println("failed instantiating application initializer " //$NON-NLS-1$
539: + className);
540: cnfe.printStackTrace();
541: }
542: }
543: if (appInitializer == null) {
544: appInitializer = new DefaultApplicationInitializer();
545: }
546: appInitializer.configure(props);
547: Application result = appInitializer.initApplication(
548: errorHandler, args);
549: if (result == null) {
550: throw new Exception(ResourceManager.getMessage(
551: Boot.PACKAGE_NAME, "bootAppInitFailed")); //$NON-NLS-1$
552: }
553: return result;
554: }
555:
556: private static void runShell() {
557: System.out.println("Press 'q' key to exit."); //$NON-NLS-1$
558: do {
559: int c;
560: try {
561: c = System.in.read();
562: } catch (IOException ioe) {
563: break;
564: }
565: if (('q' == (char) c) || ('Q' == (char) c)) {
566: break;
567: }
568: } while (true);
569: }
570:
571: private static void clearBootLog() {
572: File file = new File(BOOT_ERROR_FILE_NAME);
573: if (file.isFile()) {
574: file.delete();
575: }
576: }
577:
578: private static void bootLog(final Throwable t) {
579: try {
580: Writer writer = new OutputStreamWriter(
581: new FileOutputStream(BOOT_ERROR_FILE_NAME, false),
582: "UTF-8"); //$NON-NLS-1$
583: try {
584: writer.write("JPF Application boot failed."); //$NON-NLS-1$
585: writer.write(System.getProperty("line.separator")); //$NON-NLS-1$
586: writer.write(ErrorDialog.getErrorDetails(t));
587: } finally {
588: writer.close();
589: }
590: } catch (Throwable t2) {
591: throw new Error("boot failed", t); //$NON-NLS-1$
592: }
593: }
594:
595: private Boot() {
596: // no-op
597: }
598: }
599:
600: final class SimpleSplashHandler implements SplashHandler {
601: private float progress;
602: private String text;
603: private URL image;
604: private boolean isVisible;
605:
606: /**
607: * @see org.java.plugin.boot.SplashHandler#configure(
608: * org.java.plugin.util.ExtendedProperties)
609: */
610: public void configure(final ExtendedProperties config) {
611: // no-op
612: }
613:
614: /**
615: * @see org.java.plugin.boot.SplashHandler#getProgress()
616: */
617: public float getProgress() {
618: return progress;
619: }
620:
621: /**
622: * @see org.java.plugin.boot.SplashHandler#setProgress(float)
623: */
624: public void setProgress(final float value) {
625: if ((value < 0) || (value > 1)) {
626: throw new IllegalArgumentException(
627: "invalid progress value " + value); //$NON-NLS-1$
628: }
629: progress = value;
630: }
631:
632: /**
633: * @see org.java.plugin.boot.SplashHandler#getText()
634: */
635: public String getText() {
636: return text;
637: }
638:
639: /**
640: * @see org.java.plugin.boot.SplashHandler#setText(java.lang.String)
641: */
642: public void setText(final String value) {
643: text = value;
644: }
645:
646: /**
647: * @see org.java.plugin.boot.SplashHandler#getImage()
648: */
649: public URL getImage() {
650: return image;
651: }
652:
653: /**
654: * @see org.java.plugin.boot.SplashHandler#setImage(java.net.URL)
655: */
656: public void setImage(final URL value) {
657: image = value;
658: }
659:
660: /**
661: * @see org.java.plugin.boot.SplashHandler#isVisible()
662: */
663: public boolean isVisible() {
664: return isVisible;
665: }
666:
667: /**
668: * @see org.java.plugin.boot.SplashHandler#setVisible(boolean)
669: */
670: public void setVisible(final boolean value) {
671: if (isVisible == value) {
672: return;
673: }
674: if (value) {
675: SplashWindow.splash(image);
676: isVisible = true;
677: return;
678: }
679: SplashWindow.disposeSplash();
680: isVisible = false;
681: }
682:
683: /**
684: * @see org.java.plugin.boot.SplashHandler#getImplementation()
685: */
686: public Object getImplementation() {
687: return this ;
688: }
689: }
690:
691: final class SplashHandlerWrapper implements SplashHandler {
692: private final SplashHandler delegate;
693: private final boolean isDisposeOnHide;
694:
695: SplashHandlerWrapper(final boolean disposeOnHide,
696: final SplashHandler other) {
697: isDisposeOnHide = disposeOnHide;
698: delegate = other;
699: }
700:
701: /**
702: * @see org.java.plugin.boot.SplashHandler#configure(
703: * org.java.plugin.util.ExtendedProperties)
704: */
705: public void configure(final ExtendedProperties config) {
706: delegate.configure(config);
707: }
708:
709: /**
710: * @see org.java.plugin.boot.SplashHandler#getProgress()
711: */
712: public float getProgress() {
713: return delegate.getProgress();
714: }
715:
716: /**
717: * @see org.java.plugin.boot.SplashHandler#setProgress(float)
718: */
719: public void setProgress(float value) {
720: delegate.setProgress(value);
721: }
722:
723: /**
724: * @see org.java.plugin.boot.SplashHandler#getText()
725: */
726: public String getText() {
727: return delegate.getText();
728: }
729:
730: /**
731: * @see org.java.plugin.boot.SplashHandler#setText(java.lang.String)
732: */
733: public void setText(String value) {
734: delegate.setText(value);
735: }
736:
737: /**
738: * @see org.java.plugin.boot.SplashHandler#getImage()
739: */
740: public URL getImage() {
741: return delegate.getImage();
742: }
743:
744: /**
745: * @see org.java.plugin.boot.SplashHandler#setImage(java.net.URL)
746: */
747: public void setImage(URL value) {
748: delegate.setImage(value);
749: }
750:
751: /**
752: * @see org.java.plugin.boot.SplashHandler#isVisible()
753: */
754: public boolean isVisible() {
755: return delegate.isVisible();
756: }
757:
758: /**
759: * @see org.java.plugin.boot.SplashHandler#setVisible(boolean)
760: */
761: public void setVisible(boolean value) {
762: delegate.setVisible(value);
763: if (isDisposeOnHide && !delegate.isVisible()) {
764: Boot.splashHandler = null;
765: }
766: }
767:
768: /**
769: * @see org.java.plugin.boot.SplashHandler#getImplementation()
770: */
771: public Object getImplementation() {
772: return delegate.getImplementation();
773: }
774:
775: }
|