/* * Copyright 2014-15 Skynav, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY SKYNAV, INC. AND ITS CONTRIBUTORS “AS IS” AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL SKYNAV, INC. OR ITS CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.skynav.ttv.util; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.net.URL; import java.util.Map; import javax.xml.namespace.QName; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.TransformerFactoryConfigurationError; import javax.xml.transform.dom.DOMResult; import javax.xml.transform.sax.SAXSource; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.xml.sax.InputSource; import com.skynav.ttv.app.Namespace; import com.skynav.xml.helpers.Documents; public class Configuration { public static final String defaultFileName = "config.xml"; private static final QName optionEltName = new QName(Namespace.NAMESPACE, "option"); private ConfigurationDefaults defaults; private Map<String,String> options; public Configuration() { this(new ConfigurationDefaults()); } public Configuration(ConfigurationDefaults defaults) { this(defaults, null); } public Configuration(ConfigurationDefaults defaults, Document d) { if (defaults == null) throw new IllegalArgumentException(); this.defaults = defaults; populate(d); } protected void populate(Document d) { populateOptions(d); } private void populateOptions(Document d) { Map<String,String> options = new java.util.HashMap<String,String>(); if (defaults != null) defaults.populateDefaults(options); if (d != null) { for (Element e : Documents.findElementsByName(d, optionEltName)) { if (e.hasAttribute("name")) { String n = e.getAttribute("name"); String v = performVariableSubstitution(e.getTextContent()); options.put(n, v); } } } this.options = options; } private String performVariableSubstitution(String s) { if (maybeHasVariable(s)) { StringBuffer sb = new StringBuffer(); for (int i = 0, n = s.length(); i < n;) { int c0 = s.charAt(i++); if (c0 == '$') { if (i < n) { int c1 = s.charAt(i++); if (c1 == '{') { int j = s.indexOf('}', i); if (j >= i) { String name = s.substring(i, j); String value = getVariable(name); if (value != null) sb.append(value); else { sb.append("${"); sb.append(s.substring(i, j + 1)); } i = j + 1; } else { sb.append("${"); sb.append(s.substring(i)); i = n; } } else { sb.append((char) c0); sb.append((char) c1); } } } else sb.append((char) c0); } return sb.toString(); } else return s; } private boolean maybeHasVariable(String s) { return s.indexOf("${") >= 0; } private String getVariable(String name) { if (name.equals("configdir")) { return defaults.getConfigurationDirectory(); } else return null; } public URL getLocator() { return (defaults != null) ? defaults.getConfigurationLocator() : null; } public Map<String,String> getOptions() { return options; } public String getOption(String name) { return getOption(name, getOptionDefault(name)); } public String getOption(String name, String optionDefault) { if (options.containsKey(name)) return options.get(name); else return optionDefault; } public String getOptionDefault(String name) { return (defaults != null) ? defaults.getDefault(name) : null; } public static Configuration fromLocator(URL locator, ConfigurationDefaults defaults, Class<? extends Configuration> cls, Reporter reporter) throws IOException { try { return (locator != null) ? fromStream(locator.openStream(), defaults, cls, reporter) : null; } catch (IOException e) { reporter.logError(e); return null; } } public static Configuration fromStream(InputStream is, ConfigurationDefaults defaults, Class<? extends Configuration> cls, Reporter reporter) throws IOException { try { SAXSource source = new SAXSource(new InputSource(is)); DOMResult result = new DOMResult(); TransformerFactory.newInstance().newTransformer().transform(source, result); return newInstance(cls, defaults, (Document) result.getNode(), reporter); } catch (TransformerFactoryConfigurationError e) { reporter.logError(new RuntimeException(e)); return null; } catch (TransformerException e) { reporter.logError(e); return null; } } public static Configuration newInstance(Class<? extends Configuration> cls, ConfigurationDefaults defaults, Document d, Reporter reporter) { if (cls != null) { try { Constructor<? extends Configuration> constructor = cls.getDeclaredConstructor(new Class<?>[] { ConfigurationDefaults.class, Document.class }); return constructor.newInstance(new Object[] { defaults, d }); } catch (NoSuchMethodException e) { reporter.logError(e); return null; } catch (IllegalAccessException e) { reporter.logError(e); return null; } catch (InvocationTargetException e) { reporter.logError(e); return null; } catch (InstantiationException e) { reporter.logError(e); return null; } } else return null; } public static URL getDefaultConfigurationLocator(Class<?> cls, String name) { if (name == null) name = defaultFileName; ClassLoader loader = cls.getClassLoader(); if (loader == null) loader = ClassLoader.getSystemClassLoader(); Package pkg = cls.getPackage(); String path = (pkg != null) ? pkg.getName().replace('.','/') : null; if (path != null) path = path + "/" + name; else path = name; return loader.getResource(path); } }