Package org.apache.cocoon.spring.configurator.impl

Source Code of org.apache.cocoon.spring.configurator.impl.SettingsBeanFactoryPostProcessor

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cocoon.spring.configurator.impl;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Properties;

import org.apache.cocoon.configuration.MutableSettings;
import org.apache.cocoon.configuration.Settings;
import org.apache.cocoon.configuration.SettingsDefaults;
import org.apache.cocoon.spring.configurator.ResourceUtils;

/**
* This is a bean factory post processor which handles all the settings stuff for Cocoon. It reads
* in all properties files and replaces references to them in the spring configuration files. In
* addition this bean acts as a factory bean providing the settings object.
*
* <p>
* The settings object is created by reading several property files and merging of the values. If
* there is more than one definition for a property, the last one wins. The property files are read
* in the following order:
* <ol>
* <li>If {@link #readFromClasspath} is true: classpath*:/META-INF/cocoon/properties/*.properties
* Default values for the core and each block - the files are read in alphabetical order. Actually
* the files are read in two chunks, the first one containing all property files from jar files, and
* the second one containing all property files from WEB-INF/classes.
* <li>If {@link #readFromClasspath} is true:
* classpath*:/META-INF/cocoon/properties/[RUNNING_MODE]/*.properties Default values for the core
* and each block for a specific running mode - the files are read in alphabetical order. Actually
* the files are read in two chunks, the first one containing all property files from jar files, and
* the second one containing all property files from WEB-INF/classes.
* <li>If {@link #readFromGlobalLocation} is true: /WEB-INF/cocoon/properties/*.properties Default
* values for the core and each block - the files are read in alphabetical order. Actually the files
* are read in two chunks, the first one containing all property files from jar files, and the
* second one containing all property files from WEB-INF/classes.
* <li>If {@link #readFromGlobalLocation} is true:
* /WEB-INF/cocoon/properties/[RUNNING_MODE]/*.properties Default values for the core and each block
* for a specific running mode - the files are read in alphabetical order. Actually the files are
* read in two chunks, the first one containing all property files from jar files, and the second
* one containing all property files from WEB-INF/classes.
* <li>Working directory from servlet context (if not already set)
* <li>Optional property file which is stored under ".cocoon/settings.properties" in the user
* directory.
* <li>Additional property file specified by the "org.apache.cocoon.settings" property. If the
* property defines a directory, all property files from this directory are read in alphabetical
* order and all files from a sub directory with the name of the current running mode are read in
* alphabetical order as well.
* <li>Property provider (if configured in the bean factory)
* <li>Add properties from configured directories {@link #directories}.
* <li>Add additional properties configured at {@link #additionalProperties}
* <li>System properties
* </ol>
*
* This means that system properties (provided on startup of the web application) override all
* others etc.
*
* @since 1.0
* @version $Id: SettingsBeanFactoryPostProcessor.java 754971 2009-03-16 18:18:53Z reinhard $
*/
public class SettingsBeanFactoryPostProcessor extends AbstractSettingsBeanFactoryPostProcessor {

    /**
     * The running mode for the web application.
     */
    protected String runningMode = SettingsDefaults.DEFAULT_RUNNING_MODE;

    /**
     * Should we read the properties from the classpath?
     *
     * @see Constants#CLASSPATH_PROPERTIES_LOCATION
     */
    protected boolean readFromClasspath = true;

    /**
     * Should we read the properties from the global location?
     *
     * @see Constants#GLOBAL_PROPERTIES_LOCATION
     */
    protected boolean readFromGlobalLocation = true;

    /**
     * Set the running mode.
     *
     * @param mode The new running mode.
     */
    public void setRunningMode(String mode) {
        this.runningMode = mode;
    }

    /**
     * Set if we read property configurations from the classpath.
     *
     * @param readFromClasspath
     */
    public void setReadFromClasspath(boolean readFromClasspath) {
        this.readFromClasspath = readFromClasspath;
    }

    /**
     * Set if we read property configurations from the global location.
     */
    public void setReadFromGlobalLocation(boolean readFromGlobalLocation) {
        this.readFromGlobalLocation = readFromGlobalLocation;
    }

    /**
     * Initialize this processor. Setup the settings object.
     *
     * @throws Exception
     */
    @Override
    public void init() throws Exception {
        // get the running mode
        final String mode = this.getRunningMode();
        RunningModeHelper.checkRunningMode(mode);

        // print out version information
        final Properties pomProps = ResourceUtils.getPOMProperties("org.apache.cocoon", "cocoon-spring-configurator");
        final String version;
        if (pomProps != null) {
            version = pomProps.getProperty("version");
        } else {
            version = null;
        }

        // give a startup message
        final String msg = "Apache Cocoon Spring Configurator " + (version != null ? "v" + version + " " : "")
                + "is running in mode '" + mode + "'.";
        if (this.servletContext != null) {
            this.servletContext.log(msg);
        } else {
            this.logger.info(msg);
        }

        // first we dump the system properties
        this.dumpSystemProperties();

        // now create the settings object
        super.init();

        // finally pre load classes
        this.forceLoad();
    }

    /**
     * @see org.apache.cocoon.spring.configurator.impl.AbstractSettingsBeanFactoryPostProcessor#getRunningMode()
     */
    @Override
    protected String getRunningMode() {
        return RunningModeHelper.determineRunningMode(this.runningMode);
    }

    @Override
    protected void preInit(final MutableSettings s, final Properties properties) {
        final String mode = this.getRunningMode();
        if (this.readFromClasspath) {
            // now read all properties from classpath directory
            ResourceUtils.readProperties(Constants.CLASSPATH_PROPERTIES_LOCATION, properties, this.getResourceLoader(),
                    this.resourceFilter, this.logger);
            // read all properties from the mode dependent directory
            ResourceUtils.readProperties(Constants.CLASSPATH_PROPERTIES_LOCATION + "/" + mode, properties, this
                    .getResourceLoader(), this.resourceFilter, this.logger);
        }

        if (this.readFromGlobalLocation) {
            // now read all properties from the properties directory
            ResourceUtils.readProperties(Constants.GLOBAL_PROPERTIES_LOCATION, properties, this.getResourceLoader(),
                    this.resourceFilter, this.logger);
            // read all properties from the mode dependent directory
            ResourceUtils.readProperties(Constants.GLOBAL_PROPERTIES_LOCATION + "/" + mode, properties, this
                    .getResourceLoader(), this.resourceFilter, this.logger);
        }

        // set default work directory value
        if (s.getWorkDirectory() == null) {
            File workDir;
            // fill from the servlet context
            if (this.servletContext != null) {
                workDir = (File) this.servletContext.getAttribute("javax.servlet.context.tempdir");
            } else {
                workDir = new File("cocoon-files");
            }
            s.setWorkDirectory(workDir.getAbsolutePath());
        }

        // set default cache directory value
        if (s.getCacheDirectory() == null) {
            s.setCacheDirectory(new File(s.getWorkDirectory(), "cache-dir").getAbsolutePath());
        }

        // read additional properties file
        // first try in home directory
        final String homeDir = this.getSystemProperty("user.home");
        if (homeDir != null) {
            final String fileName = homeDir + File.separator + ".cocoon" + File.separator + "settings.properties";
            final File testFile = new File(fileName);
            if (testFile.exists()) {
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Reading user settings from '" + fileName + "'");
                }
                try {
                    final FileInputStream fis = new FileInputStream(fileName);
                    try {
                        properties.load(fis);
                    } finally {
                        try {
                            fis.close();
                        } catch (IOException ioe) {
                            this.logger.warn("Failed to close FileInputStream:", ioe);
                        }
                    }
                } catch (IOException ignore) {
                    this.logger.info("Unable to read '" + fileName + "' - continuing with initialization.", ignore);
                }
            }
        }

