Java tutorial
/* * 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"); }