    001    /* ========================================================================
    002     * JCommon : a free general purpose class library for the Java(tm) platform
    003     * ========================================================================
    004     *
    005     * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
    006     *
    007     * Project Info:  http://www.jfree.org/jcommon/index.html
    008     *
    009     * This library is free software; you can redistribute it and/or modify it
    010     * under the terms of the GNU Lesser General Public License as published by
    011     * the Free Software Foundation; either version 2.1 of the License, or
    012     * (at your option) any later version.
    013     *
    014     * This library is distributed in the hope that it will be useful, but
    015     * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
    016     * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
    017     * License for more details.
    018     *
    019     * You should have received a copy of the GNU Lesser General Public
    020     * License along with this library; if not, write to the Free Software
    021     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
    022     * USA.
    023     *
    024     * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
    025     * in the United States and other countries.]
    026     *
    027     * -----------------
    028     * AbstractBoot.java
    029     * -----------------
    030     * (C)opyright 2004, 2005, by Thomas Morgner and Contributors.
    031     *
    032     * Original Author:  Thomas Morgner;
    033     * Contributor(s):   David Gilbert (for Object Refinery Limited);
    034     *
    035     * $Id: AbstractBoot.java,v 1.13 2005/11/03 09:54:59 mungady Exp $
    036     *
    037     * Changes
    038     * -------
    039     * 07-Jun-2004 : Added source headers (DG);
    040     * 18-Aug-2005 : Added casts to suppress compiler warnings, as suggested in
    041     *               patch 1260622 (DG);
    042     *
    043     */
    044
    045    package org.jfree.base;
    046
    047    import java.lang.reflect.Method;
    048
    049    import org.jfree.base.config.HierarchicalConfiguration;
    050    import org.jfree.base.config.PropertyFileConfiguration;
    051    import org.jfree.base.config.SystemPropertyConfiguration;
    052    import org.jfree.base.modules.PackageManager;
    053    import org.jfree.base.modules.SubSystem;
    054    import org.jfree.util.Configuration;
    055    import org.jfree.util.Log;
    056    import org.jfree.util.ObjectUtilities;
    057    import org.jfree.util.ExtendedConfiguration;
    058    import org.jfree.util.ExtendedConfigurationWrapper;
    059
    060    /**
    061     * The common base for all Boot classes.
    062     * <p>
    063     * This initializes the subsystem and all dependent subsystems.
    064     * Implementors of this class have to provide a public static
    065     * getInstance() method which returns a singleton instance of the
    066     * booter implementation.
    067     * <p>
    068     * Further creation of Boot object should be prevented using
    069     * protected or private constructors in that class, or proper
    070     * initialzation cannot be guaranteed.
    071     *
    072     * @author Thomas Morgner
    073     */
    074    public abstract class AbstractBoot implements SubSystem {
    075
    076        /** The configuration wrapper around the plain configuration. */
    077        private ExtendedConfigurationWrapper extWrapper;
    078
    079        /** A packageManager instance of the package manager. */
    080        private PackageManager packageManager;
    081
    082        /** Global configuration. */
    083        private Configuration globalConfig;
    084
    085        /** A flag indicating whether the booting is currenly in progress. */
    086        private boolean bootInProgress;
    087
    088        /** A flag indicating whether the booting is complete. */
    089        private boolean bootDone;
    090
    091        /**
    092         * Default constructor.
    093         */
    094        protected AbstractBoot() {
    095        }
    096
    097        /**
    098         * Returns the packageManager instance of the package manager.
    099         *
    100         * @return The package manager.
    101         */
    102        public synchronized PackageManager getPackageManager() {
    103            if (this.packageManager == null) {
    104                this.packageManager = PackageManager.createInstance(this);
    105            }
    106            return this.packageManager;
    107        }
    108
    109        /**
    110         * Returns the global configuration.
    111         *
    112         * @return The global configuration.
    113         */
    114        public synchronized Configuration getGlobalConfig() {
    115            if (this.globalConfig == null) {
    116                this.globalConfig = loadConfiguration();
    117                start();
    118            }
    119            return this.globalConfig;
    120        }
    121
    122        /**
    123         * Checks, whether the booting is in progress.
    124         *
    125         * @return true, if the booting is in progress, false otherwise.
    126         */
    127        public final synchronized boolean isBootInProgress() {
    128            return this.bootInProgress;
    129        }
    130
    131        /**
    132         * Checks, whether the booting is complete.
    133         *
    134         * @return true, if the booting is complete, false otherwise.
    135         */
    136        public final synchronized boolean isBootDone() {
    137            return this.bootDone;
    138        }
    139
    140        /**
    141         * Loads the configuration. This will be called exactly once.
    142         *
    143         * @return The configuration.
    144         */
    145        protected abstract Configuration loadConfiguration();
    146
    147        /**
    148         * Starts the boot process.
    149         */
    150        public final void start() {
    151
    152            synchronized (this) {
    153                if (isBootInProgress() || isBootDone()) {
    154                    return;
    155                }
    156                this.bootInProgress = true;
    157            }
    158
    159            // boot dependent libraries ...
    160            final BootableProjectInfo info = getProjectInfo();
    161            if (info != null) {
    162                Log.info (info.getName() + " " + info.getVersion());
    163                final BootableProjectInfo[] childs = info.getDependencies();
    164                for (int i = 0; i < childs.length; i++) {
    165                    final AbstractBoot boot = loadBooter(childs[i].getBootClass());
    166                    if (boot != null) {
    167                        boot.start();
    168                    }
    169                }
    170            }
    171            performBoot();
    172
    173            synchronized (this) {
    174                this.bootInProgress = false;
    175                this.bootDone = true;
    176            }
    177        }
    178
    179        /**
    180         * Performs the boot.
    181         */
    182        protected abstract void performBoot();
    183
    184        /**
    185         * Returns the project info.
    186         *
    187         * @return The project info.
    188         */
    189        protected abstract BootableProjectInfo getProjectInfo();
    190
    191        /**
    192         * Loads the specified booter implementation.
    193         *
    194         * @param classname  the class name.
    195         *
    196         * @return The boot class.
    197         */
    198        protected AbstractBoot loadBooter(final String classname) {
    199            if (classname == null) {
    200                return null;
    201            }
    202            try {
    203                final Class c = ObjectUtilities.getClassLoader(
    204                        getClass()).loadClass(classname);
    205                final Method m = c.getMethod("getInstance", (Class[]) null);
    206                return (AbstractBoot) m.invoke(null, (Object[]) null);
    207            }
    208            catch (Exception e) {
    209                Log.info ("Unable to boot dependent class: " + classname);
    210                return null;
    211            }
    212        }
    213
    214        /**
    215         * Creates a default configuration setup, which loads its settings from
    216         * the static configuration (defaults provided by the developers of the
    217         * library) and the user configuration (settings provided by the deployer).
    218         * The deployer's settings override the developer's settings.
    219         *
    220         * If the parameter <code>addSysProps</code> is set to true, the system
    221         * properties will be added as third configuration layer. The system
    222         * properties configuration allows to override all other settings.
    223         *
    224         * @param staticConfig the resource name of the developers configuration
    225         * @param userConfig the resource name of the deployers configuration
    226         * @param addSysProps a flag defining whether to include the system
    227         *                    properties into the configuration.
    228         * @return the configured Configuration instance.
    229         */
    230        protected Configuration createDefaultHierarchicalConfiguration
    231            (final String staticConfig, final String userConfig,
    232                    final boolean addSysProps)
    233        {
    234            final HierarchicalConfiguration globalConfig
    235                = new HierarchicalConfiguration();
    236
    237            if (staticConfig != null) {
    238              final PropertyFileConfiguration rootProperty
    239                  = new PropertyFileConfiguration();
    240              rootProperty.load(staticConfig);
    241              globalConfig.insertConfiguration(rootProperty);
    242              globalConfig.insertConfiguration(
    243                      getPackageManager().getPackageConfiguration());
    244            }
    245            if (userConfig != null)
    246            {
    247              final PropertyFileConfiguration baseProperty
    248                  = new PropertyFileConfiguration();
    249              baseProperty.load(userConfig);
    250              globalConfig.insertConfiguration(baseProperty);
    251            }
    252            final SystemPropertyConfiguration systemConfig
    253                = new SystemPropertyConfiguration();
    254            globalConfig.insertConfiguration(systemConfig);
    255            return globalConfig;
    256        }
    257
    258        /**
    259         * Returns the global configuration as extended configuration.
    260         *
    261         * @return the extended configuration.
    262         */
    263        public synchronized ExtendedConfiguration getExtendedConfig ()
    264        {
    265          if (extWrapper == null)
    266          {
    267            extWrapper = new ExtendedConfigurationWrapper(getGlobalConfig());
    268          }
    269          return extWrapper;
    270        }
    271    }