Package org.pentaho.reporting.engine.classic.core

Source Code of org.pentaho.reporting.engine.classic.core.ClassicEngineBoot$UserConfigWrapper

/*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
* or from the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* Copyright (c) 2001 - 2009 Object Refinery Ltd, Pentaho Corporation and Contributors..  All rights reserved.
*/

package org.pentaho.reporting.engine.classic.core;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.pentaho.reporting.engine.classic.core.style.StyleKey;
import org.pentaho.reporting.libraries.base.boot.AbstractBoot;
import org.pentaho.reporting.libraries.base.boot.DefaultModuleInfo;
import org.pentaho.reporting.libraries.base.boot.PackageManager;
import org.pentaho.reporting.libraries.base.config.Configuration;
import org.pentaho.reporting.libraries.base.config.HierarchicalConfiguration;
import org.pentaho.reporting.libraries.base.config.ModifiableConfiguration;
import org.pentaho.reporting.libraries.base.config.PropertyFileConfiguration;
import org.pentaho.reporting.libraries.base.config.SystemPropertyConfiguration;
import org.pentaho.reporting.libraries.base.util.CSVTokenizer;
import org.pentaho.reporting.libraries.base.util.ObjectUtilities;
import org.pentaho.reporting.libraries.base.versioning.ProjectInformation;

/**
* An utility class to safely boot and initialize the Pentaho-Reporting library. This class should be called before
* using the Pentaho-Reporting classes, to make sure that all subsystems are initialized correctly and in the correct
* order.
* <p/>
* Application developers should make sure, that the booting is done before any Pentaho-Reporting functions are used. If
* the system has not be initialized by booting this class, anything can happen and the results of all functionality of
* this reporting engine will be undefined.
* <p/>
* Additional modules can be specified by defining the system property <code>"org.pentaho.reporting.engine.classic.core.boot.Modules"</code>.
* The property expects a comma-separated list of {@link org.pentaho.reporting.libraries.base.boot.Module}
* implementations.
* <p/>
* Booting should be done by aquirering a new boot instance using {@link ClassicEngineBoot#getInstance()} and then
* starting the boot process with {@link ClassicEngineBoot#start()}.
*
* @author Thomas Morgner
*/
public class ClassicEngineBoot extends AbstractBoot
{
  public static final String INDEX_COLUMN_PREFIX = "::column::";
  public static final String METADATA_NAMESPACE =
      "http://reporting.pentaho.org/namespaces/engine/classic/metadata/1.0";
  public static final String DATASCHEMA_NAMESPACE =
      "http://reporting.pentaho.org/namespaces/engine/classic/dataschema/1.0";
  public static final String BUNDLE_TYPE = "application/vnd.pentaho.reporting.classic";

  private static final Log logger = LogFactory.getLog(ClassicEngineBoot.class);

  /**
   * A wrappper around the user supplied global configuration.
   */
  private static class UserConfigWrapper extends HierarchicalConfiguration
  {
    /**
     * The wrapped configuration.
     */
    private Configuration wrappedConfiguration;

    /**
     * Default constructor.
     */
    protected UserConfigWrapper()
    {
      this(null);
    }

    /**
     * Creates a new user-configuration wrapper for the given configuration.
     *
     * @param config the user-provided configuration that should be wrapped.
     */
    protected UserConfigWrapper(final Configuration config)
    {
      this.wrappedConfiguration = config;
    }

    /**
     * Sets a new configuration. This configuration will be inserted into the report configuration hierarchy. Set this
     * property to null to disable the user defined configuration.
     *
     * @param wrappedConfiguration the wrapped configuration.
     */
    public void setWrappedConfiguration(final Configuration wrappedConfiguration)
    {
      this.wrappedConfiguration = wrappedConfiguration;
    }

    /**
     * Returns the user supplied global configuration, if exists.
     *
     * @return the user configuration.
     */
    public Configuration getWrappedConfiguration()
    {
      return wrappedConfiguration;
    }

    /**
     * Returns the configuration property with the specified key.
     *
     * @param key the property key.
     * @return the property value.
     */
    public String getConfigProperty(final String key)
    {
      if (wrappedConfiguration == null)
      {
        return getParentConfig().getConfigProperty(key);
      }

      final String retval = wrappedConfiguration.getConfigProperty(key);
      if (retval != null)
      {
        return retval;
      }
      return getParentConfig().getConfigProperty(key);
    }

