org.tolven.plugin.repository.ConfigPluginsWrapper.java Source code

Java tutorial

Introduction

Here is the source code for org.tolven.plugin.repository.ConfigPluginsWrapper.java

Source

/*
 * Copyright (C) 2009 Tolven Inc
    
 * This library is free software; you can redistribute it and/or modify it under the terms of 
 * the GNU Lesser General Public License as published by the Free Software Foundation; either 
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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.
 *
 * Contact: info@tolvenhealth.com 
 *
 * @author Joseph Isaac
 * @version $Id$
 */
package org.tolven.plugin.repository;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;

import org.apache.commons.io.FileUtils;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Logger;
import org.apache.log4j.helpers.Loader;
import org.apache.log4j.xml.DOMConfigurator;
import org.tolven.plugin.repository.bean.PluginDetail;
import org.tolven.plugin.repository.bean.PluginPropertyDetail;
import org.tolven.plugin.repository.bean.Plugins;
import org.tolven.plugin.repository.el.ExpressionEvaluator;

/**
 * This class acts as a wrapper for the JAXB Plugins class.
 * 
 * @author Joseph Isaac
 *
 */
public class ConfigPluginsWrapper {

    public static final String CONFIG_DIR = "config.dir";
    public static final String BUILD_DIR = "build";
    public static final String REPOSITORY_LIBRARY = "repositoryLibrary";
    public static final String REPOSITORY_TRUNK_METADATA = "trunkMetadata";
    public static final String REPOSITORY_SNAPSHOT_METADATA = "snapshotMetadata";
    public static final String USE_SNAPSHOT = "useSnapshot";
    public static final String OVERWRITE_SNAPSHOT = "overwriteSnapshot";
    public static final String REPOSITORY_DEVLIB = "repositoryDevLib";
    public static final String REPOSITORY_RUNTIME = "repositoryRuntime";
    public static final String REPOSITORY_RUNTIME_UNPACKED = "repositoryRuntimeUnpacked";
    public static final String REPOSITORY_STAGE = "repositoryStage";
    public static final String REPOSITORY_TMP = "repositoryTmp";
    public static final String LOG4JCONFIGURATION = "log4JConfiguration";
    public static final String LOGFILE = "logFile";
    public static final String LIBRARY_PLUGS_DIR = "plugins";
    public static final String INSTALL_DIR = "installation.dir";

    public static final String DEFAULT_LOG_FILE = System.getProperty("user.dir") + "/tolven.log";
    public static final String LOG_FILE_PROPERTY = "tolven.log.file";

    private File pluginsFile;
    private Plugins plugins;
    private ExpressionEvaluator ee;
    private Logger logger = Logger.getLogger(ConfigPluginsWrapper.class);
    private Map<String, Map<String, String>> pluginPropertyMap = new HashMap<String, Map<String, String>>();

    public ConfigPluginsWrapper() {
    }

    public File getPluginsFile() {
        return pluginsFile;
    }

    public void setPluginsFile(File pluginsFile) {
        this.pluginsFile = pluginsFile;
    }

    public Plugins getPlugins() {
        return plugins;
    }

    public void setPlugins(Plugins plugins) {
        this.plugins = plugins;
    }

    private String getProperty(String name) {
        return getProperty(name, null);
    }

    private String getProperty(String name, String defaultValue) {
        for (PluginPropertyDetail pluginProperty : getPlugins().getProperty()) {
            if (pluginProperty.getName().equals(name)) {
                return pluginProperty.getValue();
            }
        }
        return defaultValue;
    }

    public PluginPropertyDetail getPluginProperty(String name) {
        for (PluginPropertyDetail pluginProperty : getPlugins().getProperty()) {
            if (pluginProperty.getName().equals(name)) {
                return pluginProperty;
            }
        }
        return null;
    }

    public File getConfigDir() {
        String value = getProperty(CONFIG_DIR);
        if (value == null) {
            throw new RuntimeException("Plugin property " + CONFIG_DIR + " is not defined");
        }
        value = (String) evaluate(value);
        return new File(value);
    }

    public File getInstallDir() {
        String value = getProperty(INSTALL_DIR);
        if (value == null) {
            throw new RuntimeException("Plugin property " + INSTALL_DIR + " is not defined");
        }
        value = (String) evaluate(value);
        return new File(value);
    }

    public File getBuildDir() {
        return new File(getConfigDir(), BUILD_DIR);
    }

    public File getRepositoryRuntimeDir() {
        String value = getProperty(REPOSITORY_RUNTIME);
        if (value == null) {
            throw new RuntimeException("Plugin property " + REPOSITORY_RUNTIME + " is not defined");
        }
        value = (String) evaluate(value);
        return new File(value);
    }

