001/* 002 * jPOS Project [http://jpos.org] 003 * Copyright (C) 2000-2026 jPOS Software SRL 004 * 005 * This program is free software: you can redistribute it and/or modify 006 * it under the terms of the GNU Affero General Public License as 007 * published by the Free Software Foundation, either version 3 of the 008 * License, or (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 013 * GNU Affero General Public License for more details. 014 * 015 * You should have received a copy of the GNU Affero General Public License 016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 017 */ 018 019package org.jpos.q2; 020 021import java.io.File; 022import java.io.FileInputStream; 023import java.io.IOException; 024import java.io.InputStream; 025import java.util.ArrayList; 026import java.util.List; 027import java.util.Map; 028import java.util.Properties; 029 030import org.jdom2.Element; 031import org.jpos.core.Configuration; 032import org.jpos.core.ConfigurationException; 033import org.jpos.core.Environment; 034import org.jpos.core.SimpleConfiguration; 035import org.jpos.iso.ISOUtil; 036import org.yaml.snakeyaml.Yaml; 037 038public class SimpleConfigurationFactory implements ConfigurationFactory { 039 @Override 040 public Configuration getConfiguration(Element e) throws ConfigurationException { 041 Properties props = new Properties(); 042 for (Element property : e.getChildren("property")) { 043 String name = property.getAttributeValue("name"); 044 String value = property.getAttributeValue("value"); 045 String baseFile = property.getAttributeValue("file"); 046 if (baseFile != null) { 047 boolean isEnv = Boolean.parseBoolean(property.getAttributeValue("env", "false")); 048 processFile(props, baseFile, isEnv); 049 } else if (name != null && value != null) { 050 processProperty(props, name, value); 051 } 052 } 053 return new SimpleConfiguration(props); 054 } 055 056 protected void processProperty(Properties props, String name, String value) { 057 Object obj = props.get(name); 058 if (obj instanceof String[]) { 059 String[] mobj = (String[]) obj; 060 String[] m = new String[mobj.length + 1]; 061 System.arraycopy(mobj, 0, m, 0, mobj.length); 062 m[mobj.length] = value; 063 props.put(name, m); 064 } else if (obj instanceof String) { 065 String[] m = new String[2]; 066 m[0] = (String) obj; 067 m[1] = value; 068 props.put(name, m); 069 } else 070 props.put(name, value); 071 } 072 073 protected void processFile(Properties props, String baseFile, boolean isEnv) throws ConfigurationException { 074 baseFile = Environment.get(baseFile); 075 boolean foundFile = false; 076 for (String file : getFiles(baseFile, isEnv?Environment.getEnvironment().getName():"")) { 077 foundFile |= readYamlFile(props, file); 078 } 079 if (!foundFile) { 080 throw new ConfigurationException("Could not find any matches for file: " + baseFile); 081 } 082 } 083 084 protected List<String> getFiles(String baseFile, String environmnents) { 085 List<String> files = new ArrayList<>(); 086 files.add(baseFile); 087 if (baseFile.endsWith(".yml") || baseFile.endsWith(".properties")) { 088 baseFile = baseFile.substring(0, baseFile.lastIndexOf(".")); 089 } 090 for (String env : ISOUtil.commaDecode(environmnents)) { 091 if (!ISOUtil.isBlank(env)) { 092 files.add(baseFile + "-" + env + ".yml"); 093 files.add(baseFile + "-" + env + ".properties"); 094 } 095 } 096 return files; 097 } 098 099 protected boolean readYamlFile(Properties props, String fileName) throws ConfigurationException { 100 try { 101 if (fileName.endsWith(".yml")) { 102 return readYAML(props, fileName); 103 } else { 104 return readPropertyFile(props, fileName); 105 } 106 } catch (Exception ex) { 107 throw new ConfigurationException(fileName, ex); 108 } 109 } 110 111 protected boolean readPropertyFile(Properties props, String fileName) throws IOException { 112 File f = new File(fileName); 113 if (f.exists() && f.canRead()) { 114 try (FileInputStream in = new FileInputStream(f)) { 115 props.load(in); 116 return true; 117 } 118 } 119 return false; 120 } 121 122 protected boolean readYAML(Properties props, String fileName) throws IOException { 123 File f = new File(fileName); 124 if (f.exists() && f.canRead()) { 125 try (InputStream fis = new FileInputStream(f)) { 126 Yaml yaml = new Yaml(); 127 Iterable<Object> document = yaml.loadAll(fis); 128 document.forEach(d -> { 129 Environment.flat(props, null, (Map<String, Object>) d, true); 130 }); 131 } 132 return true; 133 } 134 return false; 135 } 136}