package com.sitech.util;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Properties;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import org.apache.log4j.Logger;
   
   
/** 
 * properties文件读写操作工具类  
 * @version 1.0 
 */  
public class PropertyUtils {  
    private static Logger _log = Logger.getLogger(PropertyUtils.class);  
	private static boolean islocked  = false;
   
     private static Hashtable<String , Properties> pptContainer = new Hashtable<String , Properties>();  
   
   
   
   
   
   
   
     /** 
      * 获取配置键 
      * @param propertyFilePath 
      * @return 
      */  
     public static Enumeration<Object> getkeys(String propertyFilePath ){  
         Properties ppts = getProperties(propertyFilePath);  
         return ppts.keys();  
     }  
   
   
     /** 
      * 是否重新加載 
      */  
    private static boolean isreload=false;  
   
   
   
   
   
     public static boolean isIsreload() {  
        return isreload;  
    }  
   
   
   
   
   
   
    public static void setIsreload(boolean isreload) {  
        PropertyUtils.isreload = isreload;  
    }  
   
   
   
   
   
   
    /** 
      *  
      * 方法用途和描述: 获得属性文件的属性  
      *  
      * @param propertyFilePath 
      *            属性文件(包括类路径) 
      * @return 属性 
      * @author jily 新增日期:20140815 
      * @author 你的姓名 修改日期:20140815 
      * @since wapportal_manager version(2.0) 
      */  
     public final static Properties getProperties(String propertyFilePath) {  
      if (propertyFilePath == null) {  
       _log.error("配置文件变量为空值【propertyFilePath is null】!");  
       return null;  
      }  
      Properties ppts = pptContainer.get(propertyFilePath);  
   
      if (ppts == null||isIsreload()) {  
       ppts = loadPropertyFile(propertyFilePath);  
       if (ppts != null) {  
        pptContainer.put(propertyFilePath, ppts);  
       }  
      }  
   
      return ppts;  
     }  
   
     /** 
      *  
      * 方法用途和描述: 获得属性文件的属性  
      *  
      * @param propertyFilePath 
      *            属性文件(包括类路径) 
      * @return 属性 
      * @author jily 新增日期:20140815 
      * @author 你的姓名 修改日期:20140815 
      * @since wapportal_manager version(2.0) 
      */  
     public final static Properties getProperties2(String propertyFilePath,boolean isreload) {  
         if (propertyFilePath == null) {  
             _log.error("配置文件变量为空值【propertyFilePath is null】!");  
             return null;  
         }  
         Properties ppts = pptContainer.get(propertyFilePath);  
   
         if (ppts == null||isreload) {  
             ppts = loadPropertyFile(propertyFilePath);  
             if (ppts != null) {  
                 pptContainer.put(propertyFilePath, ppts);  
             }  
         }  
   
         return ppts;  
     }  
   
   
   
     /** 
      *  
      * 方法用途和描述: 获得属性文件的属性  
      *  
      * @param propertyFilePath 
      *            属性文件路径(包括类路径及文件系统路径) 
      * @return 属性文件对象 Properties 
      * @author jily 新增日期:20140815 
      * @author 你的姓名 修改日期:20140815 
      * @since wapportal_manager version(2.0) 
      */  
     public final static Properties getPropertiesByFs(String propertyFilePath) {  
      if (propertyFilePath == null) {  
       _log.error("propertyFilePath is null!");  
       return null;  
      }  
      Properties ppts = pptContainer.get(propertyFilePath);  
      if (ppts == null) {  
       ppts = loadPropertyFileByFileSystem(propertyFilePath);  
       if (ppts != null) {  
        pptContainer.put(propertyFilePath, ppts);  
       }  
      }  
      return ppts;  
     }  
   
     /** 
      *  
      * 方法用途和描述: 加载属性  
      *  
      * @param propertyFilePath 
      *            属性文件(包括类路径) 
      * @return 属性 
      * @author jily 新增日期:20140815 
      * @author 你的姓名 修改日期:20140815 
      * @since wapportal_manager version(2.0) 
      */  
     private static Properties loadPropertyFile(String propertyFilePath) {  
      java.io.InputStream is = PropertyUtils.class  
        .getResourceAsStream(propertyFilePath);  
      if (is == null) {  
       return loadPropertyFileByFileSystem(propertyFilePath);  
      }  
      Properties ppts = new Properties();  
      try {  
       ppts.load(is);  
       return ppts;  
      } catch (Exception e) {  
       _log.debug("加载属性文件出错:" + propertyFilePath, e);  
       return null;  
      }  
     }  
   