    public File getRepositoryRuntimePluginsDir() {
        String value = getProperty(REPOSITORY_RUNTIME);
        if (value == null) {
            throw new RuntimeException("Plugin property " + REPOSITORY_RUNTIME + " is not defined");
        }
        value = (String) evaluate(value);
        return new File(getRepositoryRuntimeDir(), LIBRARY_PLUGS_DIR);
    }

    public File getRepositoryRuntimeUnpackedDir() {
        String value = getProperty(REPOSITORY_RUNTIME_UNPACKED);
        if (value == null) {
            throw new RuntimeException("Plugin property " + REPOSITORY_RUNTIME_UNPACKED + " is not defined");
        }
        value = (String) evaluate(value);
        return new File(value);
    }

    public File getRepositoryTmpDir() {
        String value = getProperty(REPOSITORY_TMP);
        if (value == null) {
            throw new RuntimeException("Plugin property " + REPOSITORY_TMP + " is not defined");
        }
        value = (String) evaluate(value);
        return new File(value);
    }

    public File getRepositoryStageDir() {
        String value = getProperty(REPOSITORY_STAGE);
        if (value == null) {
            throw new RuntimeException("Plugin property " + REPOSITORY_STAGE + " is not defined");
        }
        value = (String) evaluate(value);
        return new File(value);
    }

    public File getRepositoryDevLibDir() {
        String value = getProperty(REPOSITORY_DEVLIB);
        if (value == null) {
            throw new RuntimeException("Plugin property " + REPOSITORY_DEVLIB + " is not defined");
        }
        value = (String) evaluate(value);
        return new File(value);
    }

    public PluginPropertyDetail getRepositoryLibrary() {
        PluginPropertyDetail pluginProperty = getPluginProperty(REPOSITORY_LIBRARY);
        if (pluginProperty == null) {
            throw new RuntimeException("Plugin property " + REPOSITORY_LIBRARY + " is not defined");
        } else {
            return pluginProperty;
        }
    }

    public File getLog4JConfiguration() {
        String value = getProperty(LOG4JCONFIGURATION);
        if (value == null) {
            throw new RuntimeException("Plugin property " + LOG4JCONFIGURATION + " is not defined");
        }
        value = (String) evaluate(value);
        return new File(value);
    }

    public File getLogFile() {
        String value = getProperty(LOGFILE);
        if (value == null) {
            throw new RuntimeException("Plugin property " + LOGFILE + " is not defined");
        }
        value = (String) evaluate(value);
        return new File(value);
    }

    public String evaluate(String aString) {
        return (String) ee.evaluate(aString);
    }

    public String evaluate(String aString, String pluginId) {
        ee.pushContext();
        ee.addVariable("pluginProperty", pluginPropertyMap.get(pluginId));
        String value = aString;
        int count = 0;
        do {
            value = (String) ee.evaluate(value);
            //TODO cheap loop detection
            if (value == null || count++ > 10) {
                break;
            }
        } while (value.contains("#{"));
        ee.popContext();
        return value;
    }

    public void loadConfigDir(File configDir) {
        if (!configDir.exists()) {
            throw new RuntimeException("Could not find the configuration directory: " + configDir.getPath());
        }
        setPluginsFile(new File(configDir, RepositoryMetadata.METADATA_XML));
        load(getPluginsFile());
        if (!configDir.equals(getConfigDir())) {
            throw new RuntimeException(CONFIG_DIR + " plugins file property " + getConfigDir().getPath()
                    + " does not match load directory: " + getConfigDir().getPath());
        }
        File log4JConfiguration = getLog4JConfiguration();
        if (!log4JConfiguration.getPath().equals(log4JConfiguration.getAbsolutePath())) {
            log4JConfiguration = new File(System.getProperty("user.dir"), log4JConfiguration.getName());
        }
        File logFile = getLogFile();
        if (!logFile.getPath().equals(logFile.getAbsolutePath())) {
            logFile = new File(System.getProperty("user.dir"), logFile.getName());
        }
        initialize(log4JConfiguration.getPath(), logFile);
    }

    public void storeMetadata(File pluginsXMLFile) {
        logger.info("Write Runtime plugins metadata to " + pluginsXMLFile);
        try {
            FileUtils.writeStringToFile(pluginsXMLFile, RepositoryMetadata.getPluginsXML(getPlugins()));
        } catch (IOException ex) {
            throw new RuntimeException("Could not write runtime plugins to: " + pluginsXMLFile, ex);
        }
    }