    /**
     * Returns the configuration property with the specified key (or the specified default value if there is no such
     * property).
     * <p/>
     * If the property is not defined in this configuration, the code will lookup the property in the parent
     * configuration.
     *
     * @param key          the property key.
     * @param defaultValue the default value.
     * @return the property value.
     */
    public String getConfigProperty(final String key, final String defaultValue)
    {
      if (wrappedConfiguration == null)
      {
        return getParentConfig().getConfigProperty(key, defaultValue);
      }

      final String retval = wrappedConfiguration.getConfigProperty(key, null);
      if (retval != null)
      {
        return retval;
      }
      return getParentConfig().getConfigProperty(key, defaultValue);
    }

    /**
     * Sets a configuration property.
     *
     * @param key   the property key.
     * @param value the property value.
     */
    public void setConfigProperty(final String key, final String value)
    {
      if (wrappedConfiguration instanceof ModifiableConfiguration)
      {
        final ModifiableConfiguration modConfiguration =
            (ModifiableConfiguration) wrappedConfiguration;
        modConfiguration.setConfigProperty(key, value);
      }
    }

    /**
     * Returns all defined configuration properties for the report. The enumeration contains all keys of the changed
     * properties, properties set from files or the system properties are not included.
     *
     * @return all defined configuration properties for the report.
     */
    public Enumeration getConfigProperties()
    {
      if (wrappedConfiguration instanceof ModifiableConfiguration)
      {
        final ModifiableConfiguration modConfiguration =
            (ModifiableConfiguration) wrappedConfiguration;
        return modConfiguration.getConfigProperties();
      }
      return super.getConfigProperties();
    }
  }

  /**
   * The singleton instance of the Boot class.
   */
  private static ClassicEngineBoot instance;
  /**
   * The project info contains all meta data about the project.
   */
  private ProjectInformation projectInfo;

  /**
   * Holds a possibly empty reference to a user-supplied Configuration implementation.
   */
  private static final UserConfigWrapper configWrapper =
      new UserConfigWrapper();

  /**
   * Creates a new instance.
   */
  private ClassicEngineBoot()
  {
    projectInfo = ClassicEngineInfo.getInstance();
  }

  /**
   * Returns the singleton instance of the boot utility class.
   *
   * @return the boot instance.
   */
  public static synchronized ClassicEngineBoot getInstance()
  {
    if (instance == null)
    {
      instance = new ClassicEngineBoot();
    }
    return instance;
  }

  /**
   * Returns the current global configuration as modifiable instance. This is exactly the same as casting the global
   * configuration into a ModifableConfiguration instance.
   * <p/>
   * This is a convinience function, as all programmers are lazy.
   *
   * @return the global config as modifiable configuration.
   */
  public ModifiableConfiguration getEditableConfig()
  {
    return (ModifiableConfiguration) getGlobalConfig();
  }

  /**
   * Returns the project info.
   *
   * @return The project info.
   */
  protected ProjectInformation getProjectInfo()
  {
    return projectInfo;
  }

  /**
   * Loads the configuration. This will be called exactly once.
   *
   * @return The configuration.
   */
  protected Configuration loadConfiguration()
  {

    final HierarchicalConfiguration globalConfig = new HierarchicalConfiguration(getClass());

    final PropertyFileConfiguration rootProperty = new PropertyFileConfiguration();
    rootProperty.load("/org/pentaho/reporting/engine/classic/core/classic-engine.properties", ClassicEngineBoot.class); // NON-NLS
    globalConfig.insertConfiguration(rootProperty);
    globalConfig.insertConfiguration(getPackageManager().getPackageConfiguration());

    try
    {
      final String userConfigStripped = "classic-engine.properties"; // NON-NLS
      final Enumeration userConfigs = ObjectUtilities.getClassLoader(ClassicEngineBoot.class).getResources(
          userConfigStripped);
      final ArrayList configs = new ArrayList();
      while (userConfigs.hasMoreElements())
      {
        final URL url = (URL) userConfigs.nextElement();
        try
        {
          final PropertyFileConfiguration baseProperty = new PropertyFileConfiguration();
          final InputStream in = url.openStream();
          try
          {
            baseProperty.load(in);
          }
          finally
          {
            in.close();
          }
          configs.add(baseProperty);
        }
        catch (IOException ioe)
        {
          logger.warn("Failed to load the user configuration at " + url, ioe); // NON-NLS
        }
      }

      for (int i = configs.size() - 1; i >= 0; i--)
      {
        final PropertyFileConfiguration baseProperty = (PropertyFileConfiguration) configs.get(i);
        globalConfig.insertConfiguration(baseProperty);
      }
    }
    catch (IOException e)
    {
      logger.warn("Failed to lookup the user configurations.", e); // NON-NLS
    }

    globalConfig.insertConfiguration(ClassicEngineBoot.configWrapper);

    final SystemPropertyConfiguration systemConfig = new SystemPropertyConfiguration();
    globalConfig.insertConfiguration(systemConfig);
    return globalConfig;
  }