     /** 
      *  
      * 方法用途和描述: 从文件系统加载属性文件  
      *  
      * @param propertyFilePath 
      *            属性文件(文件系统的文件路径) 
      * @return 属性 
      * @author jily 新增日期:20140815 
      * @author 你的姓名 修改日期:20140815 
      * @since wapportal_manager version(2.0) 
      */  
     private static Properties loadPropertyFileByFileSystem(  
       final String propertyFilePath) {  
      try {  
       Properties ppts = new Properties();  
       ppts.load(new java.io.FileInputStream(propertyFilePath));  
       return ppts;  
      } catch (java.io.FileNotFoundException e) {  
       _log.error("FileInputStream(\"" + propertyFilePath  
         + "\")! FileNotFoundException: " + e);  
       return null;  
      } catch (java.io.IOException e) {  
       _log.error("Properties.load(InputStream)! IOException: " + e);  
       return null;  
      }  
     }  
   
     /** 
      *  
      * 方法用途和描述: 对存在的属性文件中添加键值对并保存 
      *  
      * @param propertyFilePath 
      *            属性文件的路径(包括类路径及文件系统路径) 
      * @param htKeyValue 
      *            键值对Hashtable 
      * @return 
      * @author jily 新增日期:20140815 
      * @author 你的姓名 修改日期:20140815 
      * @since wapportal_manager version(2.0) 
      */  
     public final static boolean setValueAndStore(String propertyFilePath,  
       java.util.Hashtable<String , String> htKeyValue) {  
      return setValueAndStore(propertyFilePath, htKeyValue, null);  
     }  
   
     /** 
      *  
      * 方法用途和描述: 对存在的属性文件中添加键值对并保存  
      *  
      * @param propertyFilePath 
      *            属性文件的路径(包括类路径及文件系统路径) 
      * @param htKeyValue 
      *            键值对Hashtable 
      * @param storeMsg 
      *            保存时添加的附加信息(注释) 
      * @return 
      * @author jily 新增日期:20140815 
      * @author 你的姓名 修改日期:20140815 
      * @since wapportal_manager version(2.0) 
      */  
     public final static boolean setValueAndStore(String propertyFilePath,  
       java.util.Hashtable<String , String> htKeyValue, String storeMsg) {  
      Properties ppts = getProperties(propertyFilePath);  
   
      if (ppts == null || htKeyValue == null) {  
       return false;  
      }  
      ppts.putAll(htKeyValue);  
      java.io.OutputStream stream = null;  
      try {  
       stream = new java.io.FileOutputStream(propertyFilePath);  
      } catch (FileNotFoundException e) {  
       _log.debug("propertyFilePath = " + propertyFilePath);  
       String path = PropertyUtils.class.getResource(propertyFilePath)  
         .getPath();  
       _log.debug("~~~~~~~~path~~~XXX~~~~~" + path);  
       try {  
        stream = new java.io.FileOutputStream(path);  
       } catch (FileNotFoundException e1) {  
        _log.error("FileNotFoundException! path=" + propertyFilePath);  
        return false;  
       }  
      }  
   
      if (stream == null) {  
       return false;  
      }  
   
      try {  
       ppts.store(stream, storeMsg != null ? storeMsg  
         : "set value and store.");  
       return true;  
      } catch (java.io.IOException e) {  
       e.printStackTrace();  
       return false;  
      } finally {  
       if (stream != null) {  
        try {  
         stream.close();  
        } catch (IOException e) {  
         e.printStackTrace();  
        }  
       }  
      }  
     }  
   
     /** 
      *  
      * 方法用途和描述: 创建属性文件  
      *  
      * @param propertyFilePath 
      *            要存储属性文件的路径 
      * @param htKeyValue 
      *            属性文件中的键值对Hashtable 
      * @return 
      * @author jily 新增日期:20140815 
      * @author 你的姓名 修改日期:20140815 
      * @since wapportal_manager version(2.0) 
      */  
     public final static boolean createPropertiesFile(String propertyFilePath,  
       java.util.Hashtable<String , String> htKeyValue) {  
      java.io.File file = new java.io.File(propertyFilePath);  
      if (!file.exists()) {  
       try {  
        file.createNewFile();  
       } catch (java.io.IOException e) {  
        e.printStackTrace();  
       }  
      }  
      return setValueAndStore(propertyFilePath, htKeyValue);  
     }  
   
