Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  
  /*
   * Copyright (C) 2006 Sun Microsystems, Inc. All rights reserved. Use is
   * subject to license terms.
   */ 
  
  package org.jdesktop.application;
  
 import java.util.List;
The base class for Swing applications.

This class defines a simple lifecyle for Swing applications: initialize, startup, ready, and shutdown. The Application's startup method is responsible for creating the initial GUI and making it visible, and the shutdown method for hiding the GUI and performing any other cleanup actions before the application exits. The initialize method can be used configure system properties that must be set before the GUI is constructed and the ready method is for applications that want to do a little bit of extra work once the GUI is "ready" to use. Concrete subclasses must override the startup method.

Applications are started with the static launch method. Applications use the ApplicationContext Application.getContext singleton to find resources, actions, local storage, and so on.

All Application subclasses must override startup and they should call exit (which calls shutdown) to exit. Here's an example of a complete "Hello World" Application:

 public class MyApplication extends Application {
     JFrame mainFrame = null;
     @Override protected void startup() {
         mainFrame = new JFrame("Hello World");
         mainFrame.add(new JLabel("Hello World"));
         mainFrame.addWindowListener(new MainFrameListener());
         mainFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
         mainFrame.pack();
         mainFrame.setVisible(true);
     }
     @Override protected void shutdown() {
         mainFrame.setVisible(false);
     }
     private class MainFrameListener extends WindowAdapter {
         public void windowClosing(WindowEvent e) {
            exit();
         }
     }
     public static void main(String[] args) {
         Application.launch(MyApplication.class, args);
     }
 }
 

The mainFrame's defaultCloseOperation is set to DO_NOTHING_ON_CLOSE because we're handling attempts to close the window by calling ApplicationContext exit.

Simple single frame applications like the example can be defined more easily with the SingleFrameApplication Application subclass.

All of the Application's methods are called (must be called) on the EDT.

All but the most trivial applications should define a ResourceBundle in the resources subpackage with the same name as the application class (like resources/MyApplication.properties). This ResourceBundle contains resources shared by the entire application and should begin with the following the standard Application resources:

 Application.name = A short name, typically just a few words
 Application.id = Suitable for Application specific identifiers, like file names
 Application.title = A title suitable for dialogs and frames
 Application.version = A version string that can be incorporated into messages
 Application.vendor = A proper name, like Sun Microsystems, Inc.
 Application.vendorId = suitable for Application-vendor specific identifiers, like file names.
 Application.homepage = A URL like http://www.javadesktop.org
 Application.description =  One brief sentence
 Application.lookAndFeel = either system, default, or a LookAndFeel class name
 

The Application.lookAndFeel resource is used to initialize the UIManager lookAndFeel as follows:

  • system - the system (native) look and feel
  • default - use the JVM default, typically the cross platform look and feel
  • a LookAndFeel class name - use the specified class

Author(s):
Hans Muller (Hans.Muller@Sun.COM)
See also:
SingleFrameApplication
ApplicationContext
UIManager.setLookAndFeel
@ProxyActions({"cut""copy""paste""delete"})
public abstract class Application extends AbstractBean {
    private static final Logger logger = Logger.getLogger(Application.class.getName());
    private static Application application = null;
    private final List<ExitListenerexitListeners;
    private final ApplicationContext context;

    
Not to be called directly, see launch.

Subclasses can provide a no-args construtor to initialize private final state however GUI initialization, and anything else that might refer to public API, should be done in the startup method.

