001package gu.sql2java;
002
003import static gu.sql2java.SimpleLog.*;
004
005import java.io.File;
006import java.io.FileWriter;
007import java.io.IOException;
008import java.io.InputStream;
009import java.io.InputStreamReader;
010import java.net.URL;
011import java.util.HashSet;
012import java.util.Properties;
013import java.util.Set;
014/**
015 * 配置文件读取工具类
016 * @author guyadong
017 *
018 */
019public class ConfigUtils {
020    private static final String JAR_SUFFIX = ".jar";
021
022    /**
023     * 顺序加载不同位置的properties文件,加载顺序为:<br>
024     * 1.调用{@link ClassLoader#getResource(String)}方法在{@code clazz}所在位置查找,如果失败则抛出异常<br>
025     * 2.如果class在jar包中,则尝试读取在jar所在位置../confFolder/propFile,tomcat下即为WEB-INF/confFolder/propFile<br>
026     * 3.如果环境变量envVar定义,则从envVar指定的目录下读取propFile<br>
027     * 4.user.dir下查找confFolder/propFile加载配置<br>
028     * 后面的配置变量会覆盖前面的定义<br>
029     * @param propFile 要加载的properties文件名,为{@code null}或空时抛出异常 {@link IllegalArgumentException}
030     * @param confFolder popFile所在文件夹,{@code null}时使用默认值'conf'
031     * @param envVar 环境变量名 用于定义propFile位置,可为{@code null}
032     * @param clazz 用于获取 {@link ClassLoader}的类,为null时使用本类的class
033     * @param showProp 加载后是否显示所有值
034     * @return 返回加载后的{@link Properties}对象
035     */
036    public static Properties loadAllProperties(String propFile, String confFolder, String envVar, Class<?> clazz, boolean showProp) {
037        if(null==propFile||propFile.isEmpty()){
038            throw new IllegalArgumentException("the argument 'propFile' must not be null or empty");
039        }
040        if (null == confFolder){
041            confFolder = "conf";
042        }
043        if (null == clazz){
044            clazz = ConfigUtils.class;
045        }
046        final String fileSeparator = System.getProperty("file.separator");
047        String propPath = confFolder.concat(System.getProperty("file.separator")).concat(propFile);
048        Properties props = new Properties();
049        Set<File> loadedFiles = new HashSet<File>();
050        try {
051            // 在jar包中查找默认配置文件
052            URL url = clazz.getClassLoader().getResource(propPath.replace(fileSeparator, "/"));
053            if(null==url){
054                throw new ExceptionInInitializerError(String.format("not found default properties %s", propPath));
055            }
056            loadProperties(url, props);
057        } catch (Exception e) {
058            // 默认配置必须加载成功否则抛出异常
059            throw new ExceptionInInitializerError(String.format("fail to load default properties(加载默认配置文件失败) %s cause by %s", propPath,
060                    e.getMessage()));
061        }
062        try {
063            // 加载 jar包所在位置 ../conf/cassdk.properties
064            URL classLocation = clazz.getProtectionDomain().getCodeSource().getLocation();
065            if (classLocation.toString().endsWith(JAR_SUFFIX)) {
066                // jar包所在目录的父目录,tomcat下即为WEB-INF
067                File jarParent = new File(classLocation.getPath()).getParentFile().getParentFile();
068                if (null != jarParent) {
069                    File confFile = new File(jarParent, propPath);
070                    if (confFile.isFile()) {
071                        loadProperties(confFile.toURI().toURL(), props);
072                        loadedFiles.add(confFile);
073                    }
074                }
075            }
076        } catch (Exception e) {
077        }
078        try {
079            // 通过环境变量查找properties文件
080            if (envVar != null && !envVar.isEmpty()) {
081                String cf = System.getProperty(envVar);
082                if (null != cf&&!cf.isEmpty()) {
083                    File envFile = new File(cf, propFile);
084                    if (!loadedFiles.contains(envFile)) {
085                        loadProperties(envFile.toURI().toURL(), props);
086                        loadedFiles.add(envFile);
087                    }
088                } else {
089                    log("not defined environment variable '%s'", envVar);
090                }
091            }
092        } catch (Exception e) {
093        }
094        try {
095            // 在当前路径下查找配置文件
096            File propInUserDir = new File(System.getProperty("user.dir"), propPath);
097            if (propInUserDir.isFile() && !loadedFiles.contains(propInUserDir)) {
098                loadProperties(propInUserDir.toURI().toURL(), props);
099                loadedFiles.add(propInUserDir);
100            }
101        } catch (Exception e) {
102        }
103
104        // 输出所有参数值
105        if(showProp){
106            props.list(System.out);
107        }
108        return props;
109    }
110
111    /**
112     * 基于user.home,加载相对路径propPath指定的properties文件
113     * @param propPath
114     * @return
115     */
116    public static Properties loadPropertiesInUserHome(String propPath){
117        Properties props = new Properties();
118        try {
119            // 在user.home路径下查找配置文件
120            File propInUserHome = new File(System.getProperty("user.home"), propPath);
121            if (propInUserHome.isFile() ) {
122                loadProperties(propInUserHome.toURI().toURL(), props);
123            }
124        } catch (Exception e) {
125        }
126        return props;
127    }
128    /**
129     * 基于user.home,保存指定的{@link Properties}
130     * @param properties
131     * @param propertiesFile properties文件名
132     * @throws IOException
133     * @see Properties#store(java.io.Writer, String)
134     * @see System#getProperties()
135     */
136    public static void storePropertiesInUserHome(Properties properties,String propertiesFile) throws IOException{
137        if(null==properties){
138            throw new NullPointerException();
139        }
140        if(null==propertiesFile||propertiesFile.isEmpty()){
141            throw new IllegalArgumentException("propertiesFile must not be empty or null");
142        }
143        File propInUserHome = new File(System.getProperty("user.home"), propertiesFile);
144        File parent=propInUserHome.getParentFile();
145        if(!parent.exists()){
146            parent.mkdirs();
147        }
148        properties.store(new FileWriter(propInUserHome), null);
149
150    }
151    /**
152     * configure with the parameters given in the given url
153     * 
154     * @param url
155     *            the resource filename to be used
156     * @param props
157     *            dest properties to add
158     * @throws IOException
159     */
160    private static void loadProperties(URL url, Properties props) throws IOException {
161        if (null != url) {
162            InputStream is = null;
163            try {
164                props.load(new InputStreamReader(is = url.openStream(),"UTF-8"));
165                log("Load properties from %s", url.toString());
166            } finally {
167                if (is != null){
168                    is.close();
169                }
170            }
171        }
172    }
173}