From 59ac15b78aab4892631bd30a2fd4954a79db3504 Mon Sep 17 00:00:00 2001 From: manlge Date: Sun, 18 Aug 2013 17:44:30 +0800 Subject: [PATCH 1/7] =?UTF-8?q?=E9=85=8D=E7=BD=AE=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=8F=98=E9=87=8F(=E5=80=BC=E6=9D=A5?= =?UTF-8?q?=E4=BA=8ESystem=E7=9A=84Properties)=EF=BC=8Cpom=E4=BE=9D?= =?UTF-8?q?=E8=B5=96=E6=B7=BB=E5=8A=A0junit?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 5 + dist/profile.properties | 6 +- dist/tprofiler.jar | Bin 90069 -> 92242 bytes pom.xml | 17 +- src/main/java/com/taobao/profile/Manager.java | 2 +- .../com/taobao/profile/config/ProfConfig.java | 155 ++++++++---------- .../com/taobao/profile/utils/Utilities.java | 64 ++++++++ .../utils/VariableNotFoundException.java | 31 ++++ src/main/resources/profile.properties | 6 +- .../taobao/profile/test/UtilitiesTest.java | 18 ++ 10 files changed, 205 insertions(+), 99 deletions(-) create mode 100644 .gitignore create mode 100644 src/main/java/com/taobao/profile/utils/Utilities.java create mode 100644 src/main/java/com/taobao/profile/utils/VariableNotFoundException.java create mode 100644 src/test/java/com/taobao/profile/test/UtilitiesTest.java diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..88618c3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +/target +.DS_Store +.settings +.project +.classpath diff --git a/dist/profile.properties b/dist/profile.properties index e777020..d9a9682 100644 --- a/dist/profile.properties +++ b/dist/profile.properties @@ -7,9 +7,9 @@ port = 50000 debugMode = false needNanoTime = false ignoreGetSetMethod = true -logFilePath = /home/admin/logs/tprofiler.log -methodFilePath = /home/admin/logs/tmethod.log -samplerFilePath = /home/admin/logs/tsampler.log +logFilePath = ${user.home}/logs/tprofiler.log +methodFilePath = ${user.home}/logs/tmethod.log +samplerFilePath = ${user.home}/logs/tsampler.log excludeClassLoader = org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader includePackageStartsWith = com.taobao;com.taobao.common excludePackageStartsWith = com.taobao.sketch;org.apache.velocity;com.alibaba;com.taobao.forest.domain.dataobject diff --git a/dist/tprofiler.jar b/dist/tprofiler.jar index c4a96786ca3b2f4bfbfdfc33f652c521ed85d558..4d5c06f2a0318a4bf24c3033bf50580538e84d1b 100644 GIT binary patch delta 28515 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 diff --git a/pom.xml b/pom.xml index 442daf0..667e83f 100644 --- a/pom.xml +++ b/pom.xml @@ -12,13 +12,19 @@ asm 3.3.1 + + junit + junit + 4.11 + test + org.apache.maven.plugins maven-compiler-plugin - 3.0 + 3.0 1.6 1.6 @@ -28,7 +34,16 @@ maven-assembly-plugin 2.2.2 + + + package + + assembly + + + + false jar-with-dependencies diff --git a/src/main/java/com/taobao/profile/Manager.java b/src/main/java/com/taobao/profile/Manager.java index f5e61fc..8631abf 100644 --- a/src/main/java/com/taobao/profile/Manager.java +++ b/src/main/java/com/taobao/profile/Manager.java @@ -29,7 +29,7 @@ public class Manager { /** * 默认配置文件 */ - private static final String DEFAULT_CONFIG = "profile"; + private static final String DEFAULT_CONFIG = "profile.properties"; /** * 远程连接端口 diff --git a/src/main/java/com/taobao/profile/config/ProfConfig.java b/src/main/java/com/taobao/profile/config/ProfConfig.java index dcae38d..60a661f 100644 --- a/src/main/java/com/taobao/profile/config/ProfConfig.java +++ b/src/main/java/com/taobao/profile/config/ProfConfig.java @@ -9,11 +9,12 @@ package com.taobao.profile.config; import java.io.File; -import java.io.FileNotFoundException; import java.io.FileReader; -import java.io.IOException; +import java.io.InputStream; import java.util.Properties; -import java.util.ResourceBundle; + +import com.taobao.profile.utils.Utilities; +import com.taobao.profile.utils.VariableNotFoundException; /** * 读取并保存配置 @@ -121,59 +122,66 @@ public ProfConfig(String defaultPath) { * @param path */ private void parseProperty(File path) { - Properties resource = new Properties(); try { resource.load(new FileReader(path)); - String startProfTime = resource.getProperty("startProfTime"); - String endProfTime = resource.getProperty("endProfTime"); - String logFilePath = resource.getProperty("logFilePath"); - String methodFilePath = resource.getProperty("methodFilePath"); - String samplerFilePath = resource.getProperty("samplerFilePath"); - String includePackageStartsWith = resource.getProperty("includePackageStartsWith"); - String eachProfUseTime = resource.getProperty("eachProfUseTime"); - String eachProfIntervalTime = resource.getProperty("eachProfIntervalTime"); - String samplerIntervalTime = resource.getProperty("samplerIntervalTime"); - String excludePackageStartsWith = resource.getProperty("excludePackageStartsWith"); - String needNanoTime = resource.getProperty("needNanoTime"); - String ignoreGetSetMethod = resource.getProperty("ignoreGetSetMethod"); - String excludeClassLoader = resource.getProperty("excludeClassLoader"); - String debugMode = resource.getProperty("debugMode"); - String port = resource.getProperty("port"); - setPort(port == null ? 50000 : Integer.valueOf(port)); - setDebugMode("true".equals(debugMode)); - setExcludeClassLoader(excludeClassLoader); - setExcludePackageStartsWith(excludePackageStartsWith); - setEndProfTime(endProfTime); - setIncludePackageStartsWith(includePackageStartsWith); - setLogFilePath(logFilePath); - setMethodFilePath(methodFilePath); - setSamplerFilePath(samplerFilePath); - setStartProfTime(startProfTime); - setNeedNanoTime("true".equals(needNanoTime)); - setIgnoreGetSetMethod("true".equals(ignoreGetSetMethod)); - if (eachProfUseTime == null) { - setEachProfUseTime(5); - } else { - setEachProfUseTime(Integer.valueOf(eachProfUseTime.trim())); - } - if (eachProfIntervalTime == null) { - setEachProfIntervalTime(50); - } else { - setEachProfIntervalTime(Integer.valueOf(eachProfIntervalTime.trim())); - } - if (samplerIntervalTime == null) { - setSamplerIntervalTime(10); - } else { - setSamplerIntervalTime(Integer.valueOf(samplerIntervalTime.trim())); - } - } catch (FileNotFoundException e) { - e.printStackTrace(); - } catch (IOException e) { + loadConfig(resource); + } catch (Exception e) { e.printStackTrace(); } } + /** + * 加载配置 + * @param properties + * @throws ParseException + */ + private void loadConfig(Properties properties) throws VariableNotFoundException { + Properties context = System.getProperties(); + String startProfTime = properties.getProperty("startProfTime"); + String endProfTime = properties.getProperty("endProfTime"); + String logFilePath = Utilities.repleseVariables(properties.getProperty("logFilePath"), context) ; + String methodFilePath = Utilities.repleseVariables(properties.getProperty("methodFilePath"), context) ; + String samplerFilePath = Utilities.repleseVariables(properties.getProperty("samplerFilePath"), context) ; + String includePackageStartsWith = properties.getProperty("includePackageStartsWith"); + String eachProfUseTime = properties.getProperty("eachProfUseTime"); + String eachProfIntervalTime = properties.getProperty("eachProfIntervalTime"); + String samplerIntervalTime = properties.getProperty("samplerIntervalTime"); + String excludePackageStartsWith = properties.getProperty("excludePackageStartsWith"); + String needNanoTime = properties.getProperty("needNanoTime"); + String ignoreGetSetMethod = properties.getProperty("ignoreGetSetMethod"); + String excludeClassLoader = properties.getProperty("excludeClassLoader"); + String debugMode = properties.getProperty("debugMode"); + String port = properties.getProperty("port"); + setPort(port == null ? 50000 : Integer.valueOf(port)); + setDebugMode("true".equals(debugMode)); + setExcludeClassLoader(excludeClassLoader); + setExcludePackageStartsWith(excludePackageStartsWith); + setEndProfTime(endProfTime); + setIncludePackageStartsWith(includePackageStartsWith); + setLogFilePath(logFilePath); + setMethodFilePath(methodFilePath); + setSamplerFilePath(samplerFilePath); + setStartProfTime(startProfTime); + setNeedNanoTime("true".equals(needNanoTime)); + setIgnoreGetSetMethod("true".equals(ignoreGetSetMethod)); + if (eachProfUseTime == null) { + setEachProfUseTime(5); + } else { + setEachProfUseTime(Integer.valueOf(eachProfUseTime.trim())); + } + if (eachProfIntervalTime == null) { + setEachProfIntervalTime(50); + } else { + setEachProfIntervalTime(Integer.valueOf(eachProfIntervalTime.trim())); + } + if (samplerIntervalTime == null) { + setSamplerIntervalTime(10); + } else { + setSamplerIntervalTime(Integer.valueOf(samplerIntervalTime.trim())); + } + } + /** * 解析默认配置文件 * @@ -181,48 +189,13 @@ private void parseProperty(File path) { */ private void parse(String configName) { try { - ResourceBundle resource = ResourceBundle.getBundle(configName); - String startProfTime = resource.getString("startProfTime"); - String endProfTime = resource.getString("endProfTime"); - String logFilePath = resource.getString("logFilePath"); - String methodFilePath = resource.getString("methodFilePath"); - String samplerFilePath = resource.getString("samplerFilePath"); - String includePackageStartsWith = resource.getString("includePackageStartsWith"); - String eachProfUseTime = resource.getString("eachProfUseTime"); - String eachProfIntervalTime = resource.getString("eachProfIntervalTime"); - String samplerIntervalTime = resource.getString("samplerIntervalTime"); - String excludePackageStartsWith = resource.getString("excludePackageStartsWith"); - String needNanoTime = resource.getString("needNanoTime"); - String ignoreGetSetMethod = resource.getString("ignoreGetSetMethod"); - String excludeClassLoader = resource.getString("excludeClassLoader"); - String debugMode = resource.getString("debugMode"); - String port = resource.getString("port"); - setPort(port == null ? 50000 : Integer.valueOf(port)); - setDebugMode("true".equals(debugMode)); - setExcludeClassLoader(excludeClassLoader); - setExcludePackageStartsWith(excludePackageStartsWith); - setEndProfTime(endProfTime); - setIncludePackageStartsWith(includePackageStartsWith); - setLogFilePath(logFilePath); - setMethodFilePath(methodFilePath); - setSamplerFilePath(samplerFilePath); - setStartProfTime(startProfTime); - setNeedNanoTime("true".equals(needNanoTime)); - setIgnoreGetSetMethod("true".equals(ignoreGetSetMethod)); - if (eachProfUseTime == null) { - setEachProfUseTime(5); - } else { - setEachProfUseTime(Integer.valueOf(eachProfUseTime.trim())); - } - if (eachProfIntervalTime == null) { - setEachProfIntervalTime(50); - } else { - setEachProfIntervalTime(Integer.valueOf(eachProfIntervalTime.trim())); - } - if (samplerIntervalTime == null) { - setSamplerIntervalTime(10); - } else { - setSamplerIntervalTime(Integer.valueOf(samplerIntervalTime.trim())); + InputStream in = getClass().getResourceAsStream("/" + configName); + try{ + Properties properties = new Properties(); + properties.load(in); + loadConfig(properties); + } finally{ + in.close(); } } catch (Exception e) { e.printStackTrace(); diff --git a/src/main/java/com/taobao/profile/utils/Utilities.java b/src/main/java/com/taobao/profile/utils/Utilities.java new file mode 100644 index 0000000..a45a603 --- /dev/null +++ b/src/main/java/com/taobao/profile/utils/Utilities.java @@ -0,0 +1,64 @@ +/** + * (C) 2011-2012 Alibaba Group Holding Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + */ + +package com.taobao.profile.utils; + +import java.util.Map; + +/** + * 提供常用的一些工具方法 + * @author 刘永伟(manlge) + * @version 1.0 + * @since 2013-08-18 + */ +public class Utilities { + + private Utilities() { + } + + /** + * 变量替换,将以${user.home}类似的变量替换成具体的值 + * @param source 源字符串,如:${user.dir}/${user.language}/tprofiler.log + * @param context 上下文,用于查找变量的具体值 + * @return 替换过的字符串 + * @throws VariableNotFoundException + * @author manlge + */ + public static String repleseVariables(String source, Map context) throws VariableNotFoundException{ + if (source == null){ + throw new IllegalArgumentException("source can't be null"); + } + + if (context == null){ + throw new IllegalArgumentException("context can't be null"); + } + + //从后向前查找 + int p = source.lastIndexOf('}'); + while (p != -1){ + int p1 = source.lastIndexOf("${"); + //没有找到匹配 + if (p1 == -1){ + return source; + } + + String key = source.substring(p1 + 2, p); //+2 是跳过${ + if (!context.containsKey(key)){ + throw new VariableNotFoundException("variable " + key + " not found"); + } + String value = String.valueOf(context.get(key)); + String start = source.substring(0, p1); + String end = source.substring(p + 1); + source = start + value + end; + p = source.lastIndexOf('}'); + } + + return source; + } +} diff --git a/src/main/java/com/taobao/profile/utils/VariableNotFoundException.java b/src/main/java/com/taobao/profile/utils/VariableNotFoundException.java new file mode 100644 index 0000000..82f3568 --- /dev/null +++ b/src/main/java/com/taobao/profile/utils/VariableNotFoundException.java @@ -0,0 +1,31 @@ +package com.taobao.profile.utils; + +public class VariableNotFoundException extends Exception { + + /** + * + */ + private static final long serialVersionUID = -1103164294134360436L; + + public VariableNotFoundException() { + super(); + } + + public VariableNotFoundException(String message, Throwable cause, + boolean enableSuppression, boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } + + public VariableNotFoundException(String message, Throwable cause) { + super(message, cause); + } + + public VariableNotFoundException(String message) { + super(message); + } + + public VariableNotFoundException(Throwable cause) { + super(cause); + } + +} diff --git a/src/main/resources/profile.properties b/src/main/resources/profile.properties index e777020..d9a9682 100644 --- a/src/main/resources/profile.properties +++ b/src/main/resources/profile.properties @@ -7,9 +7,9 @@ port = 50000 debugMode = false needNanoTime = false ignoreGetSetMethod = true -logFilePath = /home/admin/logs/tprofiler.log -methodFilePath = /home/admin/logs/tmethod.log -samplerFilePath = /home/admin/logs/tsampler.log +logFilePath = ${user.home}/logs/tprofiler.log +methodFilePath = ${user.home}/logs/tmethod.log +samplerFilePath = ${user.home}/logs/tsampler.log excludeClassLoader = org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader includePackageStartsWith = com.taobao;com.taobao.common excludePackageStartsWith = com.taobao.sketch;org.apache.velocity;com.alibaba;com.taobao.forest.domain.dataobject diff --git a/src/test/java/com/taobao/profile/test/UtilitiesTest.java b/src/test/java/com/taobao/profile/test/UtilitiesTest.java new file mode 100644 index 0000000..ac3fd13 --- /dev/null +++ b/src/test/java/com/taobao/profile/test/UtilitiesTest.java @@ -0,0 +1,18 @@ +package com.taobao.profile.test; + +import org.junit.Assert; +import org.junit.Test; + +import com.taobao.profile.utils.Utilities; +import com.taobao.profile.utils.VariableNotFoundException; + +public class UtilitiesTest{ + + @Test + public void testRepleseVariables() throws VariableNotFoundException{ + String source = "${user.home}/logs/${user.language}/tprofiler.log"; + String str1 = Utilities.repleseVariables(source, System.getProperties()); + String str2 = System.getProperty("user.home") + "/logs/" + System.getProperty("user.language") + "/tprofiler.log"; + Assert.assertEquals(str1, str2); + } +} From 186b570267ac7a29198bc0d23af96bc903407496 Mon Sep 17 00:00:00 2001 From: manlge Date: Sun, 18 Aug 2013 18:45:14 +0800 Subject: [PATCH 2/7] =?UTF-8?q?=E5=8A=A0=E8=BD=BD=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E6=97=B6=EF=BC=8C=E7=BB=9F=E4=B8=80=E9=87=87=E7=94=A8=E5=85=B7?= =?UTF-8?q?=E6=9C=89=E5=8F=98=E9=87=8F=E6=9B=BF=E6=8D=A2=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E7=9A=84ConfigureProperties=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dist/tprofiler.jar | Bin 92242 -> 94485 bytes .../profile/config/ConfigureProperties.java | 194 ++++++++++++++++++ .../com/taobao/profile/config/ProfConfig.java | 13 +- .../profile/test/ConfigurePropertiesTest.java | 19 ++ 4 files changed, 218 insertions(+), 8 deletions(-) create mode 100644 src/main/java/com/taobao/profile/config/ConfigureProperties.java create mode 100644 src/test/java/com/taobao/profile/test/ConfigurePropertiesTest.java diff --git a/dist/tprofiler.jar b/dist/tprofiler.jar index 4d5c06f2a0318a4bf24c3033bf50580538e84d1b..0142e05a244e867da5752a73982315480f1ddcd7 100644 GIT binary patch delta 6842 zcmZ`;1yoc~yPZpSGjvOLD~*VB3DVsS(&G;%T+=7pf^9a{(qpInU zkr5~969-0<=@mN4XIht69w>$GSS-utKi=Hm-Q6EEH9r42SMNXGu_?JE{XN^;15$PM zy_c2QSm}CPo1x=_ddGAYi^IMxPcF9&N-p}M%gxk6Dv~C?}k@#1L$B1qbn(et~@oTw(Qpy_KxH~V^h2A zk7&SMc1M!nE-g62`xB*j@a1a<2-R8S_K&okUAk5i7PqMTl@V2|n9oSnDgEBMwtFod zofZG8_j+?*L-)1YIAvJrRNYj>V0IEOdRorHUaKM;mj}L7s3UP85f*rBlB03ftHQGU z{_Otwz|q`G?D!WE`()WX)Qz;l23+cyi!Fjq3iUo8#v*EfxpRWlx0W;CmLc{c2jIG} zWld`Lrma?Znwx!({aof-g4o;_4l|G3j>Z`EXs5T%5?{OB7M`u`uFuZUz!jAiEi+5T z918*E^)nrFB%9P27YyDZU{;>15-id&+3NSI4_3E%chdh@_a)`(y)~nFAqAyx_JZBO z52p*#Cm}nOha?NqEYVHtgyfLeQTioJ0c>Whfp7aSGrthrDGJ}F!UNhj1YHINQTp!| z0Ml(_xc;r=O&Yha!?)2qr*syEqjh=EKh-#q^}A>C6kiqT1n)BQEb|ERV9M<+;D#RQ zrwyXFHCl`7Ja<-GzciP5(jOPoZbFJl8SHF%i!S)Ke>~`RQ@A81H76rv!Ra%jS=Lv{ z_*ct*SMvv z3Fyc4YV`69Dr9S&WuD;6Kt6OjKRe(;pWcn%#>O)2UAHv`doYu966tFeFtnJ4l$W1h zN^#584zUyyKxgMRh^mINxA^}=obElq3TRd=K9ixm_i$!W(CQA~lytG9o)OF~#*RM@?4(yfl! z{!pt@688O~#U)H(*@1fi<{e?xyr!<0lO{Q4Xt_qn6ngJrEX{Fsi;3*0DDl)(@u*XQ zEvD76Gw(CWcU0&yeVTUS`|A--$LQnxK?UD=ize%poj-qzXlv@A@osc`BkgCOuaX`j z$fjd#KREvaCLYDR??49;gdG?+!JVWvwokB)i{ZRHVpH}x`+1VS)UShm<}_I(_VR*# z-_^E6_-!{t4f@QDScebDv{@AY^pPvZ3^?JuXwVGA5Op#xrplat`zk_WmWQ5MtN4yY z1za#FUFlqEoP+(-=K{QI${qTGA>Rw3P*x2HeEZ;pFn%WVknBCgQSp@aEG4^}D}CzL z!By_=Dpk(Q^^P3t$4jp^4W$x-f1q~QPDZSnKNwEm`nEvcstNDnB0a@_P_S6$*Dr5V z`?}1sugX9mJad6JtzNx=CRJw+*D3W5@7d@pw+nk#Pwj=WijuFQ)CQV#jee{3FN4zo zMeC-S47h6h$IHWLh}I;|*J9wkBX1`)2lQH5Ro<->mi{)`{Rc$93T`R1wG;cz^>-hqNU$U=FbbT0%OuiWb$;Hg zHF8E{vp0p+8?SPv;Z@T#_$eV)R5E|0)HBmA`^_Q+=AJU~Rvhh?Rr*o^)`@$Y7LJIq zDP;*Si6@k{ln#P3=_bN=)?|QPG@{*FE~mkfZ){g0jZ?zQM3&iv@>Svo7F!j{)0yhB zd_|!dzz#oNNmPW-c?)3e84%ivFkp(N;T(M-i0zE+pz?}MjV*~a5Pd%4gz8DCn5xnY zC1oo75edtD5Ys09sZ)pE_@I;Os(l={plRk2>l~ZMr6r_7djE64<&Ir2`wYE-Z-`UV z$l1#}5kh%~a?iB4x4l)fnSBBTA}^^@>vveZ^b(fU>Gf^XwdB*SifYtW$w`DvpUg9{ z$fB%~;;gawG!V2lC45ODWq7*oMb?=Y*Sm>kpf%w8boBI*XXpxbf%eF0OWm6gy?s6{ zF4eW9niWk*$$qIO)%NzMTOoS0A7$AN&Tfrra&CpleBI$3#b+9%?&5oxbk!2~lUAU! zGJ1`oK>4wg{H>z^{LtNq=N9a|b_}S;A6O*=iM#l***n&Yl9JPgRn)d3m9#8VO1z^S zyeRjQ)2-sh1&qaacZWER=qshN-YA!!5oQ->@!7ZuLwI}Yw+CxZQyH|Ya`AiTb?{Q~wZ~aT0z&|0H;T@t0)?O6ir)N)H9HhyCbWON{Q1*f-_PM6j<)xD z=^40==)i=B!{*q87uxZ3B=p~yo<#jvC&o_r);koUePkvUY}!jIqdu4{)HZ9~9A{27 zVpowk#cop+2e++As?{IlqRNabiF-^XNEJkN7*I^8WyJt3p8fpYR;n+(bAo@O?i_$_ z8eSz19P>Pe^sfx@JnmgV2lLkj#0+T7_Dq~_Z}L3uIqKqBCTGa3RT$(qx{e*F4h zoj7OQ?)n_D7Gp9HM;!6tLX~&y0d*7{n!FjT0Hqggv(Gk6N1Z zbC0G6;`L#_DmG19;=D`DG;uObDR~GYy&+;#K{b)Sp-j8XLgnJ~L**-jG3a2OVdwes zd*c$k=1Fl=>=v+T4PLMy8jhJv0{6on(4wv)FL#zD+I zi!Eh)x}Ol?j1R)1UzvSUB&Kg?j}cM~P;6!9@+=B}QxhL3m^@9+gl*JA*J9oypyY`U zg&LZUTjN62jOP1SP{2#pt29Qg17eDLDW_m+$Ell zJzNb@K_k;)apnxjCu!!eCdpM64}y@L)ESOjqeD}9^lK+;H04ti8M@BuqmRnRhs2MQ z6Q!me084eg#XCCnjvRzWmSIp~866g(pi`g1(KJ0VDw>hAEh@5l$EmkI)f0u|qZURV z$~p!lJ;c;=M$22$huo8m+`kvld{%vAbEKUK)7#2gd8UHCxeg6K<2P0QQ3k2!i~8Ct zrthms$NFefgPDl)(NIcfAd1snJ7aNs|NE}_SXp>MdUm({7;3$hom zcWy98A!u%(a0@OAEoShD1NT9)-YyG&m}fCv{1W91^#qs7w_^t>22$m8n8yN|J)! zpI}R|c-6`e-@TI_?@j!A$6n;w?1?{{n315!^MT3eF*1tF?3jsFTtB?z-n<#@2lb-l5gqNcTyzG9WbmFZUT%i%__D9ALbp+V#{s*#%2 zDZFC6CWvU~T}_aHi-n1Fv*I~N3z;^H_c2zudtJBZSmLz!?W&fV9i#)~0Edn}wbv*PW$N68xU zxuV-6R{5gaG~%r_+Q}x5INly_qw(hjwI_aiOq{bhkaEGB9;N1qwvap4g2(Gq;P(aR z>lk;bOVfiP*Mj3Wv0P4)m2H`eRXx5fY3@@yo|0yDlAh9js~A#p5dXabpPw=+!V|0D z_BfN$A@@ES+f(}eLXYQf?%mlZ_H8jhtJS3qzw8e&ekQ$qM<(K-@{m>R^5BekD7 z-F`uWb0InYzMF)(SSLJP2^*cBxm+olmR=E+p5=0A>YkG;TL;?Z@P$ftTyZo>ZWF<^ zK(9o^R%Al9WsV~A(^0i8BfTVYbhArEnd2K zd_}>;s|<_sD}dM)`*I2_;P zCZh*D(_a;26EsAO6KZQXmOnGm!~y~1X_ed-`#2gSd@E}Z+g1X&lZQt1t868{+6(=`2AWVG z`LLfqqn#!r6AB3*U>lFW=KQhX&TOE_v00eu>SGah$uL?)x#tKfHB{u|doyujl z-kW1p(5MA?>u5%}HwXG=nzDRX&iH3DmqIv|+(2NJ+`eaZk|uj16ni+0M9$hTettW1 zTsK>e&l}wf7Oa!Kf>xLM#FZPk*9>LuT9v*A{=S~BcUiVTLpJtC*K^R3=(4kW)95og zaJZTGo}k?{1c%SQAe)elWqgId?S#s9~bo02n#Z&;}$B*c_t`1Y#fuXa>L(vO=(rhJY**DUASSB$gQg zw6MoUi0<+4$$cb#GXhkRC}RvL{Sg%y--wzgi~-skt34CI1j(wJ0yapjHU->}NN)yM zAu-Ghutegj8DNY=S#!XI_}@M-2qX+EHwU;C|KB#SwiAN?wf$qoSDJP&~_*#f_7 z^W8OfzXl=0Mbt<9A9<$qZ+j0hfDWc-2aqCb<79{2qRbyg2sUo_yEgMkrd0knLue21 zA?336h=XaWf8-c2*Si2A@BjTZ*i>9i%^|*7iio^9{z>As`d_i*_5cmibqDD>sQnj{ ztqd^m{O$VZe-Ys}hy{dGi7ez#hOCSnJ6NH5;O}e1;j({N25vhWp zbWlNx6s4~6a$$Gh@?O60-hbx&r_Gs3zBx&pBN`eYqR`hu5~2|Brz++V1vf!u%p0Fij2T5Dxo?@2!_u&7h&MYl{^L>NWl(}qW<=Xr{Z#@ zVX8M*>R5vt(&q*w|B8wyrC>G10)-)2K%YBWsTZ z5=P&*9;B3RQKys~1|)IvZX`cO%+?EJo&H4yEP-D&pnDqO;@Aj zi?)Hl6ET@?N8USEn}hD(a$J+!nK(=f?87=`94ySLfnIu}M)Qbbm0g0S&N;w<{b($^ z*se6T)=rh%C@z|9lh3HKD<2i^?*QT0{S0u$D7KAkirCFJ_Oe@bIQ9S$GQF}WUK5}7 zUSIk`V;}zwx+kXPSK3+V> zfPSDn-yzC5Xv=kF)sHZ8KL*>hpx{=O5iMKpEPGbJ?p5^Th|`1ug}hH)d>O~jm%n{; zrT4*L68fvyTzX4WS^B6mAJZDDLnr7CvD~tbX`YLjmJ8+Vdw%;dKUy3vKI*HH@`w-O&sqqTtRl9@ZYOPL9p3v8 z#$(q~cReokF|A%2r@ldY3@(S3u*CaXW(=#6D#lioGg`#)z-&H@UZ+FJ;S#q;vi9Ry z>CRFYbINz|?*a)0wMjC~`^Zxq;K7(H6fVk3Vl5gpR;v1c0fmF#toR9-i+_S7lEY!6~ecxURbg2I^?RdLmY3+|czmC5XtmjVNG?u#cHUHt&q)Bn3 z;%j0Ql_E~fqP-K9c~3`@MxqJJ!>k<7aA1-Ke zF9hpykv`wWyfd3I-++)xqqo~94u^HyrQSC9=r$IcDsk<>kE+96D<`LAiMwr;WL*4j zE2g-1<{68{FJ7=pdABZtl^?tz-=zG9pe;Ei2`OeULSOj_&t|9^El~;|T_lh3wftH6 ziC4LddMqh?r>rP<<`^hjDZcVBK;?B|?ev%uyPGmmTIP3CW4!Ed%6Sebi%7bRY3tS9 zvz9PW99dplYu6BSXOAivR({4etb9q5KU?v1{bS{g2i?kyDFq8$cd(g8tpW^|7}Lr{ z+w!FLrOehv`|>dB28;W<)fsvV5Bguvw23p{72NL=R*Wdh5_brBamwkgy6NQN%OM6G zag~HezsldmvZ+goIG!>3Vj~;iyDy);w%jwdhZeMr^A~ylWz0lG%XhDv)L5jrBa2Ch zUtBW96zAI2T8miCc;SH^3Uv^}T0}GOtgse}u`S5taaERE;)Yd|Km2}^)c8|xpFq50 z!0-MOnWi<-gZBpqWHrR+w=)Zk*siHKMkm__7iydhP-hV=XnDBLe#tv2jy+LvZSHzn zo>)Rl*{A(Rbu(q;Y0e)HG&-{kP2Ig`l^^c7Qpfkdw!x@oxD!-oV3!KgJZ*#{7M-gT zUrY>HRjq1%ske5BNg7(2xT;iY-Js_lH-GNI`W=OS5LJ-^VZ6z~E|_&TE& z>5tj8@cWKS=W{O}r^I^cpn4qX4v?Js;WrmA(A|C?{pzD>s-j5j`-cjwVXpmNoL+lO z3)7bd)KeCkBZ6L~;S8&Wh5itmX(dL72)oj>$SRj3L@+Aox9af{Gx_ve!pRt^INsN) zHA=xh>9WR_woq!r^}3P#syQUBw}R211uq)?mi7zriBsFeW|b4G=ij@hTXknxM(t`f zIrk(dpGWa{XoaVu;e7S3?+x-9rW>Eu~6vK`tGrN-;D z<~Z47XC(f9Pc0)cSpJ^JNN^D8 za(1wMLbX&Tdr$qvO!kf|4@-Q7iz6G4_Pi?FU_B- z57C`heO~|8rv`hqfY|eO`!0j$Q|!(F{Y&~<8yU~`Rv)9wy3meieY*9lbU)@hvnJ0Q zYM1J#wUWLKPc~EUM4X!t(kwU8Zb#ZNu+afouCL`vn3e~Y8qdBb$Bt6VSt^()QSj?# zf0*CrXXyM$5g)5D=bWk}`l|?QB%vSp6(sV|iO4Y#9rSYNMsSNllVk6|Fp9z}H zD9y#{`gI2gsf=rkFSg4_b~@8-u(t7}f4?UiY4$)*`dN5?N0cOIB5ihl#8qhn-DJP} zV|l0PeNC(hejxJnYYX?U9SHpzKdd9_lU2BJIQ_%FN_R!g%Z2P`4lxn8s(!-fjr=Sn z!UKK}qTJL!vHX~^&`@P!-bLQ0Hw=S+<(Kh=wii>WRgD@&qY!DT&X&!6uPKjyLuwM`fA3_O4FZmIK&ubXZ^H)skh}VP{-AP!z=fZ6^nGTs+#Idu>k`kMs*G93ZpJuK-ZP;t& zUj3LOV~CesLc#;-A)HSLR)&SWtdy+dsxx(y!~DPyai1>kvSxZaZ=6I9-**z<%$py_ zTubHlS&IE9w}rVqB*Ll(E?k@1HRO-uk&2VbQ@D_Tbn!;|L!*rlvP*!Z>yshJn+b(& z&5&znNw5{Ylncl!TeegjmQ-e$<~)N4UT6e~znN5EA??DU6-K4iT6d z8;U)xUoI?vM>maL9Dk`~CCXM?3N|Gkx0;n2iQduFdOBh$O6!7Ki)U!+OrOm4*_gB% zO8+<^lfi2#i_vpRl_6p@L|y24g!AN0-%)pS2$hM{G340k!H-zGOb8dgq7@W%WA3V@ z^!ZA~E$1q%B`~Tquy#2TRB)5T1?BS%$xI#c|J@;wBJj8F-X&{7`1XB%Eu9F)-mR6R z+j#ws)6tysC*jepo&RtKZWL2{VQD-=Syslb51L*^nMh-_ zgo>(=xQV2xu<-c>X7ooYREJiDt@)7RjUGNu>D}9νb2K!b4cI3IY*7b}xc+N*Y zZgb|LIPB(aFYGVxV%H-0Y+A2jKQ-BG$(+rc7a8#r*$Dny``DOTPGc~Q#CKs3p*fJi zH)@cKIZ%M-eKvpvg3JK}JSjB?(s-<0HV6L1upqz|u+#=ygIc&s&?Q@N8AiNR9YzW} zfQDvl@onDmL={G3JD>?;rX5iGM~TS(NU2uD9-xn0={bO_Fk9pR>|vz64m@BCz7A|* zoWBliU{rAgS76L?1XpQKbZjgLgaAb81OyY}rf8sNPJn^~=I{FNy<{dtAPPzG{84Xu z{K^fno`rxTpocEw+suT$C2FY00#Lxdsht6u;MJ!iHeq^)8ZvMOY%p;XCajnLA>zNE zhR{}j1roinJHkYSK$PJ-V6hW{biVyAJw#_eNQx`&j|E0^PR`|t$v2?8XD$Na3qFy~2tKuqDY6+98spW-jw3cMv8bO81sO#PRX+zqh8Qa(4l z^cLNb6hn1#Nl*w(US>E>2X4@z1~e(yY|;<;h=x2+k+1xgWq?)6M-ZYVSV^d5XjsMZ?B?!Y(J?DsG&@+<8_q4 z%yso+=BGYjKmYGt_~$nX@3;g1h@J@0tqCBs1K@_-jR4jE*-@Dmw#nlUhYIok9*%0Q gzwGL601*ONU1<3RKvQWWv=IeN2*e+H_|+i(0~F4g#{d8T diff --git a/src/main/java/com/taobao/profile/config/ConfigureProperties.java b/src/main/java/com/taobao/profile/config/ConfigureProperties.java new file mode 100644 index 0000000..6e081c0 --- /dev/null +++ b/src/main/java/com/taobao/profile/config/ConfigureProperties.java @@ -0,0 +1,194 @@ +package com.taobao.profile.config; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.io.Reader; +import java.io.Writer; +import java.util.Collection; +import java.util.Enumeration; +import java.util.InvalidPropertiesFormatException; +import java.util.Map; +import java.util.Properties; +import java.util.Set; + +import com.taobao.profile.utils.Utilities; +import com.taobao.profile.utils.VariableNotFoundException; + +/** + * 用于加载配置文件的properties类,与java默认的不同,在调用get方法返回value时,会对value + * 会检查是否存在变量(如:${user.home}),如果存在,会将变量替换成具体的值。 + * 该类使用dectorator设计模式 + * @author manlge + * @since 2013-08-18 + */ +public class ConfigureProperties extends Properties { + + /** + * + */ + private static final long serialVersionUID = -3868173073422671544L; + + private Properties delegate; + + private Properties context; + + + public ConfigureProperties(Properties delegate, Properties context) { + super(); + this.delegate = delegate; + this.context = context; + } + + public Object setProperty(String key, String value) { + return delegate.setProperty(key, value); + } + + public void load(Reader reader) throws IOException { + delegate.load(reader); + } + + public int size() { + return delegate.size(); + } + + public boolean isEmpty() { + return delegate.isEmpty(); + } + + public Enumeration keys() { + return delegate.keys(); + } + + public Enumeration elements() { + return delegate.elements(); + } + + public void load(InputStream inStream) throws IOException { + delegate.load(inStream); + } + + public boolean contains(Object value) { + return delegate.contains(value); + } + + public boolean containsValue(Object value) { + return delegate.containsValue(value); + } + + public boolean containsKey(Object key) { + return delegate.containsKey(key); + } + + public Object get(Object key) { + return delegate.get(key); + } + + public Object put(Object key, Object value) { + return delegate.put(key, value); + } + + public Object remove(Object key) { + return delegate.remove(key); + } + + public void putAll(Map t) { + delegate.putAll(t); + } + + public void clear() { + delegate.clear(); + } + + public Object clone() { + return delegate.clone(); + } + + public String toString() { + return delegate.toString(); + } + + public Set keySet() { + return delegate.keySet(); + } + + public Set> entrySet() { + return delegate.entrySet(); + } + + public void save(OutputStream out, String comments) { + delegate.save(out, comments); + } + + public void store(Writer writer, String comments) throws IOException { + delegate.store(writer, comments); + } + + public Collection values() { + return delegate.values(); + } + + public void store(OutputStream out, String comments) throws IOException { + delegate.store(out, comments); + } + + public boolean equals(Object o) { + return delegate.equals(o); + } + + public int hashCode() { + return delegate.hashCode(); + } + + public void loadFromXML(InputStream in) throws IOException, + InvalidPropertiesFormatException { + delegate.loadFromXML(in); + } + + public void storeToXML(OutputStream os, String comment) throws IOException { + delegate.storeToXML(os, comment); + } + + public void storeToXML(OutputStream os, String comment, String encoding) + throws IOException { + delegate.storeToXML(os, comment, encoding); + } + + public String getProperty(String key) { + String value = delegate.getProperty(key); + try { + return Utilities.repleseVariables(value, context); + } catch (VariableNotFoundException e) { + throw new RuntimeException(e); + } + } + + public String getProperty(String key, String defaultValue) { + String value = delegate.getProperty(key, defaultValue); + try { + return Utilities.repleseVariables(value, context); + } catch (VariableNotFoundException e) { + throw new RuntimeException(e); + } + } + + public Enumeration propertyNames() { + return delegate.propertyNames(); + } + + public Set stringPropertyNames() { + return delegate.stringPropertyNames(); + } + + public void list(PrintStream out) { + delegate.list(out); + } + + public void list(PrintWriter out) { + delegate.list(out); + } + + +} diff --git a/src/main/java/com/taobao/profile/config/ProfConfig.java b/src/main/java/com/taobao/profile/config/ProfConfig.java index 60a661f..9e6f376 100644 --- a/src/main/java/com/taobao/profile/config/ProfConfig.java +++ b/src/main/java/com/taobao/profile/config/ProfConfig.java @@ -13,7 +13,6 @@ import java.io.InputStream; import java.util.Properties; -import com.taobao.profile.utils.Utilities; import com.taobao.profile.utils.VariableNotFoundException; /** @@ -125,7 +124,7 @@ private void parseProperty(File path) { Properties resource = new Properties(); try { resource.load(new FileReader(path)); - loadConfig(resource); + loadConfig(new ConfigureProperties(resource, System.getProperties())); } catch (Exception e) { e.printStackTrace(); } @@ -134,15 +133,13 @@ private void parseProperty(File path) { /** * 加载配置 * @param properties - * @throws ParseException */ private void loadConfig(Properties properties) throws VariableNotFoundException { - Properties context = System.getProperties(); String startProfTime = properties.getProperty("startProfTime"); String endProfTime = properties.getProperty("endProfTime"); - String logFilePath = Utilities.repleseVariables(properties.getProperty("logFilePath"), context) ; - String methodFilePath = Utilities.repleseVariables(properties.getProperty("methodFilePath"), context) ; - String samplerFilePath = Utilities.repleseVariables(properties.getProperty("samplerFilePath"), context) ; + String logFilePath = properties.getProperty("logFilePath"); + String methodFilePath = properties.getProperty("methodFilePath"); + String samplerFilePath = properties.getProperty("samplerFilePath"); String includePackageStartsWith = properties.getProperty("includePackageStartsWith"); String eachProfUseTime = properties.getProperty("eachProfUseTime"); String eachProfIntervalTime = properties.getProperty("eachProfIntervalTime"); @@ -193,7 +190,7 @@ private void parse(String configName) { try{ Properties properties = new Properties(); properties.load(in); - loadConfig(properties); + loadConfig(new ConfigureProperties(properties, System.getProperties())); } finally{ in.close(); } diff --git a/src/test/java/com/taobao/profile/test/ConfigurePropertiesTest.java b/src/test/java/com/taobao/profile/test/ConfigurePropertiesTest.java new file mode 100644 index 0000000..9b9bf56 --- /dev/null +++ b/src/test/java/com/taobao/profile/test/ConfigurePropertiesTest.java @@ -0,0 +1,19 @@ +package com.taobao.profile.test; + +import java.util.Properties; + +import org.junit.Assert; +import org.junit.Test; + +import com.taobao.profile.config.ConfigureProperties; + +public class ConfigurePropertiesTest { + + @Test + public void testConfigureProperties(){ + Properties prop = new Properties(); + prop.put("log.file.path", "${user.home}/tprofiler.log"); + Properties properties = new ConfigureProperties(prop, System.getProperties()); + Assert.assertEquals(properties.getProperty("log.file.path"), System.getProperty("user.home") + "/tprofiler.log" ); + } +} From 97e97ffb007c5378edf2bfcd60a15edaba95dfd3 Mon Sep 17 00:00:00 2001 From: manlge Date: Sun, 18 Aug 2013 20:19:30 +0800 Subject: [PATCH 3/7] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E6=9F=A5=E6=89=BE=E5=8A=9F=E8=83=BD=201.=20?= =?UTF-8?q?=E7=B3=BB=E7=BB=9F=E5=8F=82=E6=95=B0-Dprofile.properties=3D/pat?= =?UTF-8?q?h/profile.properties=202.=20=E5=BD=93=E5=89=8D=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E5=A4=B9=E4=B8=8B=E7=9A=84profile.properties=203.=20~?= =?UTF-8?q?/.tprofiler/profile.properties=204.=20=E9=BB=98=E8=AE=A4jar?= =?UTF-8?q?=E5=8C=85=E4=B8=AD=E7=9A=84profile.properties?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dist/tprofiler.jar | Bin 94485 -> 94982 bytes .../com/taobao/profile/config/ProfConfig.java | 39 +++++++++++++----- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/dist/tprofiler.jar b/dist/tprofiler.jar index 0142e05a244e867da5752a73982315480f1ddcd7..9c3682a3f794f3c2e8ab4dcb519a6681c8f3ee8c 100644 GIT binary patch delta 5172 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 VtJEUyT0rAh!G5}L7pRj#{2#M4!SetB diff --git a/src/main/java/com/taobao/profile/config/ProfConfig.java b/src/main/java/com/taobao/profile/config/ProfConfig.java index 9e6f376..5c9772c 100644 --- a/src/main/java/com/taobao/profile/config/ProfConfig.java +++ b/src/main/java/com/taobao/profile/config/ProfConfig.java @@ -102,17 +102,36 @@ public class ProfConfig { * 构造方法 */ public ProfConfig(String defaultPath) { - String configPath = System.getProperty("profile.properties"); - if (configPath == null || configPath.isEmpty()) { - parse(defaultPath); - } else { - File file = new File(configPath); - if (file.exists()) { - parseProperty(file); - } else { - parse(defaultPath); - } + + boolean debug = "true".equalsIgnoreCase(System.getProperty("tprofiler.debug")); + /* + * 查找顺序: + * 1. 系统参数-Dprofile.properties=/path/profile.properties + * 2. 当前文件夹下的profile.properties + * 3. 有户文件夹~/.tprofiler/profile.properties,如:/home/manlge/.tprofiler/profile.properties + * 4. 默认jar包中的profile.properties + */ + String configPaths[] = {System.getProperty("profile.properties"), + "profile.properties", + new File(System.getProperty("user.home"), "/.tprofiler/profile.properties").getAbsolutePath()}; + + for (String configPath : configPaths){ + if (configPath != null && !configPath.isEmpty()) { + File file = new File(configPath); + if (file.exists()) { + if (debug){ + System.out.println(String.format("load configuration from \"%s\".", file.getAbsolutePath())); + } + parseProperty(file); + return; + } + } } + //加载默认配置 + if (debug){ + System.out.println(String.format("load configuration from \"%s\".", Thread.currentThread().getContextClassLoader().getResource(defaultPath))); + } + parse(defaultPath); } /** From 1e882c05e8728b93b0ec69cc4b30d81664e935d8 Mon Sep 17 00:00:00 2001 From: manlge Date: Mon, 19 Aug 2013 20:50:05 +0800 Subject: [PATCH 4/7] =?UTF-8?q?=E9=85=8D=E7=BD=AE=E5=8A=A0=E8=BD=BD?= =?UTF-8?q?=E7=9B=B8=E5=85=B3=E4=BC=98=E5=8C=96=E5=8F=8A=E5=8D=95=E6=97=A0?= =?UTF-8?q?=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/taobao/profile/Manager.java | 6 +- .../profile/config/ConfigureProperties.java | 46 +++++++- .../com/taobao/profile/config/ProfConfig.java | 105 +++++++++++------- src/main/resources/profile.properties | 16 ++- .../profile/test/ConfigurePropertiesTest.java | 28 ++++- 5 files changed, 150 insertions(+), 51 deletions(-) diff --git a/src/main/java/com/taobao/profile/Manager.java b/src/main/java/com/taobao/profile/Manager.java index 8631abf..83b8600 100644 --- a/src/main/java/com/taobao/profile/Manager.java +++ b/src/main/java/com/taobao/profile/Manager.java @@ -26,10 +26,6 @@ * @since 2012-1-9 */ public class Manager { - /** - * 默认配置文件 - */ - private static final String DEFAULT_CONFIG = "profile.properties"; /** * 远程连接端口 @@ -121,7 +117,7 @@ private Manager() {} * 初始化配置 */ public void initialization() { - profConfig = new ProfConfig(DEFAULT_CONFIG); + profConfig = new ProfConfig(); NEED_NANO_TIME = profConfig.isNeedNanoTime(); IGNORE_GETSET_METHOD = profConfig.isIgnoreGetSetMethod(); METHOD_LOG_PATH = profConfig.getMethodFilePath(); diff --git a/src/main/java/com/taobao/profile/config/ConfigureProperties.java b/src/main/java/com/taobao/profile/config/ConfigureProperties.java index 6e081c0..7008c60 100644 --- a/src/main/java/com/taobao/profile/config/ConfigureProperties.java +++ b/src/main/java/com/taobao/profile/config/ConfigureProperties.java @@ -18,9 +18,51 @@ import com.taobao.profile.utils.VariableNotFoundException; /** - * 用于加载配置文件的properties类,与java默认的不同,在调用get方法返回value时,会对value + *

用于加载配置文件的properties类,与java默认的不同,在调用get方法返回value时,会对value * 会检查是否存在变量(如:${user.home}),如果存在,会将变量替换成具体的值。 - * 该类使用dectorator设计模式 + *

该类使用dectorator设计模式 + * + *

示例文件内容(profile.properties): + *

+ *   logFileName = tprofiler.log
+ *   methodFileName = tmethod.log
+ *   samplerFileName = tsampler.log
+ *   
+ *   startProfTime = 9:00:00
+ *   endProfTime = 11:00:00
+ *   eachProfUseTime = 5
+ *   eachProfIntervalTime = 50
+ *   samplerIntervalTime = 20
+ *   port = 50000
+ *   debugMode = false
+ *   needNanoTime = false
+ *   ignoreGetSetMethod = true
+ *   
+ *   logFilePath = ${user.home}/logs/${logFileName}
+ *   methodFilePath = ${user.home}/logs/${methodFileName}
+ *   samplerFilePath = ${user.home}/logs/${samplerFileName}
+ *   
+ *   excludeClassLoader = org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader
+ *   includePackageStartsWith = com.taobao;com.taobao.common
+ *   excludePackageStartsWith = com.taobao.sketch;org.apache.velocity;com.alibaba;com.taobao.forest.domain.dataobject
+ * 
+ *

未例代码: + *

+ *   Properties properties = new Properties();
+ *   InputStream in = getClass().getClassLoader().getResourceAsStream("profile.properties");
+ *   properties.load(in);
+ *
+ *   Properties context = new Properties(System.getProperties());
+ *   context.putAll(System.getProperties());
+ *   context.putAll(properties);
+ *   try{
+ *     ConfigureProperties configureProperties = new ConfigureProperties(properties, context);
+ *     String logFilePath = configureProperties.getProperty("logFilePath");
+ *     Assert.assertEquals(logFilePath, System.getProperty("user.home") + "/logs/tprofiler.log");
+ *   }finally{
+ *     in.close();
+ *   }
+ * 
* @author manlge * @since 2013-08-18 */ diff --git a/src/main/java/com/taobao/profile/config/ProfConfig.java b/src/main/java/com/taobao/profile/config/ProfConfig.java index 5c9772c..be55ed7 100644 --- a/src/main/java/com/taobao/profile/config/ProfConfig.java +++ b/src/main/java/com/taobao/profile/config/ProfConfig.java @@ -8,9 +8,13 @@ */ package com.taobao.profile.config; +import java.io.BufferedOutputStream; import java.io.File; +import java.io.FileOutputStream; import java.io.FileReader; +import java.io.IOException; import java.io.InputStream; +import java.io.OutputStream; import java.util.Properties; import com.taobao.profile.utils.VariableNotFoundException; @@ -22,6 +26,17 @@ * @since 2010-6-22 */ public class ProfConfig { + + /** + * 配置文件名 + */ + private static final String CONFIG_FILE_NAME = "profile.properties"; + + /** + * 默认的配置文件路径 + */ + private File DEFAULT_PROFILE_PATH = new File(System.getProperty("user.home"), "/.tprofiler/" + CONFIG_FILE_NAME); + /** * 开始profile时间 @@ -101,7 +116,7 @@ public class ProfConfig { /** * 构造方法 */ - public ProfConfig(String defaultPath) { + public ProfConfig() { boolean debug = "true".equalsIgnoreCase(System.getProperty("tprofiler.debug")); /* @@ -111,39 +126,70 @@ public ProfConfig(String defaultPath) { * 3. 有户文件夹~/.tprofiler/profile.properties,如:/home/manlge/.tprofiler/profile.properties * 4. 默认jar包中的profile.properties */ - String configPaths[] = {System.getProperty("profile.properties"), - "profile.properties", - new File(System.getProperty("user.home"), "/.tprofiler/profile.properties").getAbsolutePath()}; + File configFiles[] = { + new File(System.getProperty(CONFIG_FILE_NAME)), + new File(CONFIG_FILE_NAME), + DEFAULT_PROFILE_PATH + }; - for (String configPath : configPaths){ - if (configPath != null && !configPath.isEmpty()) { - File file = new File(configPath); - if (file.exists()) { - if (debug){ - System.out.println(String.format("load configuration from \"%s\".", file.getAbsolutePath())); - } - parseProperty(file); - return; - } + for (File file : configFiles){ + if (file.exists() && file.isFile()) { + if (debug){ + System.out.println(String.format("load configuration from \"%s\".", file.getAbsolutePath())); + } + parseProperty(file); + return; } } //加载默认配置 if (debug){ - System.out.println(String.format("load configuration from \"%s\".", Thread.currentThread().getContextClassLoader().getResource(defaultPath))); + System.out.println(String.format("load configuration from \"%s\".", DEFAULT_PROFILE_PATH.getAbsolutePath())); + } + try { + extractDefaultProFile(); + parseProperty(DEFAULT_PROFILE_PATH); + } catch (IOException e) { + throw new RuntimeException("error load config file", e); } - parse(defaultPath); + } /** + * 解压默认的配置文件到~/.tprofiler/profile.properties,可以作为模板,以便用户编辑 + * @throws IOException + */ + private void extractDefaultProFile() throws IOException { + InputStream in = getClass().getClassLoader().getResourceAsStream(CONFIG_FILE_NAME); + OutputStream out = null; + try{ + File profileDirectory = DEFAULT_PROFILE_PATH.getParentFile(); + if (!profileDirectory.exists()){ + profileDirectory.mkdirs(); + } + out = new BufferedOutputStream(new FileOutputStream(DEFAULT_PROFILE_PATH)); + byte[] buffer = new byte[1024]; + for (int len = -1; (len = in.read(buffer)) != -1;){ + out.write(buffer, 0, len); + } + + }finally{ + in.close(); + out.close(); + } + } + + /** * 解析用户自定义配置文件 - * * @param path */ private void parseProperty(File path) { - Properties resource = new Properties(); + Properties properties = new Properties(); try { - resource.load(new FileReader(path)); - loadConfig(new ConfigureProperties(resource, System.getProperties())); + properties.load(new FileReader(path)); + Properties context = new Properties(); + context.putAll(System.getProperties()); + context.putAll(properties); + loadConfig(new ConfigureProperties(properties, context)); } catch (Exception e) { e.printStackTrace(); } @@ -198,25 +244,6 @@ private void loadConfig(Properties properties) throws VariableNotFoundException } } - /** - * 解析默认配置文件 - * - * @param configName - */ - private void parse(String configName) { - try { - InputStream in = getClass().getResourceAsStream("/" + configName); - try{ - Properties properties = new Properties(); - properties.load(in); - loadConfig(new ConfigureProperties(properties, System.getProperties())); - } finally{ - in.close(); - } - } catch (Exception e) { - e.printStackTrace(); - } - } /** * @return diff --git a/src/main/resources/profile.properties b/src/main/resources/profile.properties index d9a9682..0986555 100644 --- a/src/main/resources/profile.properties +++ b/src/main/resources/profile.properties @@ -1,3 +1,9 @@ +#log file name +logFileName = tprofiler.log +methodFileName = tmethod.log +samplerFileName = tsampler.log + +#basic configuration items startProfTime = 9:00:00 endProfTime = 11:00:00 eachProfUseTime = 5 @@ -7,9 +13,13 @@ port = 50000 debugMode = false needNanoTime = false ignoreGetSetMethod = true -logFilePath = ${user.home}/logs/tprofiler.log -methodFilePath = ${user.home}/logs/tmethod.log -samplerFilePath = ${user.home}/logs/tsampler.log + +#file paths +logFilePath = ${user.home}/logs/${logFileName} +methodFilePath = ${user.home}/logs/${methodFileName} +samplerFilePath = ${user.home}/logs/${samplerFileName} + +#exclude & excludes items excludeClassLoader = org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader includePackageStartsWith = com.taobao;com.taobao.common excludePackageStartsWith = com.taobao.sketch;org.apache.velocity;com.alibaba;com.taobao.forest.domain.dataobject diff --git a/src/test/java/com/taobao/profile/test/ConfigurePropertiesTest.java b/src/test/java/com/taobao/profile/test/ConfigurePropertiesTest.java index 9b9bf56..244f741 100644 --- a/src/test/java/com/taobao/profile/test/ConfigurePropertiesTest.java +++ b/src/test/java/com/taobao/profile/test/ConfigurePropertiesTest.java @@ -1,5 +1,7 @@ package com.taobao.profile.test; +import java.io.IOException; +import java.io.InputStream; import java.util.Properties; import org.junit.Assert; @@ -12,8 +14,30 @@ public class ConfigurePropertiesTest { @Test public void testConfigureProperties(){ Properties prop = new Properties(); - prop.put("log.file.path", "${user.home}/tprofiler.log"); - Properties properties = new ConfigureProperties(prop, System.getProperties()); + prop.put("file.name", "tprofiler.log"); + prop.put("log.file.path", "${user.home}/${file.name}"); + Properties context = System.getProperties(); + context.putAll(prop); + + Properties properties = new ConfigureProperties(prop, context); Assert.assertEquals(properties.getProperty("log.file.path"), System.getProperty("user.home") + "/tprofiler.log" ); } + + @Test + public void testConfigure() throws IOException{ + Properties properties = new Properties(); + InputStream in = getClass().getClassLoader().getResourceAsStream("profile.properties"); + properties.load(in); + + Properties context = new Properties(System.getProperties()); + context.putAll(System.getProperties()); + context.putAll(properties); + try{ + ConfigureProperties configureProperties = new ConfigureProperties(properties, context); + String logFilePath = configureProperties.getProperty("logFilePath"); + Assert.assertEquals(logFilePath, System.getProperty("user.home") + "/logs/tprofiler.log"); + }finally{ + in.close(); + } + } } From 75da7b9c10e5d0d80e62df39caeddaf8e7747e7c Mon Sep 17 00:00:00 2001 From: manlge Date: Mon, 19 Aug 2013 20:50:05 +0800 Subject: [PATCH 5/7] =?UTF-8?q?=E9=85=8D=E7=BD=AE=E5=8A=A0=E8=BD=BD?= =?UTF-8?q?=E7=9B=B8=E5=85=B3=E4=BC=98=E5=8C=96=E5=8F=8A=E5=8D=95=E6=97=A0?= =?UTF-8?q?=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dist/profile.properties | 16 ++- dist/tprofiler.jar | Bin 94982 -> 95208 bytes src/main/java/com/taobao/profile/Manager.java | 6 +- .../profile/config/ConfigureProperties.java | 46 +++++++- .../com/taobao/profile/config/ProfConfig.java | 105 +++++++++++------- src/main/resources/profile.properties | 16 ++- .../profile/test/ConfigurePropertiesTest.java | 28 ++++- 7 files changed, 163 insertions(+), 54 deletions(-) diff --git a/dist/profile.properties b/dist/profile.properties index d9a9682..0986555 100644 --- a/dist/profile.properties +++ b/dist/profile.properties @@ -1,3 +1,9 @@ +#log file name +logFileName = tprofiler.log +methodFileName = tmethod.log +samplerFileName = tsampler.log + +#basic configuration items startProfTime = 9:00:00 endProfTime = 11:00:00 eachProfUseTime = 5 @@ -7,9 +13,13 @@ port = 50000 debugMode = false needNanoTime = false ignoreGetSetMethod = true -logFilePath = ${user.home}/logs/tprofiler.log -methodFilePath = ${user.home}/logs/tmethod.log -samplerFilePath = ${user.home}/logs/tsampler.log + +#file paths +logFilePath = ${user.home}/logs/${logFileName} +methodFilePath = ${user.home}/logs/${methodFileName} +samplerFilePath = ${user.home}/logs/${samplerFileName} + +#exclude & excludes items excludeClassLoader = org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader includePackageStartsWith = com.taobao;com.taobao.common excludePackageStartsWith = com.taobao.sketch;org.apache.velocity;com.alibaba;com.taobao.forest.domain.dataobject diff --git a/dist/tprofiler.jar b/dist/tprofiler.jar index 9c3682a3f794f3c2e8ab4dcb519a6681c8f3ee8c..6e899f4d813bc8e91383a32ef1857048fe8a912a 100644 GIT binary patch delta 10888 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 diff --git a/src/main/java/com/taobao/profile/Manager.java b/src/main/java/com/taobao/profile/Manager.java index 8631abf..83b8600 100644 --- a/src/main/java/com/taobao/profile/Manager.java +++ b/src/main/java/com/taobao/profile/Manager.java @@ -26,10 +26,6 @@ * @since 2012-1-9 */ public class Manager { - /** - * 默认配置文件 - */ - private static final String DEFAULT_CONFIG = "profile.properties"; /** * 远程连接端口 @@ -121,7 +117,7 @@ private Manager() {} * 初始化配置 */ public void initialization() { - profConfig = new ProfConfig(DEFAULT_CONFIG); + profConfig = new ProfConfig(); NEED_NANO_TIME = profConfig.isNeedNanoTime(); IGNORE_GETSET_METHOD = profConfig.isIgnoreGetSetMethod(); METHOD_LOG_PATH = profConfig.getMethodFilePath(); diff --git a/src/main/java/com/taobao/profile/config/ConfigureProperties.java b/src/main/java/com/taobao/profile/config/ConfigureProperties.java index 6e081c0..7008c60 100644 --- a/src/main/java/com/taobao/profile/config/ConfigureProperties.java +++ b/src/main/java/com/taobao/profile/config/ConfigureProperties.java @@ -18,9 +18,51 @@ import com.taobao.profile.utils.VariableNotFoundException; /** - * 用于加载配置文件的properties类,与java默认的不同,在调用get方法返回value时,会对value + *

用于加载配置文件的properties类,与java默认的不同,在调用get方法返回value时,会对value * 会检查是否存在变量(如:${user.home}),如果存在,会将变量替换成具体的值。 - * 该类使用dectorator设计模式 + *

该类使用dectorator设计模式 + * + *

示例文件内容(profile.properties): + *

+ *   logFileName = tprofiler.log
+ *   methodFileName = tmethod.log
+ *   samplerFileName = tsampler.log
+ *   
+ *   startProfTime = 9:00:00
+ *   endProfTime = 11:00:00
+ *   eachProfUseTime = 5
+ *   eachProfIntervalTime = 50
+ *   samplerIntervalTime = 20
+ *   port = 50000
+ *   debugMode = false
+ *   needNanoTime = false
+ *   ignoreGetSetMethod = true
+ *   
+ *   logFilePath = ${user.home}/logs/${logFileName}
+ *   methodFilePath = ${user.home}/logs/${methodFileName}
+ *   samplerFilePath = ${user.home}/logs/${samplerFileName}
+ *   
+ *   excludeClassLoader = org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader
+ *   includePackageStartsWith = com.taobao;com.taobao.common
+ *   excludePackageStartsWith = com.taobao.sketch;org.apache.velocity;com.alibaba;com.taobao.forest.domain.dataobject
+ * 
+ *

未例代码: + *

+ *   Properties properties = new Properties();
+ *   InputStream in = getClass().getClassLoader().getResourceAsStream("profile.properties");
+ *   properties.load(in);
+ *
+ *   Properties context = new Properties(System.getProperties());
+ *   context.putAll(System.getProperties());
+ *   context.putAll(properties);
+ *   try{
+ *     ConfigureProperties configureProperties = new ConfigureProperties(properties, context);
+ *     String logFilePath = configureProperties.getProperty("logFilePath");
+ *     Assert.assertEquals(logFilePath, System.getProperty("user.home") + "/logs/tprofiler.log");
+ *   }finally{
+ *     in.close();
+ *   }
+ * 
* @author manlge * @since 2013-08-18 */ diff --git a/src/main/java/com/taobao/profile/config/ProfConfig.java b/src/main/java/com/taobao/profile/config/ProfConfig.java index 5c9772c..be55ed7 100644 --- a/src/main/java/com/taobao/profile/config/ProfConfig.java +++ b/src/main/java/com/taobao/profile/config/ProfConfig.java @@ -8,9 +8,13 @@ */ package com.taobao.profile.config; +import java.io.BufferedOutputStream; import java.io.File; +import java.io.FileOutputStream; import java.io.FileReader; +import java.io.IOException; import java.io.InputStream; +import java.io.OutputStream; import java.util.Properties; import com.taobao.profile.utils.VariableNotFoundException; @@ -22,6 +26,17 @@ * @since 2010-6-22 */ public class ProfConfig { + + /** + * 配置文件名 + */ + private static final String CONFIG_FILE_NAME = "profile.properties"; + + /** + * 默认的配置文件路径 + */ + private File DEFAULT_PROFILE_PATH = new File(System.getProperty("user.home"), "/.tprofiler/" + CONFIG_FILE_NAME); + /** * 开始profile时间 @@ -101,7 +116,7 @@ public class ProfConfig { /** * 构造方法 */ - public ProfConfig(String defaultPath) { + public ProfConfig() { boolean debug = "true".equalsIgnoreCase(System.getProperty("tprofiler.debug")); /* @@ -111,39 +126,70 @@ public ProfConfig(String defaultPath) { * 3. 有户文件夹~/.tprofiler/profile.properties,如:/home/manlge/.tprofiler/profile.properties * 4. 默认jar包中的profile.properties */ - String configPaths[] = {System.getProperty("profile.properties"), - "profile.properties", - new File(System.getProperty("user.home"), "/.tprofiler/profile.properties").getAbsolutePath()}; + File configFiles[] = { + new File(System.getProperty(CONFIG_FILE_NAME)), + new File(CONFIG_FILE_NAME), + DEFAULT_PROFILE_PATH + }; - for (String configPath : configPaths){ - if (configPath != null && !configPath.isEmpty()) { - File file = new File(configPath); - if (file.exists()) { - if (debug){ - System.out.println(String.format("load configuration from \"%s\".", file.getAbsolutePath())); - } - parseProperty(file); - return; - } + for (File file : configFiles){ + if (file.exists() && file.isFile()) { + if (debug){ + System.out.println(String.format("load configuration from \"%s\".", file.getAbsolutePath())); + } + parseProperty(file); + return; } } //加载默认配置 if (debug){ - System.out.println(String.format("load configuration from \"%s\".", Thread.currentThread().getContextClassLoader().getResource(defaultPath))); + System.out.println(String.format("load configuration from \"%s\".", DEFAULT_PROFILE_PATH.getAbsolutePath())); + } + try { + extractDefaultProFile(); + parseProperty(DEFAULT_PROFILE_PATH); + } catch (IOException e) { + throw new RuntimeException("error load config file", e); } - parse(defaultPath); + } /** + * 解压默认的配置文件到~/.tprofiler/profile.properties,可以作为模板,以便用户编辑 + * @throws IOException + */ + private void extractDefaultProFile() throws IOException { + InputStream in = getClass().getClassLoader().getResourceAsStream(CONFIG_FILE_NAME); + OutputStream out = null; + try{ + File profileDirectory = DEFAULT_PROFILE_PATH.getParentFile(); + if (!profileDirectory.exists()){ + profileDirectory.mkdirs(); + } + out = new BufferedOutputStream(new FileOutputStream(DEFAULT_PROFILE_PATH)); + byte[] buffer = new byte[1024]; + for (int len = -1; (len = in.read(buffer)) != -1;){ + out.write(buffer, 0, len); + } + + }finally{ + in.close(); + out.close(); + } + } + + /** * 解析用户自定义配置文件 - * * @param path */ private void parseProperty(File path) { - Properties resource = new Properties(); + Properties properties = new Properties(); try { - resource.load(new FileReader(path)); - loadConfig(new ConfigureProperties(resource, System.getProperties())); + properties.load(new FileReader(path)); + Properties context = new Properties(); + context.putAll(System.getProperties()); + context.putAll(properties); + loadConfig(new ConfigureProperties(properties, context)); } catch (Exception e) { e.printStackTrace(); } @@ -198,25 +244,6 @@ private void loadConfig(Properties properties) throws VariableNotFoundException } } - /** - * 解析默认配置文件 - * - * @param configName - */ - private void parse(String configName) { - try { - InputStream in = getClass().getResourceAsStream("/" + configName); - try{ - Properties properties = new Properties(); - properties.load(in); - loadConfig(new ConfigureProperties(properties, System.getProperties())); - } finally{ - in.close(); - } - } catch (Exception e) { - e.printStackTrace(); - } - } /** * @return diff --git a/src/main/resources/profile.properties b/src/main/resources/profile.properties index d9a9682..0986555 100644 --- a/src/main/resources/profile.properties +++ b/src/main/resources/profile.properties @@ -1,3 +1,9 @@ +#log file name +logFileName = tprofiler.log +methodFileName = tmethod.log +samplerFileName = tsampler.log + +#basic configuration items startProfTime = 9:00:00 endProfTime = 11:00:00 eachProfUseTime = 5 @@ -7,9 +13,13 @@ port = 50000 debugMode = false needNanoTime = false ignoreGetSetMethod = true -logFilePath = ${user.home}/logs/tprofiler.log -methodFilePath = ${user.home}/logs/tmethod.log -samplerFilePath = ${user.home}/logs/tsampler.log + +#file paths +logFilePath = ${user.home}/logs/${logFileName} +methodFilePath = ${user.home}/logs/${methodFileName} +samplerFilePath = ${user.home}/logs/${samplerFileName} + +#exclude & excludes items excludeClassLoader = org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader includePackageStartsWith = com.taobao;com.taobao.common excludePackageStartsWith = com.taobao.sketch;org.apache.velocity;com.alibaba;com.taobao.forest.domain.dataobject diff --git a/src/test/java/com/taobao/profile/test/ConfigurePropertiesTest.java b/src/test/java/com/taobao/profile/test/ConfigurePropertiesTest.java index 9b9bf56..244f741 100644 --- a/src/test/java/com/taobao/profile/test/ConfigurePropertiesTest.java +++ b/src/test/java/com/taobao/profile/test/ConfigurePropertiesTest.java @@ -1,5 +1,7 @@ package com.taobao.profile.test; +import java.io.IOException; +import java.io.InputStream; import java.util.Properties; import org.junit.Assert; @@ -12,8 +14,30 @@ public class ConfigurePropertiesTest { @Test public void testConfigureProperties(){ Properties prop = new Properties(); - prop.put("log.file.path", "${user.home}/tprofiler.log"); - Properties properties = new ConfigureProperties(prop, System.getProperties()); + prop.put("file.name", "tprofiler.log"); + prop.put("log.file.path", "${user.home}/${file.name}"); + Properties context = System.getProperties(); + context.putAll(prop); + + Properties properties = new ConfigureProperties(prop, context); Assert.assertEquals(properties.getProperty("log.file.path"), System.getProperty("user.home") + "/tprofiler.log" ); } + + @Test + public void testConfigure() throws IOException{ + Properties properties = new Properties(); + InputStream in = getClass().getClassLoader().getResourceAsStream("profile.properties"); + properties.load(in); + + Properties context = new Properties(System.getProperties()); + context.putAll(System.getProperties()); + context.putAll(properties); + try{ + ConfigureProperties configureProperties = new ConfigureProperties(properties, context); + String logFilePath = configureProperties.getProperty("logFilePath"); + Assert.assertEquals(logFilePath, System.getProperty("user.home") + "/logs/tprofiler.log"); + }finally{ + in.close(); + } + } } From 882d80c704b135f5caf7861579d698d4cbdf4b44 Mon Sep 17 00:00:00 2001 From: manlge Date: Tue, 20 Aug 2013 12:15:39 +0800 Subject: [PATCH 6/7] =?UTF-8?q?=E5=8A=A0=E8=BD=BD=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E6=97=B6=E6=97=B6=E4=BD=BF=E7=94=A8buffer?= =?UTF-8?q?=EF=BC=8C=E5=B9=B6=E5=AE=8C=E5=96=84=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/taobao/profile/config/ProfConfig.java | 28 +++++++++++++------ 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/taobao/profile/config/ProfConfig.java b/src/main/java/com/taobao/profile/config/ProfConfig.java index be55ed7..4e6c4c5 100644 --- a/src/main/java/com/taobao/profile/config/ProfConfig.java +++ b/src/main/java/com/taobao/profile/config/ProfConfig.java @@ -8,6 +8,7 @@ */ package com.taobao.profile.config; +import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; @@ -33,7 +34,7 @@ public class ProfConfig { private static final String CONFIG_FILE_NAME = "profile.properties"; /** - * 默认的配置文件路径 + * 默认的配置文件路径,~/.tprofiler/profile.properties */ private File DEFAULT_PROFILE_PATH = new File(System.getProperty("user.home"), "/.tprofiler/" + CONFIG_FILE_NAME); @@ -118,12 +119,13 @@ public class ProfConfig { */ public ProfConfig() { + //此时配置文件中的debug参数还未读取,因些使用-Dtprofiler.debug=true来读取,用于开发时调试 boolean debug = "true".equalsIgnoreCase(System.getProperty("tprofiler.debug")); /* * 查找顺序: * 1. 系统参数-Dprofile.properties=/path/profile.properties * 2. 当前文件夹下的profile.properties - * 3. 有户文件夹~/.tprofiler/profile.properties,如:/home/manlge/.tprofiler/profile.properties + * 3. 用户文件夹~/.tprofiler/profile.properties,如:/home/manlge/.tprofiler/profile.properties * 4. 默认jar包中的profile.properties */ File configFiles[] = { @@ -146,20 +148,25 @@ public ProfConfig() { System.out.println(String.format("load configuration from \"%s\".", DEFAULT_PROFILE_PATH.getAbsolutePath())); } try { - extractDefaultProFile(); + extractDefaultProfile(); parseProperty(DEFAULT_PROFILE_PATH); } catch (IOException e) { - throw new RuntimeException("error load config file", e); + throw new RuntimeException("error load config file " + DEFAULT_PROFILE_PATH, e); } } /** - * 解压默认的配置文件到~/.tprofiler/profile.properties,可以作为模板,以便用户编辑 + * 解压默认的配置文件到~/.tprofiler/profile.properties,作为模板,以便用户编辑 * @throws IOException */ - private void extractDefaultProFile() throws IOException { - InputStream in = getClass().getClassLoader().getResourceAsStream(CONFIG_FILE_NAME); + private void extractDefaultProfile() throws IOException { + /* + * 这里采用stream进行复制,而不是采用properties.load和save,主要原因为以下2点: + * 1. 性能,stream直接复制快,没有properties解析过程(不过文件较小,解析开销可以忽略) + * 2. properties会造成注释丢失,该文件作为模板提供给用户,包含注释信息 + */ + InputStream in = new BufferedInputStream(getClass().getClassLoader().getResourceAsStream(CONFIG_FILE_NAME)); OutputStream out = null; try{ File profileDirectory = DEFAULT_PROFILE_PATH.getParentFile(); @@ -171,7 +178,6 @@ private void extractDefaultProFile() throws IOException { for (int len = -1; (len = in.read(buffer)) != -1;){ out.write(buffer, 0, len); } - }finally{ in.close(); out.close(); @@ -185,10 +191,14 @@ private void extractDefaultProFile() throws IOException { private void parseProperty(File path) { Properties properties = new Properties(); try { - properties.load(new FileReader(path)); + properties.load(new FileReader(path)); //配置文件原始内容,未进行变量替换 + + //变量查找上下文,采用System.properties和配置文件集合 Properties context = new Properties(); context.putAll(System.getProperties()); context.putAll(properties); + + //加载配置 loadConfig(new ConfigureProperties(properties, context)); } catch (Exception e) { e.printStackTrace(); From 5cf496b7cbcba94ed13323ca47b69052c1aaf88a Mon Sep 17 00:00:00 2001 From: manlge Date: Tue, 20 Aug 2013 12:26:10 +0800 Subject: [PATCH 7/7] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/taobao/profile/config/ProfConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/taobao/profile/config/ProfConfig.java b/src/main/java/com/taobao/profile/config/ProfConfig.java index 4e6c4c5..2c25c41 100644 --- a/src/main/java/com/taobao/profile/config/ProfConfig.java +++ b/src/main/java/com/taobao/profile/config/ProfConfig.java @@ -119,7 +119,7 @@ public class ProfConfig { */ public ProfConfig() { - //此时配置文件中的debug参数还未读取,因些使用-Dtprofiler.debug=true来读取,用于开发时调试 + //此时配置文件中的debug参数还未读取,因此使用-Dtprofiler.debug=true来读取,用于开发时调试 boolean debug = "true".equalsIgnoreCase(System.getProperty("tprofiler.debug")); /* * 查找顺序: