org.porquebox.core.PorqueBoxMetaData.java Source code

Java tutorial

Introduction

Here is the source code for org.porquebox.core.PorqueBoxMetaData.java

Source

    /*
     * Copyright 2008-2013 Red Hat, Inc, and individual contributors.
     *
     * This 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 software 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.
     *
     * You should have received a copy of the GNU Lesser General Public
     * License along with this software; if not, write to the Free
     * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
     * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
     */

    package org.porquebox.core;

    import java.io.File;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Set;
    import java.util.Iterator;

    import org.jboss.logging.Logger;
    import org.jboss.as.server.deployment.AttachmentKey;
import org.apache.commons.configuration.HierarchicalINIConfiguration;;
    import org.apache.commons.configuration.Configuration;
    import org.apache.commons.configuration.SubnodeConfiguration;
    import org.porquebox.core.app.processors.ApplicationIniParsingProcessor;
    import org.porquebox.core.app.processors.PhpIniParsingProcessor;
    import org.porquebox.core.pool.processors.PoolingIniParsingProcessor;
    import org.porquebox.core.processors.PorqueBoxIniParsingProcessor;

    /**
     * Generalized opaque holder of <code>porquebox.ini</code>-specified metadata.
     *
     * <p>
     * Once <code>porquebox.yml</code> has been parsed, each top-level section and
     * its associated un-casted value block are added to the PorqueBoxMetaData for
     * use by other, more-specific deployment processors.
     * </p>
     *
     * @see PorqueBoxYamlParsingProcessor
     * @see RubyYamlParsingProcessor
     * @see ApplicationYamlParsingProcessor
     * @see PoolingYamlParsingProcessor
     */
    public class PorqueBoxMetaData {

        public static final AttachmentKey<PorqueBoxMetaData> ATTACHMENT_KEY = AttachmentKey
                .create(PorqueBoxMetaData.class);

        private Map<String, Object> data = new HashMap<String, Object>();

        /**
         * Construct with parsed INI results.
         *
         * @param data The data, keyed by section name.
         */
        public PorqueBoxMetaData(Map<String, Object> data) {
            this.data = normalizeSectionNames(data);
        }

        public PorqueBoxMetaData(HierarchicalINIConfiguration data) {
            for (String sectionName : data.getSections()) {
                SubnodeConfiguration section = data.getSection(sectionName);
                Map<String, String> sectionData = new HashMap<String, String>();
                for (Iterator<String> keyIter = section.getKeys(); keyIter.hasNext();) {
                    String key = keyIter.next();
                    String value = (String) section.getProperty(key);
                    sectionData.put(key, value);
                }
                this.data.put(sectionName, (Object) sectionData);
            }
        }

        /**
         * Normalize section names, since some drift has occurred.
         *
         * @param data
         * @return
         */
        private Map<String, Object> normalizeSectionNames(Map<String, Object> data) {
            Map<String, Object> normalized = new HashMap<String, Object>();

            Set<String> keys = data.keySet();

            for (String key : keys) {
                normalized.put(normalizeSectionName(key), data.get(key));
            }
            return normalized;
        }

        private String normalizeSectionName(String name) {
            if (name.equalsIgnoreCase("app")) {
                return "application";
            }

            return name.toLowerCase();
        }

        public Object getSection(String name) {
            return this.data.get(normalizeSectionName(name));
        }

        @SuppressWarnings("unchecked")
        public String getApplicationRoot() {
            return findApplicationRoot((Map<String, String>) getSection("application"));
        }

        public static String findApplicationRoot(Map<String, String> section) {
            if (section != null) {
                return getOneOf(section, "root", "RAILS_ROOT", "RACK_ROOT");
            }
            return null;
        }

        public static File findApplicationRootFile(Map<String, String> section) {
            String path = findApplicationRoot(section);

            if (path == null) {
                return null;
            }

            if (path.startsWith("~")) {
                path = System.getProperty("user.home") + path.substring(1);
            }
            return new File(path);
        }

        @SuppressWarnings("unchecked")
        public File getApplicationRootFile() {
            return findApplicationRootFile((Map<String, String>) getSection("application"));
        }

        @SuppressWarnings("unchecked")
        public String getApplicationEnvironment() {
            return findApplicationEnvironment((Map<String, String>) getSection("application"));
        }

        public static String findApplicationEnvironment(Map<String, String> section) {
            if (section != null) {
                return getOneOf(section, "env", "RAILS_ENV", "RACK_ENV");
            }
            return null;
        }

        protected static String getOneOf(Map<String, String> map, String... keys) {
            for (String each : keys) {
                for (String key : map.keySet()) {
                    if (each.equalsIgnoreCase(key)) {
                        return map.get(key);
                    }
                }
            }
            return null;
        }

        protected String determineEnvironmentKey(Map<String, String> section) {
            if (section.containsKey("RAILS_ENV")) {
                return "RAILS_ENV";
            }

            if (section.containsKey("RACK_ENV")) {
                return "RACK_ENV";
            }

            return "env";
        }

        protected String determineRootKey(Map<String, String> section) {
            if (section.containsKey("RAILS_ROOT")) {
                return "RAILS_ROOT";
            }

            if (section.containsKey("RACK_ROOT")) {
                return "RACK_ROOT";
            }

            return "root";
        }

        @SuppressWarnings("unchecked")
        public PorqueBoxMetaData overlayOnto(PorqueBoxMetaData baseMetaData) {
            Map<String, Object> thisData = this.data;
            Map<String, Object> baseData = baseMetaData.data;

            Map<String, Object> mergedData = new HashMap<String, Object>();
            mergedData.putAll(baseData);

            for (String key : thisData.keySet()) {
                if (key.equals("application")) {
                    // From the application: section, only overly
                    // env/RACK_ENV/RAILS_ENV and do it smartly using
                    // whatever key(s) are in use by the base and overlay
                    // data maps.

                    Map<String, String> thisAppSection = (Map<String, String>) thisData.get("application");
                    String envKey = determineEnvironmentKey(thisAppSection);
                    String envName = thisAppSection.get(envKey);

                    if (envName != null && !envName.trim().equals("")) {
                        Map<String, String> mergedAppSection = (Map<String, String>) mergedData.get("application");

                        if (mergedAppSection == null) {
                            mergedAppSection = new HashMap<String, String>();
                            mergedData.put("application", mergedAppSection);
                        }

                        envKey = determineEnvironmentKey(mergedAppSection);
                        mergedAppSection.put(envKey, envName);
                    }

                } else {
                    mergedData.put(key, merge(key, thisData, baseData));
                }
            }

            return new PorqueBoxMetaData(mergedData);
        }

        @SuppressWarnings({ "rawtypes", "unchecked" })
        protected Object merge(Object key, Map src, Map tgt) {
            Object value = src.get(key);
            if (value instanceof Map && tgt != null) {
                Map source = (Map) value;
                Object target = tgt.get(key);
                if (target != null) {
                    Map result = new HashMap((Map) target);
                    for (Object k : source.keySet()) {
                        result.put(k, merge(k, source, result));
                    }
                    return result;
                }
            }
            return value;
        }

        public void validate() throws Exception {
            //schema.validate( this.data, false );
            // TODO: Validate the ini file.
        }

        public String toString() {
            return "[PorqueBoxMetaData: data=" + this.data + "]";
        }

        static final Logger log = Logger.getLogger("org.porquebox.core");
    }