     /** 
      *  
      * 方法用途和描述:设置属性值  
      *  
      * @param propertyFilePath 
      *            属性文件(包括类路径) 
      * @param key 
      *            属性键 
      * @param value 
      *            属性值 
      * @return 
      * @author jily 新增日期:20140815 
      * @author 你的姓名 修改日期:20140815 
      * @since wapportal_manager version(2.0) 
      */  
     public final static boolean setValue(String propertyFilePath, String key,  
       String value) {  
      Properties ppts = getProperties(propertyFilePath);  
      if (ppts == null) {  
       return false;  
      }  
      ppts.put(key, value);  
      return true;  
     }  
   
     /** 
      *  
      * 方法用途和描述: 保存属性文件对象  
      *  
      * @param properties 
      *            属性文件对象 
      * @param propertyFilePath 
      *            要保存的路径 
      * @param msg 
      *            保存时添加的附加信息(注释) 
      * @author jily 新增日期:20140815 
      * @author 你的姓名 修改日期:20140815 
      * @since wapportal_manager version(2.0) 
      */  
     public final static void store(Properties properties,  
       String propertyFilePath, String msg) {  
      try {  
       java.io.OutputStream stream = new java.io.FileOutputStream(  
         propertyFilePath);  
       properties.store(stream, msg);  
      } catch (java.io.FileNotFoundException e) {  
       _log.error("FileOutputStream(" + propertyFilePath  
         + ")! FileNotFoundException: " + e);  
      } catch (java.io.IOException e) {  
       _log.error("store(stream, msg)! IOException: " + e);  
       e.printStackTrace();  
      }  
     }  
   
     /** 
      *  
      * 方法用途和描述: 删除属性值  
      *  
      * @param propertyFilePath 
      *            属性文件(包括类路径) 
      * @param key 
      *            属性键 
      * @return 
      * @author jily 新增日期:20140815 
      * @author 你的姓名 修改日期:20140815 
      * @since wapportal_manager version(2.0) 
      */  
     public final static String removeValue(String propertyFilePath, String key) {  
   
      Properties ppts = getProperties(propertyFilePath);  
      if (ppts == null) {  
       return null;  
      }  
      return (String) ppts.remove(key);  
     }  
   
     /** 
      *  
      * 方法用途和描述: 删除属性文件中的Key数组所对应的键值对  
      *  
      * @param propertyFilePath 
      *            属性文件路径(包括类路径及文件系统路径) 
      * @param key 
      *            key数组 
      * @return 属性文件对象 
      * @author jily 新增日期:20140815 
      * @author 你的姓名 修改日期:20140815 
      * @since wapportal_manager version(2.0) 
      */  
     public final static Properties removeValue(String propertyFilePath,  
       String[] key) {  
      if (key == null) {  
       _log.error("key[] is null!");  
       return null;  
      }  
      Properties ppts = getProperties(propertyFilePath);  
      if (ppts == null) {  
       return null;  
      }  
      for (String strKey : key) {  
       ppts.remove(strKey);  
      }  
      return ppts;  
     }  
   
     /** 
      *  
      * 方法用途和描述:删除属性文件中的Key数组所对应的键值对,并将属性文件对象持久化(即保存) 
      *  
      *  
      * @param propertyFilePath 
      *            属性文件路径(包括类路径及文件系统路径) 
      * @param key 
      *            属性文件中的key数组 
      * @return 成功与否(true|false) 
      * @author jily 新增日期:20140815 
      * @author 你的姓名 修改日期:20140815 
      * @since wapportal_manager version(2.0) 
      */  
     public final static boolean removeValueAndStore(String propertyFilePath,  
       String[] key) {  
      Properties ppts = removeValue(propertyFilePath, key);  
      if (ppts == null) {  
       return false;  
      }  
      store(ppts, propertyFilePath, "batch remove key value!");  
      return true;  
     }  
   
     /** 
      *  
      * 方法用途和描述: 更新指定路径的属性文件中的键所对应的值  
      *  
      * @param propertyFilePath 
      *            属性文件路径(包括类路径及文件系统路径) 
      * @param key 
      *            属性文件中的key 
      * @param newValue 
      *            要更新的新值 
      * @return 成功与否(true|false) 
      * @author jily 新增日期:20140815 
      * @author 你的姓名 修改日期:20140815 
      * @since wapportal_manager version(2.0) 
      */  
     public final static boolean updateValue(String propertyFilePath,  
       String key, String newValue) {  
      if (key == null || newValue == null) {  
       _log.error("key or newValue is null!");  
       return false;  
      }  
      java.util.Hashtable<String , String> ht = new java.util.Hashtable<String , String>();  
      ht.put(key, newValue);  
      return setValueAndStore(propertyFilePath, ht, "update " + key  
        + "'s value!");  
     }  
   