  /**
   * Performs the actual boot process.
   */
  protected void performBoot()
  {
    if (ClassicEngineBoot.isStrictFP() == false)
    {
      ClassicEngineBoot.logger.warn("The used VM seems to use a non-strict floating point arithmetics"); // NON-NLS
      ClassicEngineBoot.logger.warn("Layouts computed with this Java Virtual Maschine may be invalid."); // NON-NLS
      ClassicEngineBoot.logger.warn("JFreeReport and the library 'iText' depend on the strict floating point rules"); // NON-NLS
      ClassicEngineBoot.logger.warn("of Java1.1 as implemented by the Sun Virtual Maschines."); // NON-NLS
      ClassicEngineBoot.logger.warn("If you are using the BEA JRockit VM, start the Java VM with the option"); // NON-NLS
      ClassicEngineBoot.logger.warn("'-Xstrictfp' to restore the default behaviour."); // NON-NLS
    }

    final PackageManager mgr = getPackageManager();

    mgr.addModule(ClassicEngineCoreModule.class.getName());
    mgr.load("org.pentaho.reporting.engine.classic.core.modules."); // NON-NLS
    mgr.load("org.pentaho.reporting.engine.classic.extensions.modules."); // NON-NLS
    mgr.load("org.pentaho.reporting.engine.classic.extensions.datasources."); // NON-NLS
    mgr.load("org.pentaho.reporting.engine.classic.core.userdefined.modules."); // NON-NLS

    bootAdditionalModules();
    mgr.initializeModules();

    if (mgr.isModuleAvailable(ClassicEngineCoreModule.class.getName()) == false)
    {
      throw new IllegalStateException("Booting the report-engine failed.");
    }

    StyleKey.lock();
  }

  /**
   * Boots modules, which have been spcified in the "org.pentaho.reporting.engine.classic.core.boot.Modules"
   * configuration parameter.
   */
  private void bootAdditionalModules()
  {
    try
    {
      final String bootModules =
          getGlobalConfig().getConfigProperty
              ("org.pentaho.reporting.engine.classic.core.boot.Modules"); // NON-NLS
      if (bootModules != null)
      {
        final CSVTokenizer csvToken = new CSVTokenizer(bootModules, ",");
        while (csvToken.hasMoreTokens())
        {
          final String token = csvToken.nextToken();
          getPackageManager().load(token);
        }
      }
    }
    catch (SecurityException se)
    {
      // we'll ignore any Security exception ..
      ClassicEngineBoot.logger.info("Security settings forbid to check the system properties for extension modules."); // NON-NLS
    }
    catch (Exception se)
    {
      ClassicEngineBoot.logger.error("An error occured while checking the system properties for extension modules.", // NON-NLS
          se);
    }
  }


  /**
   * This method returns true on non-strict floating point systems.
   * <p/>
   * Since Java 1.2 Virtual Maschines may implement the floating point arithmetics in a more performant way, which does
   * not put the old strict constraints on the floating point types <code>float</code> and <code>double</code>.
   * <p/>
   * As iText and this library requires strict (in the sense of Java1.1) floating point operations, we have to test for
   * that feature here.
   * <p/>
   * The only known VM that seems to implement that feature is the JRockit VM. The strict mode can be restored on that
   * VM by adding the "-Xstrictfp" VM parameter.
   *
   * @return true, if the VM uses strict floating points by default, false otherwise.
   */
  private static boolean isStrictFP()
  {
    final double d = 8.0e+307;
    final double result1 = 4.0 * d * 0.5;
    final double result2 = 2.0 * d;
    return (result1 != result2 && (result1 == Double.POSITIVE_INFINITY));
  }


  /**
   * Returns the user supplied global configuration.
   *
   * @return the user configuration, if any.
   */
  public static Configuration getUserConfig()
  {
    return configWrapper.getWrappedConfiguration();
  }

  /**
   * Defines the global user configuration.
   *
   * @param config the user configuration.
   */
  public static void setUserConfig(final Configuration config)
  {
    configWrapper.setWrappedConfiguration(config);
  }

  /**
   * A helper method that checks, whether a given module is available. The result of this method is undefined if the
   * system has no been booted yet.
   *
   * @param moduleClass the class-name of the module that should be tested.
   * @return true, if the module is available and has been initialized correctly, false otherwise.
   */
  public boolean isModuleAvailable(final String moduleClass)
  {
    return getPackageManager().isModuleAvailable
        (new DefaultModuleInfo(moduleClass, null, null, null));
  }
}
TOP

Related Classes of org.pentaho.reporting.engine.classic.core.ClassicEngineBoot$UserConfigWrapper

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.