public class Application extends Object
The main startup class of the GUI application framework.
With this class a Java GUI application can be started. This works as follows:
ApplicationContext
is created and initialized. This includes
setting up a resource manager.
Per default the application's configuration file is expected to be located in
the class path and has the name config.xml. This can be changed
using system properties: The property
net.sf.jguiraffe.configName
allows to change the name of the
configuration file. If defined, a file with this name will be searched in the
class path. If the property net.sf.jguiraffe.configURL
is
provided, the class tries to load this file directly from this URL.
A bunch of configuration properties is evaluated by this class to perform the
correct setup. All of these must be placed in a section called
framework
. The following table lists the available properties:
Property | Description | Optional |
---|---|---|
appctx | In this section some properties of the application context are defined:
|
Yes |
builder | This section contains some setting related to the builders used for
processing bean definitions and GUI scripts. All properties in this section
are optional - meaningful default values are applied if a value is not set.
The following sub elements are supported:
|
Yes |
frame | In this section some properties of the application's main window can be
defined, especially its location and size. The idea is that this information
will be stored in a user configuration so that the last settings can be set
again on next application start. The following properties can be defined in
this section:
|
Yes |
storeuserconfig | A boolean property that determines whether the user specific configuration should be stored when the application terminates. Defaults to false. | Yes |
userconfigname | Defines the name of the user configuration in the configuration definition file. (The configuration definition file can include an arbitrary number of configuration sources. To determine, which of these is the user configuration, its name must be specified. If no name is specified, the default userConfig will be used. | Yes |
A major part of the configuration of the application is defined in terms of
bean definitions. Here many helper classes used by the application are
defined (e.g. the resource manager, the message output object, the GUI
builder, and many more). At start up, the application creates a
BeanContext
that provides access to these beans and creates the
required instances. There is a default bean definition file (
defaultbeans.jelly) with default bean definitions for all available
helper classes. It is loaded first. Concrete applications can override some
or all of these beans. This is a powerful means of customizing the
application.
To override bean definitions, use the
framework.builder.beandefinitions
section in the application's
main configuration file (see above). In this section the names of an
arbitrary number of bean definition files can be specified (the files will be
loaded from the class path). Using the predefined names for the default beans
in these scripts causes the beans to be replaced by the custom ones. Have a
look at the defaultbeans.jelly script for more information; in this
file all available default beans are listed with a documentation for each.
Modifier and Type | Field and Description |
---|---|
static String |
BEAN_APPLICATION
Constant for the name of the bean with the current application instance.
|
static String |
BEAN_APPLICATION_CONTEXT
Constant for the name of the bean with the application context.
|
static String |
BEAN_BINDING_STRATEGY
Constant for the name of the binding strategy bean.
|
static String |
BEAN_BUILDER
Constant for the name of the builder bean.
|
static String |
BEAN_CLASS_LOADER_PROVIDER
Constant for the name of the bean for the class loader provider.
|
static String |
BEAN_COMMAND_QUEUE
Constant for the name of the command queue bean.
|
static String |
BEAN_CONFIGURATION
Constant for the name of the bean with the global configuration.
|
static String |
BEAN_DEF_RES_GROUP
Constant for the name of the bean with the default resource group.
|
static String |
BEAN_GLOBAL_CONTEXT
Constant for the name of the bean with the global bean context.
|
static String |
BEAN_GUI_SYNCHRONIZER
Constant for the name of the GUI synchronizer bean.
|
static String |
BEAN_LOCALE
Constant for the name of the bean with the locale.
|
static String |
BEAN_PREFIX
Constant for the prefix for bean definitions used by the framework.
|
static String |
BUILDER_SECTION
Constant for the section with the builder information.
|
static String |
CLASS_LOADER
Constant for the name of the class loader which loaded the application
class.
|
static String |
CONFIG_SECTION
Constant for the configuration section for the framework.
|
static String |
DEF_CONFIG_NAME
Constant for the default name of the configuration file.
|
static String |
FRAME_SECTION
Constant for the frame section in the configuration file.
|
protected org.apache.commons.logging.Log |
log
The logger to use.
|
static String |
PROP_APPCTX
Constant for the application context property in the config file.
|
static String |
PROP_BEAN_BUILDER_FACTORY
Constant for the bean builder factory property.
|
static String |
PROP_BEAN_DEFS
Constant for the bean definitions property.
|
static String |
PROP_BUILDER_FACTORY
Constant for the builder factory property.
|
static String |
PROP_BUILDER_MAIN_SCRIPT
Constant for the builder main script property.
|
static String |
PROP_BUILDER_MENU_ICON
Constant for the builder menu icon property.
|
static String |
PROP_BUILDER_TOOLBAR_TEXT
Constant for the builder toolbar text property.
|
static String |
PROP_CONFIG_NAME
Constant for the system property with the resource name of the
configuration file.
|
static String |
PROP_CONFIG_URL
Constant for the system property with the URL to the configuration file.
|
static String |
PROP_DEFRESGROUP
Constant for the default resource group property in the config file.
|
static String |
PROP_HEIGHT
Constant for the height property in the config file.
|
static String |
PROP_LOCALE
Constant for the locale property in the config file.
|
static String |
PROP_USRCONF
Constant for the storeuserconfig property in the config file.
|
static String |
PROP_USRCONFNAME
Constant for the userconfigname property in the config file.
|
static String |
PROP_WIDTH
Constant for the width property in the config file.
|
static String |
PROP_XPOS
Constant for the xpos property in the config file.
|
static String |
PROP_YPOS
Constant for the ypos property in the config file.
|
static String |
USRCONF_NAME
Constant for the name of the user configuration.
|
Constructor and Description |
---|
Application()
Creates a new instance of
Application . |
Modifier and Type | Method and Description |
---|---|
protected void |
addBeanDuringApplicationStartup(String name,
Object bean)
Adds a bean to the application's global root bean store while the
application starts up.
|
void |
addShutdownListener(ApplicationShutdownListener l)
Registers the specified object as a shutdown listeners.
|
protected ApplicationContext |
createApplicationContext()
Creates and initializes the application context.
|
protected BeanBuilderFactory |
createBeanBuilderFactory(org.apache.commons.configuration.Configuration config)
Creates the factory for the bean builder.
|
protected CommandQueue |
createCommandQueue(ApplicationContext appCtx)
Creates and initializes the application's command queue.
|
protected org.apache.commons.configuration.HierarchicalConfiguration |
createConfiguration()
Creates the configuration for this application.
|
protected org.apache.commons.configuration.HierarchicalConfiguration |
createConfiguration(URL configURL)
Reads the application's configuration from the specified URL.
|
protected MutableBeanStore |
createRootStore(org.apache.commons.configuration.Configuration config)
Creates the root bean store.
|
void |
execute(Command cmd)
Executes the given command.
|
protected void |
exitApplication(int exitCode)
Terminates this application.
|
protected URL |
fetchConfigURL()
Returns the URL to the configuration file.
|
protected Collection<Locator> |
findBeanDefinitions(org.apache.commons.configuration.Configuration config)
Deprecated.
This method is replaced by
findBeanDefinitions(Configuration, BeanContext) . It
is still called during application initialization to keep
backwards compatibility, but this base implementation simply
returns an empty collection. |
protected Collection<Locator> |
findBeanDefinitions(org.apache.commons.configuration.Configuration config,
BeanContext beanCtx)
Returns a collection with additional bean definition files to process.
|
protected boolean |
fireCanShutdown()
Calls the
canShutdown() method on all registered shutdown
listeners. |
protected void |
fireShutdown()
Notifies all registered shutdown listeners about the shutdown of this
application.
|
ApplicationContext |
getApplicationContext()
Returns a reference to the actual application context.
|
BeanBuilderFactory |
getBeanBuilderFactory()
Returns the
BeanBuilderFactory for obtaining a bean
builder. |
CommandQueue |
getCommandQueue()
Returns a reference to the command queue that is used for executing
commands in another thread.
|
String |
getConfigResourceName()
Returns the resource name of the configuration file.
|
String |
getConfigURL()
Returns the URL from which the configuration file is to be loaded.
|
int |
getExitCode()
Returns the current exit code for this application.
|
Runnable |
getExitHandler()
Returns the current exit handler of this application.
|
GUISynchronizer |
getGUISynchronizer()
Returns the
GUISynchronizer object used by this
application. |
static Application |
getInstance(BeanContext context)
Obtains the central
Application instance from the specified
BeanContext . |
BeanContext |
getMainWindowBeanContext()
Returns the
BeanContext that was created when processing the
builder script for the main window. |
protected Locator |
getPlatformBeansLocator()
Returns a
Locator object pointing to a file with bean
declarations related to the platform or UI toolkit. |
org.apache.commons.configuration.Configuration |
getUserConfiguration()
Returns the configuration object with user specific settings.
|
protected BeanContext |
initBeans(org.apache.commons.configuration.Configuration config)
Initializes the application's bean definitions.
|
protected ClassLoaderProvider |
initClassLoaderProvider(ClassLoaderProvider clp)
Initializes the global
ClassLoaderProvider . |
protected void |
initGUI(ApplicationContext appCtx)
Initializes the application's main GUI.
|
protected void |
initMainWindow(Window window,
org.apache.commons.configuration.Configuration config)
Initializes the application's main window object.
|
protected Locator |
locatorForMainScript(org.apache.commons.configuration.Configuration config)
Returns the locator object for the application's main build script.
|
static void |
main(String[] args)
A main method for applications based on this framework.
|
protected void |
onShutdown()
A hook for shutdown.
|
void |
processCommandLine(String[] args)
Hook method for processing the command line arguments.
|
protected BeanBuilderResult |
readBeanDefinition(Locator script,
MutableBeanStore rootStore,
ClassLoaderProvider loaderProvider)
A convenience method for processing a file with bean definitions.
|
protected void |
releaseBeanBuilderResults(Collection<BeanBuilderResult> results)
Releases the results of bean builder operations that were created during
initialization of this application.
|
void |
removeShutdownListener(ApplicationShutdownListener l)
Removes the specified shutdown listener.
|
static URL |
resolveResourceURL(String url,
String name)
Deprecated.
This method does not make sense in the public interface of
this class. It will be removed in later versions. Use corresponding
functionality from the
LocatorUtils class instead. |
void |
run()
The main execute method of this application.
|
void |
saveUserConfiguration()
Stores the configuration with user specific settings.
|
void |
setApplicationContext(ApplicationContext context)
Sets the application context.
|
static void |
setApplicationReference(Object target,
Application ref)
Tries to the set a reference to the global
Application
object in the target object. |
void |
setBeanBuilderFactory(BeanBuilderFactory beanBuilderFactory)
Allows to set the
BeanBuilderFactory . |
void |
setCommandQueue(CommandQueue q)
Sets the command queue that is used for executing commands.
|
void |
setConfigResourceName(String configResourceName)
Sets the resource name under which the configuration file can be loaded.
|
void |
setConfigURL(String configURL)
Sets the URL to the configuration file.
|
void |
setExitHandler(Runnable handler)
Sets the exit handler for this application.
|
void |
setGUISynchronizer(GUISynchronizer sync)
Sets the
GUISynchronizer object to be used by this
application. |
protected void |
showMainWindow(Window window)
Shows the application's main window.
|
void |
shutdown()
Shuts down this application unconditionally.
|
void |
shutdown(Object msgres,
Object titleres)
Shuts down this application.
|
static void |
startup(Application application,
String[] args)
Starts an application.
|
protected void |
updateUserConfiguration()
Updates the user configuration.
|
public static final String PROP_CONFIG_URL
public static final String PROP_CONFIG_NAME
public static final String DEF_CONFIG_NAME
public static final String BEAN_PREFIX
public static final String BEAN_CONFIGURATION
public static final String BEAN_APPLICATION
public static final String BEAN_APPLICATION_CONTEXT
public static final String BEAN_GLOBAL_CONTEXT
public static final String BEAN_BUILDER
public static final String BEAN_COMMAND_QUEUE
public static final String BEAN_GUI_SYNCHRONIZER
public static final String BEAN_BINDING_STRATEGY
public static final String BEAN_LOCALE
public static final String BEAN_DEF_RES_GROUP
public static final String BEAN_CLASS_LOADER_PROVIDER
public static final String CONFIG_SECTION
public static final String PROP_APPCTX
public static final String PROP_LOCALE
public static final String PROP_DEFRESGROUP
public static final String BUILDER_SECTION
public static final String PROP_BUILDER_FACTORY
public static final String PROP_BEAN_BUILDER_FACTORY
public static final String PROP_BEAN_DEFS
public static final String PROP_BUILDER_MENU_ICON
public static final String PROP_BUILDER_TOOLBAR_TEXT
public static final String PROP_BUILDER_MAIN_SCRIPT
public static final String FRAME_SECTION
public static final String PROP_XPOS
public static final String PROP_YPOS
public static final String PROP_WIDTH
public static final String PROP_HEIGHT
public static final String PROP_USRCONF
public static final String PROP_USRCONFNAME
public static final String USRCONF_NAME
public static final String CLASS_LOADER
ClassLoaderProvider
created at startup.protected final org.apache.commons.logging.Log log
public String getConfigURL()
public void setConfigURL(String configURL)
configURL
- the URL to the configuration filepublic String getConfigResourceName()
public void setConfigResourceName(String configResourceName)
configResourceName
- the resource name of the configuration filepublic ApplicationContext getApplicationContext()
ApplicationContext
public void setApplicationContext(ApplicationContext context)
context
- the new contextpublic BeanBuilderFactory getBeanBuilderFactory()
BeanBuilderFactory
for obtaining a bean
builder. This method can be used when a bean definition file is to be
processed.BeanBuilderFactory
public void setBeanBuilderFactory(BeanBuilderFactory beanBuilderFactory)
BeanBuilderFactory
. Normally it is not
necessary to set this property. When the application is initialized it
creates a default factory.beanBuilderFactory
- the new BeanBuilderFactory
public void addShutdownListener(ApplicationShutdownListener l)
l
- the listener to registerpublic void removeShutdownListener(ApplicationShutdownListener l)
l
- the listener to remove@Deprecated public static URL resolveResourceURL(String url, String name)
LocatorUtils
class instead.url
- a URL to the resource; this can be a full qualified URL or the
name of a file (either relative or absolute)name
- the resource namepublic static void setApplicationReference(Object target, Application ref)
Application
object in the target object. If the target object implements the
ApplicationClient
interface, the reference can be set.target
- the target objectref
- the application reference to setpublic org.apache.commons.configuration.Configuration getUserConfiguration() throws ApplicationRuntimeException
Returns the configuration object with user specific settings. This
configuration can be used to store personalization settings that override
the default configuration. For this method to work the system's main
configuration definition file must include an entry for the user
configuration that is identified by its name. Per default the name is
"userConfig", but can be altered with the
userconfigname
property. The following example fragment
from the application's configuration definition file demonstrates how the
user configuration should be declared:
<configuration> ... <xml fileName="${user.home}/myAppConfig.xml" config-name="userConfig" config-optional="true" config-forceCreate="true"/> <!-- Further configuration sources to load --> ...
In this example the attributes starting with config-
are
of special importance. With config-name
the
configuration's name is specified, which is necessary for the framework
to retrieve the correct user configuration. config-optional
declares this configuration source as optional. This means that it won't
cause an error when this source cannot be loaded (which will probably be
the case when a user starts this application for the first time). The
config-forceCreate
attribute finally tells the
configuration framework to create an empty configuration when loading of
the configuration file fails. This will cause the configuration to be
automatically created for the new user. If the user customizes the
application, these settings can be stored in this configuration. When the
application terminates it checks the value of the
storeuserconfig
property. If this is set to true,
the user configuration will be stored. So the next time the application
starts it will be found there and override the values in all other
configuration sources.
ApplicationRuntimeException
- if the user configuration cannot be
obtainedpublic void saveUserConfiguration() throws ApplicationException
getUserConfiguration()
method. It expects that the user configuration implements the
FileConfiguration
interface. If a different configuration
type is used as user configuration, this method should also be adapted.ApplicationException
- if an error occursprotected ApplicationContext createApplicationContext()
ApplicationRuntimeException
- if an error occurs during
initializationprotected URL fetchConfigURL()
configURL
and configResourceName
.ApplicationRuntimeException
- if the configuration file cannot be
locatedprotected org.apache.commons.configuration.HierarchicalConfiguration createConfiguration()
fetchConfigURL()
to determine the URL to the main
configuration file. Then this file is loaded with commons-configuration.ApplicationRuntimeException
- if the configuration file cannot be
locatedprotected org.apache.commons.configuration.HierarchicalConfiguration createConfiguration(URL configURL)
DefaultConfigurationBuilder
of
Commons Configuration is used for reading the configuration.
Occurring exceptions are re-thrown as runtime exceptions.configURL
- the configuration URLApplicationRuntimeException
- if the configuration cannot be loadedprotected MutableBeanStore createRootStore(org.apache.commons.configuration.Configuration config)
config
- the configuration objectprotected BeanBuilderFactory createBeanBuilderFactory(org.apache.commons.configuration.Configuration config)
config
- the main configurationBeanBuilderFactory
to be usedprotected BeanContext initBeans(org.apache.commons.configuration.Configuration config)
findBeanDefinitions()
is
called for obtaining a list of additional definition files to be
evaluated. Finally a bean context is created allowing access to all beans
defined this way. This algorithm allows concrete applications to define
their own beans in an easy way and also to override standard beans used
by the framework.config
- the main configuration sourceprotected void addBeanDuringApplicationStartup(String name, Object bean)
initBeans(Configuration)
and before the global bean context is
accessed. Calling this method to a later point of time is not guaranteed
to have the desired effect!name
- the name of the beanbean
- the bean itselfprotected ClassLoaderProvider initClassLoaderProvider(ClassLoaderProvider clp)
ClassLoaderProvider
. This method is called
by initBeans(Configuration)
after the default beans have been
loaded. The ClassLoaderProvider
passed to this method was
obtained from the default beans. A derived class can override this method
to perform specific initialization of the passed in ClassLoaderProvider
. It can even create a completely new object (the
ClassLoaderProvider
returned by this method will become the
global ClassLoaderProvider
; it need not be the same object as was
passed to this method). This base implementation registers the
class loader which has loaded the concrete Application
sub
class and makes it the default class loader.clp
- the ClassLoaderProvider
as obtained from the default
beansClassLoaderProvider
(must never be
null)protected BeanBuilderResult readBeanDefinition(Locator script, MutableBeanStore rootStore, ClassLoaderProvider loaderProvider)
script
- defines the script with the bean definitionsrootStore
- the root store for storing the resultsloaderProvider
- the optional class loader providerIllegalArgumentException
- if required parameters are missingApplicationRuntimeException
- if an error occurs@Deprecated protected Collection<Locator> findBeanDefinitions(org.apache.commons.configuration.Configuration config)
findBeanDefinitions(Configuration, BeanContext)
. It
is still called during application initialization to keep
backwards compatibility, but this base implementation simply
returns an empty collection.config
- the main configuration sourceprotected Collection<Locator> findBeanDefinitions(org.apache.commons.configuration.Configuration config, BeanContext beanCtx)
framework.builder.beandefinitions.beandefinition
configuration
property. The values are interpreted as textual representations of
Locator
objects which can be converted using the
LocatorConverter
class. Strings that do not contain a locator
type prefix (e.g. classpath:
or url:
are expected to be
names of bean definition files, which can be read from the class path. In
addition, the getPlatformBeansLocator()
method is called to
obtain a Locator
for a file with platform-specific bean
declarations; if this method returns a non-null value, this
Locator
is added to the list, too. If an application has
different requirements for specifying additional bean definition files,
this method can be overridden.config
- the main configuration sourcebeanCtx
- the current BeanContext
protected Locator getPlatformBeansLocator()
Locator
object pointing to a file with bean
declarations related to the platform or UI toolkit. This method is called
when additional bean declaration files to be loaded during application
initialization are detected. The base implementation returns a locator
pointing to a class path resource with the name
platformbeans.jelly
. This file contains declarations for beans
like the platform-specific component manager, window manager, etc. In a
standard JGUIraffe application a single file with this name exists which
contains definitions compatible to the supported platform. A derived
class may override this method and return a different Locator
.
Result can be null, then no additional bean declaration file is
loaded.Locator
pointing to platform-specific bean declarationsprotected void initGUI(ApplicationContext appCtx)
appCtx
- the application contextApplicationRuntimeException
- if an error occursprotected Locator locatorForMainScript(org.apache.commons.configuration.Configuration config)
config
- the configurationprotected void initMainWindow(Window window, org.apache.commons.configuration.Configuration config)
window
- the new main window objectconfig
- the actual configurationprotected void showMainWindow(Window window)
window
- the main windowprotected CommandQueue createCommandQueue(ApplicationContext appCtx)
appCtx
- the application contextInjectionException
- if the command queue
cannot be createdpublic CommandQueue getCommandQueue()
public void setCommandQueue(CommandQueue q)
q
- the new command queue (must not be null)IllegalArgumentException
- if the command queue is nullpublic GUISynchronizer getGUISynchronizer()
GUISynchronizer
object used by this
application. This object can be used to deal with the event dispatch
thread.public void setGUISynchronizer(GUISynchronizer sync)
GUISynchronizer
object to be used by this
application. This object can be used for safe GUI updates that need to
take place at the event dispatch thread. It will also set at the
application's command queue, so that always the same synchronizer is
used.sync
- the GUI synchronizerpublic void execute(Command cmd)
ApplicationClient
interface, a reference to
this application will be automatically set before execution.cmd
- the command to be executedpublic void shutdown(Object msgres, Object titleres)
ApplicationResourceDef
object. Only if the user
confirms this, the application will be ended.msgres
- defines the resource of the message to be displayedtitleres
- defines the resource of the title of the messagepublic void shutdown()
shutdown()
method does not check for tasks still running in the
background. It directly invokes the registered shutdown listeners and
exits the application if none vetos.public Runnable getExitHandler()
shutdown()
operation. This method
never returns null. If no exit handler has been set, a default one
is returned. The default exit handler terminates this application by
calling System.exit()
with the current exit code.public void setExitHandler(Runnable handler)
shutdown()
. Its task is to ultimately
terminate this application, e.g. by calling System.exit()
.handler
- the exit handler for this application (may be null)public int getExitCode()
shutdown()
operation. This method is intended to
be called by an exit handler to find out the exit status of the
application.setExitHandler(Runnable)
public BeanContext getMainWindowBeanContext()
BeanContext
that was created when processing the
builder script for the main window. This context may be useful because it
contains some central objects defined by the builder script for the main
window, e.g. global actions. If this application does not define a
builder script for the main window, this method returns null.BeanContext
created when the main window was
constructedprotected void onShutdown()
shutdown()
method. Here application specific
cleanup can be placed. Note: if this method is overloaded in a derived
class, the inherited method should be called. This implementation cares
for storing the user specific configuration if the
storeuserconfig
property is true. Before that the
updateUserConfiguration()
method is called.protected void updateUserConfiguration()
storeuserconfig
configuration property is set. Here
actual settings can be written in the user configuration object so that
they can be restored the next time the application is started again. This
implementation stores the actual bounds of the main frame in the user
config.protected boolean fireCanShutdown()
canShutdown()
method on all registered shutdown
listeners. If one of them returns false , the remaining listeners
are not invoked and shutdown process is canceled.protected void fireShutdown()
protected void releaseBeanBuilderResults(Collection<BeanBuilderResult> results)
initBeans(Configuration)
are stored so
that they can be released when the application shuts down. This is
exactly the task of this method. It is called by shutdown()
.results
- the collection with the builder results to be releasedprotected void exitApplication(int exitCode)
shutdown(Object, Object)
at the very end. It calls the
exit handler. This object is responsible for actually
terminating this application.exitCode
- the exit codesetExitHandler(Runnable)
public void run() throws ApplicationException
ApplicationException
- if an error occurs during initializationpublic void processCommandLine(String[] args) throws ApplicationException
args
- the command line argumentsApplicationException
- if a command line error occurspublic static void startup(Application application, String[] args) throws ApplicationException
Application
object. First the system properties
are checked if the configuration file is specified. Then the application
is given the opportunity of processing its command line. Finally its
run()
method is invoked, which starts the application. A
typical use case for this method is to create an Application
instance (which also can be of a derived class) and pass it to this
method together with the command line array. The rest is done by this
method.application
- the application to startargs
- the command line argumentsApplicationException
- if an error occurspublic static void main(String[] args) throws ApplicationException
startup()
method.args
- command line argumentsApplicationException
- if an error occurspublic static Application getInstance(BeanContext context)
Application
instance from the specified
BeanContext
. This method provides an easy way for obtaining
the Application
when only the ApplicationContext
is
known: just call
Application myApp = Application.getInstance(appCtx.getBeanContext());If the application cannot be found in the given bean context, an exception is thrown.
context
- the bean contextApplication
object defined in this bean contextInjectionException
- if the application bean
cannot be foundIllegalArgumentException
- if the passed in context is nullCopyright © 2016 The JGUIraffe Team. All rights reserved.