     /** 
      *  
      * 方法用途和描述: 批量更新指定路径的属性文件中的键所对应的值  
      *  
      * @param propertyFilePath 
      *            属性文件路径(包括类路径及文件系统路径) 
      * @param htKeyValue 
      *            要更新的键值对Hashtable 
      * @return 成功与否(true|false) 
      * @author jily 新增日期:20140815 
      * @author 你的姓名 修改日期:20140815 
      * @since wapportal_manager version(2.0) 
      */  
     public final static boolean batchUpdateValue(String propertyFilePath,  
       java.util.Hashtable<String , String> htKeyValue) {  
      if (propertyFilePath == null || htKeyValue == null) {  
       return false;  
      }  
      return setValueAndStore(propertyFilePath, htKeyValue,  
        "batch update key value!");  
     }  
   
     /** 
      *  
      * 方法用途和描述: 移除加载的属性文件  
      *  
      * @param propertyFilePath 
      *            属性文件(包括类路径) 
      * @return 
      * @author jily 新增日期:20140815 
      * @author 你的姓名 修改日期:20140815 
      * @since wapportal_manager version(2.0) 
      */  
     public final static Properties removePropertyFile(String propertyFilePath) {  
   
      return pptContainer.remove(propertyFilePath);  
     }  
   
     /** 
      *  
      * 方法用途和描述: 重新加载某个Property文件  
      *  
      * @param propertyFilePath 
      *            要重新加载的Property文件,如果当前内存中没有的话则加载,否则替换 
      * @author jily 新增日期:20140815 
      * @author 你的姓名 修改日期:20140815 
      * @since wapportal_manager version(2.0) 
      */  
     public final static void reloadPropertyFile(String propertyFilePath) {  
      pptContainer.remove(propertyFilePath);  
      loadPropertyFile(propertyFilePath);  
     }  
   
     /** 
      *  
      * 方法用途和描述: 获得属性文件的路径  
      *  
      * @param pkg 
      *            包名 
      * @param propertyFileName 
      *            属性文件名 
      * @return 
      * @author jily 新增日期:20140815 
      * @author 你的姓名 修改日期:20140815 
      * @since wapportal_manager version(2.0) 
      */  
     public final static String getPpropertyFilePath(String pkg,  
       String propertyFileName) {  
   
      pkg = pkg == null ? "" : pkg.replaceAll("\\.", "/");  
      propertyFileName = propertyFileName.endsWith(".properties") ? propertyFileName  
        : (propertyFileName + ".properties");  
      return "/" + pkg + "/" + propertyFileName;  
     }  
   
     public static void main(String[] args) {  
    	
      String path = "f://filechange.properties";  
      Properties pro =  getProperties(path);  
      LockFile file = new LockFile(path);
      ReentrantReadWriteLock lock = file.getLock(); 
      lock.writeLock().lock();
      int i=0;

      while(i<10){
    	 i++;
    	 System.out.println(i);
    	 if(i==8){
    		 lock.writeLock().unlock();
    	 }
    	 if(lock.isWriteLocked()){
   		  try {

   	    	 System.out.println("等待。。。。。。。");
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
   	  }else{

	      System.out.println("已经释放");
   		  break;
   	  }
      }


//      boolean iskey = pro.containsKey("name");
//      Hashtable<String , String> ht = new Hashtable<String , String>();  
//      if(!iskey){
//          ht.put("name", "jily");
//      }else{
//    	  PropertyUtils.updateValue(path, "name", "jily001");
//      }
//      PropertyUtils.setValueAndStore(path, ht); 
		//boolean isExists = PropertyUtils.createPropertiesFile("f://filechange.properties", new Hashtable<String , String>());
//    v=CharsetUtil.toGbk(v);  
   
//    Hashtable<String , String> ht = new Hashtable<String , String>();  
//    ht.put("name", "jily");  
//    PropertyUtils.setValueAndStore(path, ht);  
//    String v_ = PropertyUtils.getValue(path, "name");  
//    _log.info("value1 = " + v_);  
//    PropertyUtils.reloadPropertyFile(path);  
//    String v2_ = PropertyUtils.getValue(path, "name");  
//    _log.info("value2 = " + v2_);  
     }  
}