    public void load(File pluginsFile) {
        //Do not add any logger statements at this point, because the pluginsFile contains information
        //about the log4JConfiguration and logFile, so the log4j is still uninitialized
        FileInputStream fis = null;
        try {
            try {
                fis = new FileInputStream(pluginsFile);
                loadPlugins(fis);
            } finally {
                if (fis != null)
                    fis.close();
            }
        } catch (IOException ex) {
            throw new RuntimeException("Could not load plugins from " + pluginsFile.getPath(), ex);
        }
    }

    /**
     * Unmarshall a Plugins from an InputStream
     * @param xsdStream
     * @return
     */
    public Plugins loadPlugins(InputStream xsdStream) {
        try {
            JAXBContext jc = JAXBContext.newInstance(RepositoryMetadata.PLUGINS_PACKAGE,
                    ClassLoader.getSystemClassLoader());
            Unmarshaller u = jc.createUnmarshaller();
            setPlugins((Plugins) u.unmarshal(xsdStream));
            validate();
            ee = new ExpressionEvaluator();
            Map<String, String> globalPropertyMap = new HashMap<String, String>();
            for (PluginPropertyDetail globalProperty : getPlugins().getProperty()) {
                globalPropertyMap.put(globalProperty.getName(), globalProperty.getValue());
            }
            ee.addVariable("globalProperty", globalPropertyMap);
            for (PluginDetail plugin : getPlugins().getPlugin()) {
                Map<String, String> pMap = new HashMap<String, String>();
                for (PluginPropertyDetail pluginProperty : plugin.getProperty()) {
                    updatePropertyMap(pMap, pluginProperty);
                }
                pluginPropertyMap.put(plugin.getId(), pMap);
            }
            return getPlugins();
        } catch (JAXBException ex) {
            throw new RuntimeException("Could not load plugins inputstream", ex);
        }
    }

    /**
     * Update properties map for property and any child properties
     * 
     * @param pMap
     * @param property
     */
    private void updatePropertyMap(Map<String, String> pMap, PluginPropertyDetail property) {
        pMap.put(property.getName(), property.getValue());
        Collection<PluginPropertyDetail> childProperties = property.getProperty();
        if (childProperties.isEmpty()) {
            return;
        }
        for (PluginPropertyDetail pluginProperty : childProperties) {
            updatePropertyMap(pMap, pluginProperty);
        }
    }

    private void validate() {
        //Check for duplicates
        Set<String> pluginIds = new HashSet<String>();
        for (PluginDetail plugin : getPlugins().getPlugin()) {
            if (pluginIds.contains(plugin.getId())) {
                throw new RuntimeException(
                        plugin.getId() + " has a duplicate entry in " + getPluginsFile().getPath());
            } else {
                pluginIds.add(plugin.getId());
            }
        }
    }

    public static void initialize(String log4jConfiguration, File logFile) {
        try {
            File configFile = new File(log4jConfiguration);
            initialize(configFile.toURI().toURL().toExternalForm(), logFile.getPath());
        } catch (MalformedURLException e) {
            throw new RuntimeException("Could not convert logFile: '" + logFile.getPath() + "' to a URI");
        }
    }

    /**
     * <p>Initialize log4j logging using the Tolven appender specification.</p>
     * <p>Note: This method should <i>not</i> be called within an environment such as JBoss that has a separate
     * log4j configuration.</p>
     * @param log4jConfiguration The name of the file containing the log4j configuration. If null, the
     * a file named tolven-log4j.xml on the classpath will be used.
     * @param logFilename The name of the log file. This file will be created if it does not already exist. If null, 
     * a default file named <code>${user.dir}/tolven.log</code> will be used.
     */
    public static void initialize(String log4jConfiguration, String logFilename) {
        try {
            File logFile;
            if (logFilename != null) {
                logFile = new File(logFilename);
            } else {
                logFile = new File(DEFAULT_LOG_FILE);
            }
            System.setProperty(LOG_FILE_PROPERTY, logFile.getAbsolutePath());
            logFile.getParentFile().mkdirs();
            logFile.createNewFile();
            BasicConfigurator.configure();
            Logger.getRootLogger().info("Start log4j - Configuration: " + log4jConfiguration + ", logFileName: "
                    + logFile.getAbsolutePath());
            BasicConfigurator.resetConfiguration();
            URL configURL;
            try {
                configURL = new URL(log4jConfiguration);
            } catch (Exception e) {
                configURL = Loader.getResource(log4jConfiguration);
            }
            DOMConfigurator.configure(configURL);
        } catch (Exception e) {
            throw new RuntimeException("Exception while initializing Tolven log4j. log4jConfiguration: "
                    + log4jConfiguration + " logFilename: " + logFilename, e);
        }
    }

}