        // check for additionally specified custom file:
        // 1. bean attribute
        // 2. servletContext init parameter
        // 3. system property
        String additionalPropertyFile = s.getProperty(Settings.PROPERTY_USER_SETTINGS, this
                .getServletContextInitParameter(Settings.PROPERTY_USER_SETTINGS, this
                        .getSystemProperty(Settings.PROPERTY_USER_SETTINGS)));
        if (additionalPropertyFile != null) {
            if (this.logger.isDebugEnabled()) {
                this.logger.debug("Reading user settings from '" + additionalPropertyFile + "'");
            }
            final File additionalFile = new File(additionalPropertyFile);
            if (additionalFile.exists()) {
                if (additionalFile.isDirectory()) {
                    // read from directory
                    ResourceUtils.readProperties(additionalFile.getAbsolutePath(), properties,
                            this.getResourceLoader(), this.resourceFilter, this.logger);
                    // read all properties from the mode dependent directory
                    ResourceUtils.readProperties(additionalFile.getAbsolutePath() + File.separatorChar + mode,
                            properties, this.getResourceLoader(), this.resourceFilter, this.logger);
                } else {
                    // read the file
                    try {
                        final FileInputStream fis = new FileInputStream(additionalFile);
                        properties.load(fis);
                        fis.close();
                    } catch (IOException ignore) {
                        this.logger.info("Unable to read '" + additionalPropertyFile
                                + "' - continuing with initialization.", ignore);
                    }
                }
            } else {
                this.logger.info("Additional settings file '" + additionalPropertyFile
                        + "' does not exist - continuing with initialization.");
            }
        }
    }

    protected String getServletContextInitParameter(String key, String defaultValue) {
        if (this.servletContext == null) {
            return defaultValue;
        }

        String servletContextSettings = this.servletContext.getInitParameter(key);

        if (servletContextSettings == null || "".equals(servletContextSettings)) {
            return defaultValue;
        }

        return servletContextSettings;
    }

    @Override
    protected MutableSettings createSettings() {
        final MutableSettings s = super.createSettings();

        // first init the work-directory for the logger.
        // this is required if we are running inside a war file!
        File workDir = new File(s.getWorkDirectory());
        workDir.mkdirs();
        if (this.logger.isDebugEnabled()) {
            this.logger.debug("Using work-directory " + workDir);
        }

        File cacheDir = new File(s.getCacheDirectory());
        cacheDir.mkdirs();
        if (this.logger.isDebugEnabled()) {
            this.logger.debug("Using cache-directory " + cacheDir);
        }

        return s;
    }

    /**
     * Dump System Properties.
     */
    protected void dumpSystemProperties() {
        if (this.logger.isDebugEnabled()) {
            try {
                Enumeration e = System.getProperties().propertyNames();
                this.logger.debug("===== System Properties Start =====");
                while (e.hasMoreElements()) {
                    String key = (String) e.nextElement();
                    this.logger.debug(key + "=" + System.getProperty(key));
                }
                this.logger.debug("===== System Properties End =====");
            } catch (SecurityException se) {
                // Ignore Exceptions.
            }
        }
    }

    /**
     * Handle the <code>load-class</code> settings. This overcomes limits in many classpath issues.
     * One of the more notorious ones is a bug in WebSphere that does not load the URL handler for
     * the <code>classloader://</code> protocol. In order to overcome that bug, set
     * <code>org.apache.cocoon.classloader.load.classes.XY</code> property to the
     * <code>com.ibm.servlet.classloader.Handler</code> value.
     *
     * <p>
     * If you need to load more than one class, then add several properties, all starting with
     * <cod>org.apache.cocoon.classloader.load.classes.</code> followed by a self defined
     * identifier.
     * </p>
     */
    protected void forceLoad() {
        final Iterator i = this.settings.getLoadClasses().iterator();
        while (i.hasNext()) {
            final String fqcn = (String) i.next();
            try {
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Loading class: " + fqcn);
                }
                Thread.currentThread().getContextClassLoader().loadClass(fqcn).newInstance();
            } catch (Exception e) {
                if (this.logger.isWarnEnabled()) {
                    this.logger.warn("Could not load class: " + fqcn + ". Continuing initialization.", e);
                }
                // Do not throw an exception, because it is not a fatal error.
            }
        }
    }
}
TOP

Related Classes of org.apache.cocoon.spring.configurator.impl.SettingsBeanFactoryPostProcessor

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.