    protected Application() {
         = new ApplicationContext();
    }

    
Creates an instance of the specified Application subclass, sets the ApplicationContext application property, and then calls the new Application's startup method. The launch method is typically called from the Application's main:
     public static void main(String[] args) {
         Application.launch(MyApplication.class, args);
     }
 
The applicationClass constructor and startup methods run on the event dispatching thread.

Parameters:
applicationClass the Application class to launch
args main method arguments
See also:
shutdown()
ApplicationContext.getApplication()
    public static synchronized <T extends Applicationvoid launch(final Class<T> applicationClassfinal String[] args) {
	Runnable doCreateAndShowGUI = new Runnable() {
	    public void run() {
		try {
		     = create(applicationClass);
                    .initialize(args);
                    .waitForReady();
		}
		catch (Exception e) {
                    String msg = String.format("Application %s failed to launch"applicationClass);
		    .log(.msge);
                    throw(new Error(msge));
		}
	    }
	};
	SwingUtilities.invokeLater(doCreateAndShowGUI);
    }
    /* Initializes the ApplicationContext applicationClass and application
     * properties.  
     * 
     * Note that, as of Java SE 5, referring to a class literal
     * doesn't force the class to be loaded.  More info:
     * http://java.sun.com/javase/technologies/compatibility.jsp#literal
     * It's important to perform these initializations early, so that
     * Application static blocks/initializers happen afterwards.
     */
    static <T extends Application> T create(Class<T> applicationClassthrows Exception {
        if (!Beans.isDesignTime()) {
            /* A common mistake for privileged applications that make
             * network requests (and aren't applets or web started) is to
             * not configure the http.proxyHost/Port system properties.
             * We paper over that issue here.
             */
            try {
                System.setProperty("java.net.useSystemProxies""true"); 
            }
            catch (SecurityException ignoreException) {
                // Unsigned apps can't set this property. 
            }
        }
        /* Construct the Application object.  The following
         * complications, relative to just calling
         * applicationClass.newInstance(), allow a privileged app to
         * have a private static inner Application subclass.
         */
        Constructor<T> ctor = applicationClass.getDeclaredConstructor();
        if (!ctor.isAccessible()) {
            try {
                ctor.setAccessible(true);
            }
            catch (SecurityException ignore) {
                // ctor.newInstance() will throw an IllegalAccessException
            }
        }
        T application = ctor.newInstance();
        /* Initialize the ApplicationContext application properties
         */
        ApplicationContext ctx = application.getContext();
        ctx.setApplicationClass(applicationClass);
        ctx.setApplication(application);
	/* Load the application resource map, notably the 
	 * Application.* properties.
	 */
	ResourceMap appResourceMap = ctx.getResourceMap();
        appResourceMap.putResource("platform"platform());
        if (!Beans.isDesignTime()) {
            /* Initialize the UIManager lookAndFeel property with the
             * Application.lookAndFeel resource.  If the the resource
             * isn't defined we default to "system".
             */
            String key = "Application.lookAndFeel";
            String lnfResource = appResourceMap.getString(key);
            String lnf = (lnfResource == null) ? "system" : lnfResource;
            try {
                if (lnf.equalsIgnoreCase("system")) {
                    String name = UIManager.getSystemLookAndFeelClassName();
                    UIManager.setLookAndFeel(name);
                }
                else if (!lnf.equalsIgnoreCase("default")) {
                    UIManager.setLookAndFeel(lnf);
                }
            }
            catch(Exception e) {
                String s = "Couldn't set LookandFeel " + key + " = \"" + lnfResource + "\"";
                .log(.se);
            }
        }
        return application;
    }
    /* Defines the default value for the platform resource, 
     * either "osx" or "default".
     */
    private static String platform() {
        String platform = "default";
        try {
            String osName = System.getProperty("os.name");
            if ((osName != null) && osName.toLowerCase().startsWith("mac os x")) {
                platform = "osx";
            }
        }
        catch (SecurityException ignore) {
        }
        return platform;
    }
    /* Call the ready method when the eventQ is quiet.
     */
    void waitForReady() {
        new DoWaitForEmptyEventQ().execute();
    }

    
Responsible for initializations that must occur before the GUI is constructed by startup.

This method is called by the static launch method, before startup is called. Subclasses that want to do any initialization work before startup must override it. The initialize method runs on the event dispatching thread.

By default initialize() does nothing.

Parameters:
args the main method's arguments.
See also:
launch(java.lang.Class,java.lang.String[])
startup()
shutdown()
    protected void initialize(String[] args) {
    }

    
Responsible for starting the application; for creating and showing the initial GUI.

This method is called by the static launch method, subclasses must override it. It runs on the event dispatching thread.

    protected abstract void startup();

    
Called after the startup() method has returned and there are no more events on the system event queue. When this method is called, the application's GUI is ready to use.

It's usually important for an application to start up as quickly as possible. Applications can override this method to do some additional start up work, after the GUI is up and ready to use.

    protected void ready() {
    }

    
Called when the application exits. Subclasses may override this method to do any cleanup tasks that are neccessary before exiting. Obviously, you'll want to try and do as little as possible at this point. This method runs on the event dispatching thread.

    protected void shutdown() {
        // TBD should call TaskService#shutdownNow() on each TaskService
    }
    /* An event that sets a flag when it's dispatched and another
     * flag, see isEventQEmpty(), that indicates if the event queue
     * was empty at dispatch time.
     */
    private static class NotifyingEvent extends PaintEvent implements ActiveEvent {
        private boolean dispatched = false;
        private boolean qEmpty = false;
        NotifyingEvent(Component c) {
            super(c.null);
        }
        synchronized boolean isDispatched() { return ; }
        synchronized boolean isEventQEmpty() { return ; }
        public void dispatch() {
            EventQueue q = Toolkit.getDefaultToolkit().getSystemEventQueue();
            synchronized(this) {
		 = (q.peekEvent() == null);
                 = true;
                notifyAll();
            }
        }
    }
    /* Keep queuing up NotifyingEvents until the event queue is
     * empty when the NotifyingEvent is dispatched().
     */
    private void waitForEmptyEventQ() {
        boolean qEmpty = false;
        JPanel placeHolder  = new JPanel();
        EventQueue q = Toolkit.getDefaultToolkit().getSystemEventQueue();
        while (!qEmpty) {
            NotifyingEvent e = new NotifyingEvent(placeHolder);
            q.postEvent(e);
            synchronized(e) {
                while (!e.isDispatched()) {
                    try {
                        e.wait();
                    } 
		    catch (InterruptedException ie) {
                    }
                }
                qEmpty = e.isEventQEmpty();
            }
        }
    }
    /* When the event queue is empty, give the app a chance to do
     * something, now that the GUI is "ready".
     */
    private class DoWaitForEmptyEventQ extends Task<VoidVoid> {
        DoWaitForEmptyEventQ() { super(Application.this); }
	@Override protected Void doInBackground() {
	    return null;
	}
	@Override protected void finished() { 
	    ready();	
	}
    }


    
Gracefully shutdown the application, calls exit(null) This version of exit() is convenient if the decision to exit the application wasn't triggered by an event.

    public final void exit() {
	exit(null);
    }

    
Gracefully shutdown the application.

If none of the ExitListener.canExit() methods return false, calls the ExitListener.willExit() methods, then shutdown(), and then exits the Application with end. Exceptions thrown while running willExit() or shutdown() are logged but otherwise ignored.

If the caller is responding to an GUI event, it's helpful to pass the event along so that ExitListeners' canExit methods that want to popup a dialog know on which screen to show the dialog. For example:

 class ConfirmExit implements Application.ExitListener {
     public boolean canExit(EventObject e) {
         Object source = (e != null) ? e.getSource() : null;
         Component owner = (source instanceof Component) ? (Component)source : null;
         int option = JOptionPane.showConfirmDialog(owner, "Really Exit?");
         return option == JOptionPane.YES_OPTION;
     }
     public void willExit(EventObejct e) {} 
 }
 myApplication.addExitListener(new ConfirmExit());
 
The eventObject argument may be null, e.g. if the exit call was triggered by non-GUI code, and canExit, willExit methods must guard against the possibility that the eventObject argument's source is not a Component.

    public void exit(EventObject event) {
	for (ExitListener listener : ) {
	    if (!listener.canExit(event)) {
		return;
	    }
	}
	try {
	    for (ExitListener listener : ) {
		try {
		    listener.willExit(event);
		}
		catch (Exception e) { 
		    .log(."ExitListener.willExit() failed"e);
		}
	    }
	    shutdown();
	}
	catch (Exception e) { 
	    .log(."unexpected error in Application.shutdown()"e);
	}
	finally {
            end();
	}
    }

    
Called by exit to terminate the application. Calls Runtime.getRuntime().exit(0), which halts the JVM.

See also:
exit()
    protected void end() {
        Runtime.getRuntime().exit(0);
    }

    
Give the Application a chance to veto an attempt to exit/quit. An ExitListener's canExit method should return false if there are pending decisions that the user must make before the app exits. A typical ExitListener would prompt the user with a modal dialog.

The eventObject argument will be the the value passed to exit(). It may be null.

The willExit method is called after the exit has been confirmed. An ExitListener that's going to perform some cleanup work should do so in willExit.

ExitListeners run on the event dispatching thread.

    public interface ExitListener extends EventListener {
	boolean canExit(EventObject event);
	void willExit(EventObject event);
    }

    
Add an ExitListener to the list.

    public void addExitListener(ExitListener listener) {
	.add(listener);
    }

    
Remove an ExitListener from the list.

    public void removeExitListener(ExitListener listener) {
    }

    
All of the ExitListeners added so far.

Returns:
all of the ExitListeners added so far.
    public ExitListener[] getExitListeners() {
	int size = .size();
	return .toArray(new ExitListener[size]);
    }

    
The default Action for quitting an application, quit just exits the application by calling exit(e).

Parameters:
e the triggering event
See also:
exit(java.util.EventObject)
    @Action public void quit(ActionEvent e) {
	exit(e);
    }

    
The ApplicationContext singleton for this Application.

Returns:
the Application's ApplicationContext singleton
    public final ApplicationContext getContext() {
        return ;
    }

    
The Application singleton.

Typically this method is only called after an Application has been launched however in some situations, like tests, it's useful to be able to get an Application object without actually launching. In that case, an instance of the specified class is constructed and configured as it would be by the launch method. However it's initialize and startup methods are not run.

Parameters:
applicationClass this Application's subclass
Returns:
the launched Application singleton.
See also:
launch(java.lang.Class,java.lang.String[])
    public static synchronized <T extends Application> T getInstance(Class<T> applicationClass) {
        if ( == null) {
            /* Special case: the application hasn't been launched.  We're
             * constructing the applicationClass here to get the same effect
             * as the NoApplication class serves for getInstance().  We're
             * not launching the app, no initialize/startup/wait steps.
             */
            try {
                 = create(applicationClass);
            }
            catch (Exception e) {
                String msg = String.format("Couldn't construct %s"applicationClass);
                throw(new Error(msge));
            }
        }
	return applicationClass.cast();
    }

    
The Application singleton, or a placeholder if launch hasn't been called yet.

Typically this method is only called after an Application has been launched however in some situations, like tests, it's useful to be able to get an Application object without actually launching. The placeholder Application object provides access to an ApplicationContext singleton and has the same semantics as launching an Application defined like this:

 public class PlaceholderApplication extends Application {
     public void startup() { }
 }
 Application.launch(PlaceholderApplication.class);
 

Returns:
the Application singleton or a placeholder
See also:
launch(java.lang.Class,java.lang.String[])
getInstance(java.lang.Class)
    public static synchronized Application getInstance() {
        if ( == null) {
             = new NoApplication();
        }
        return ;
    }
    private static class NoApplication extends Application {
        protected NoApplication() {
            ApplicationContext ctx = getContext();
            ctx.setApplicationClass(getClass());
            ctx.setApplication(this);
            ResourceMap appResourceMap = ctx.getResourceMap();
            appResourceMap.putResource("platform"platform());
        }
        protected void startup() {}
    }
    /* Prototype support for the View type */
    public void show(View view) {
        Window window = (Window)view.getRootPane().getParent();
        if (window != null) {
            window.pack();
            window.setVisible(true);
        }
    }
    public void hide(View view) {
        view.getRootPane().getParent().setVisible(false);
    }
New to GrepCode? Check out our FAQ X