pax_global_header00006660000000000000000000000064135076270030014515gustar00rootroot0000000000000052 comment=e29e0de1bab7a679a9441318c1bde26f5e9929d1 zt-exec-zt-exec-1.11/000077500000000000000000000000001350762700300143735ustar00rootroot00000000000000zt-exec-zt-exec-1.11/.gitignore000066400000000000000000000002221350762700300163570ustar00rootroot00000000000000.classpath .hg/ .hgignore .hgtags .project .settings/ target/ test.log .swp .idea *.iml *.ipr *.iws writeLoop.data src/main/resources/rebel.xml zt-exec-zt-exec-1.11/.mvn/000077500000000000000000000000001350762700300152515ustar00rootroot00000000000000zt-exec-zt-exec-1.11/.mvn/wrapper/000077500000000000000000000000001350762700300167315ustar00rootroot00000000000000zt-exec-zt-exec-1.11/.mvn/wrapper/MavenWrapperDownloader.java000077500000000000000000000105711350762700300242310ustar00rootroot00000000000000/* Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ import java.net.*; import java.io.*; import java.nio.channels.*; import java.util.Properties; public class MavenWrapperDownloader { /** * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. */ private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.0/maven-wrapper-0.4.0.jar"; /** * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to * use instead of the default one. */ private static final String MAVEN_WRAPPER_PROPERTIES_PATH = ".mvn/wrapper/maven-wrapper.properties"; /** * Path where the maven-wrapper.jar will be saved to. */ private static final String MAVEN_WRAPPER_JAR_PATH = ".mvn/wrapper/maven-wrapper.jar"; /** * Name of the property which should be used to override the default download url for the wrapper. */ private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; public static void main(String args[]) { System.out.println("- Downloader started"); File baseDirectory = new File(args[0]); System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); // If the maven-wrapper.properties exists, read it and check if it contains a custom // wrapperUrl parameter. File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); String url = DEFAULT_DOWNLOAD_URL; if(mavenWrapperPropertyFile.exists()) { FileInputStream mavenWrapperPropertyFileInputStream = null; try { mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); Properties mavenWrapperProperties = new Properties(); mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); } catch (IOException e) { System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); } finally { try { if(mavenWrapperPropertyFileInputStream != null) { mavenWrapperPropertyFileInputStream.close(); } } catch (IOException e) { // Ignore ... } } } System.out.println("- Downloading from: : " + url); File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); if(!outputFile.getParentFile().exists()) { if(!outputFile.getParentFile().mkdirs()) { System.out.println( "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'"); } } System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); try { downloadFileFromURL(url, outputFile); System.out.println("Done"); System.exit(0); } catch (Throwable e) { System.out.println("- Error downloading"); e.printStackTrace(); System.exit(1); } } private static void downloadFileFromURL(String urlString, File destination) throws Exception { URL website = new URL(urlString); ReadableByteChannel rbc; rbc = Channels.newChannel(website.openStream()); FileOutputStream fos = new FileOutputStream(destination); fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); fos.close(); rbc.close(); } } zt-exec-zt-exec-1.11/.mvn/wrapper/maven-wrapper.jar000077500000000000000000001363201350762700300222230ustar00rootroot00000000000000PK! META-INF/PKPK!META-INF/MANIFEST.MF 0EC~ κ )mLcſPW{s>3P"Wg8I15 ^I!dj51d8}#S+vI )_joJՄt;97%roiFe|/5=PK !֧+PK!META-INF/maven/PKPK!META-INF/maven/io.takari/PKPK!'META-INF/maven/io.takari/maven-wrapper/PKPK!5META-INF/maven/io.takari/maven-wrapper/pom.properties+K-*ϳ533J//-L+IN,J,*LKL. &%qPKB:9PK!org/PKPK! org/apache/PKPK!org/apache/maven/PKPK!org/apache/maven/wrapper/PKPK!3org/apache/maven/wrapper/BootstrapMainStarter.classVvG`#bup "cA -l3'y^dUa#Ϗ/jlIsNzUu߻ҟI`ðe/hzEV֗=J%n3B,KVznCabO2ǭÇ*2&sܾJ!ziV 9~Q4-J1e8lD7#l\H-]1J<% _^0,Qaطg}& *pŸ7BF}MzmC& tf;N 2 jdѫa`TA twSa" \̬8 m.nR&7oSMA2aH4H0NᴂZvhsEaؙnp[[SfTE 爬Ÿe ,ZuǷ"Ic2O.U'Y)ejr.dFID(p>TAk#|LHe]PǮNUyW#11]5QC2[R!fZ"V4Ek kcY 6rU ?'e_v-jNvz<ײҾق| yBjw&vQs*4ҨeVzLm7j};%c7C}?JvvH8g`h&`;Yp ptf 5 Qk8G^h 2>T5oG?P*fR'&,ZUV{?!^oڴ$;]";xzhgdry~B`G>a6I#kl_~n0LHRF\z1WuziK;PKB` PK!Sorg/apache/maven/wrapper/DefaultDownloader$SystemPropertiesProxyAuthenticator.class]oAKRT~]TV2UWSa2Cf"Jol?eTjIڋnsfy3sfo?n,y/ ‰sF/[ GE@A/V>>9{Ad=!JM]Ah:}~S #zMh>;FSsh`f ϴ (DcI{iH˗2)8۪= 0bDحm cMPСc'*c\ݫ>)s_ֶ|{ʱ7/, S7-1Q* 1[SFapL޼* ib}=oa`Arƃ8b(8˜#I{+IESwۃU?p7fuWy߅mv38v?Kx 2:g]U]jl1(['8JVd1 |bV,H *+g5N QA: E\:a#;h8 NJӱqs9q%bO8G(Gc9¥捉/9zUsfO8br-# S+q gpinN8"7YJ' ְW=7)<-Q\0Ҙg8zE7>,$,RO;?=rX tq9Rcy6I6#a(RXPP\=`7QD+=)qĮTu,"'8V-Q]uc !xj(T2X$8v>/89K;p38҃GFcx&,R&4~[mj-MN<#?%OEs"rD F~%_ȯKE 3jOgL0LgBP:FtFKgZB|U|Q]te9N@'ڋ<`heKU*e |zV6?`,2WJc5\ha5`ŏcJ'PK8~O PK!)org/apache/maven/wrapper/Downloader.classE@x.6ν"H$j'fU<[I&3o&yBhs2IDadS]Dː Ѝe.E"A1~B|3]/G ]NH&s,pyE#KN TQD5ԭvrl^APKqPK!(org/apache/maven/wrapper/Installer.classXi`\u47ɲ-0f˖ƖA2Ʋ%Ye1،5O3Y,@B$–vR&0# KihӅq[ڴi[Jӽ7cwkX#2P"ڎCVkԊѨkPȊp ֝[ AmWzv2gg߁UyD,j+Hb?ܨTVZ O= wVպ2DVLFC>He/H0I36TΫ\[A)LE~՞ jLxP&L Fd'cA}LhZLƳyc?auW?|Cf$8A;ұ*mݺ-]a+kq^Au޾rߓ4uXAF L4>GJP &Vxgh?ʹ !MIL4+,`k 4CbkG;zc3f`\GۂQ_YzЎhYp \uLQn4Y!~̊$ߒ 'D7 n¬ I@OQIdpTwjꘑe'4v2ꧯ-?P1C+QLMe2q֝Ӌ m^5Ϥnb~ Y ;hs̫StF +g^{tT] FFJF0l'MDq';7vۂS@@^:_Ք 1 qs̎ީ|үj%UG%nw1;G7p41t2q/>LжY]r̓x :}GQb%Atn<ĜڥWK1ڱqwi<CɄ9@!x'ʊU1;9QO2! FQƧ7a{/8S MXyv%#`7~Yp`7P`5ʺJoވۑ?#xX/V@ F^8ӢWL<1bFXOl!r^b M|gXK&}ėe>f 'ZX8kM|/xԬ7 X8᰽paǚF+Tm0b:'S*/D%4` $aֺ͝d{J yhpق lD!g$ dmē 9غf*Gze&/Sv !2xwӖI$VWʠ s)j+[lw 5~4=)l#>.Eb) N[(Br9pZ:w&9CFe(S W= a INN!MEB7lGNjuIx6foԔ;ylw1+Gܔ~,*ꩥNC X:g1M{<,c *St=r|Ȑ2+ xz/r0G 6}DI{gUHQ)wآtN&{8a+ 澇( ߞH9 g?]ҴnW)EfnTW;\y|盏4o^44 M`Ygg>[Qܺ"oz.3R1TP Kqqŷ+U`ɣThc Wc&>\ /cG-ee)\^^f\q )\ NݧMt[Q՟®LuoH)p)?!@ j$Bnr**nuO ^QcBUV}$N눮^y͵qho8BZO K렂j=ĐR>*8u- +OU}UpSNBV%\W4pOM_o(=gJT + Ըjʞ<~판4Z`?Q8489Ss6z?\i7VtXbSA FOc՟0HvH$Ҫ?bWP |UJoQ)gp$M'>% |Rv jjj)Mb{ %eC q3L߼Z#%}g(&Ⴞoëbea\YT-|ak>'s*c1vA5BZt(N:an[ $ߞ]x3}]Ȼ/>k rcjA[rMPJ!Y&WҰlԽr7VZ8VrwRN?J*J K4$kSr]oclLɦgPz)L!jsEi<ԏ>t3exzKcJ(tjb-=yͥٳrEO_|;啸x >xsO`%q┣Ժe!$`6Rd͘ΡPɨ/ke7'XԤ/x>t7aN7ԺtIM+ 9#`k8"c񡧩iX/_<>|z"̦Qr/Iu|o>l5䘌eL.*N[C؜|m^1`SJ"^J6h :${WYC^+P.p|Lv'ȩW#I*\OBPKɉ\PK!%org/apache/maven/wrapper/Logger.classSn@=n.ZZJI\$^Z!DU$ER_,+_Nŧ > 1D"l;;s̱቎B,=/EJ>tbRGz x9; zo͋&c0C16@TfM3X[w>3Q=G"PTDCf $~䭵&S&긢yƼf*Q^|xX E{e0\0aGb; BzjAK_Im=D,P b?ԏ>P+U+I_yMd@ucl T**L<5I!0q&]WVFbWdP"r t1ia̚1.}E e Awp FeS4l6vr'lOlˮg81K!PK4NamPK!/org/apache/maven/wrapper/MavenWrapperMain.classXxg~eugP&iv= nB݋|/N)Pl Դ)2{@ɒ,7%بnI4[UAHO'=b ם^"zi=ՋYNZ}B\$LI`zTz( *vc@tPM!&IsT~E1r6XK X KUF izw2~\1]Ȋj!6䳻Gɠ6agHvʤaqWMG !꓎A6*J,+yW8Fʧm]|n5b)٬dƴdNwV//mrb[brZuiC_>t1I"tcу')ص$Zn蓌)61K}@ ,]׷ǚtX8u*qIN^ydEZm+hSIe4&WrA#lL:YSfHt\E$s6:R>bV <#K?zkqzw1'D6)=t,B9e̲sBZs'F(e-Z<`R%et[iZREӒ1Ś6cvGGԔ9Ǎ9-PUa*7C.iWs& =`]?MMֺrmnK>gHˣ~Xx{ ad?뮳a+\Rp Mَfy,bM3lbdL!ܞVVV"{Bqa2eSg^H ~^]JNbn%p Js͇Y_ޜ-;?C}X⥿6 >`.-Q~mt-&b}GqW$|mrGl}2EVN)?| ++&x c=Xx̓`Dz t8_꿆o(:g%U|pg~+iGYpȾ{ a)Cԝ`_'?Qy:U?c;`_m$fKs$|mM{3 NonWykeNY_WRE1y'Su>MPfYq_0*S;z3W0]A1΢(;%`DU44GF]YoG xPpQ)~\/ JE0-Ӧ`CT,u ! Hl?>}@c}{wk-V61i#¯5B*OO$kLxï@GCvvCyzN v[A`0k)I r7ب(c儖Q:ZE<{G{Ola4^ i2ԣƘ 3x\SՍIW/*+bo9U'ј}f+I= i6O}t^\zy^?6`#W\lCp|gcRIx.lEஂjvgyw1nQ=<WZ+R܈j Y꬝ESZgѾuV{΂/XőrE,%%9Xsq8(Arg<}Ϝ3xn z@uDe {t).gWbIF!jŋb7 -ܗn\O[vĤxh\ˣ:_*$w,UV9jRx=Hm](𞳙P6Q5nU(!j堧2>.of|<3{djHwYyz1sk[PH j\D$ڸkx"B0eE\,*]n ODm%UbMMYP7Pʖz @UKnuIIס$LcNgSq+'DHPK PK!>org/apache/maven/wrapper/PathAssembler$LocalDistribution.classR]OQ=-PWX?Ait(1!I&>`r^lw[[ؘG^b̙3gɞ`«Lb1D-F#ϢYG$G*/j ʄ` NDjd x]F,~f:R}o$ԛ3W*M=`5Za֕KS},bJFt><&c.aRqLs$^;MBcg cU_w8(sE;܎`%ڝ OPuw3e2QEnj5fF˱Q7Zps$ o?/8 B£ɵO9V,}@PKoItPK!,org/apache/maven/wrapper/PathAssembler.classV}kK, `*ʒ-&/Rv}qyAUvWi$mNKzߧ&7ھYɒmD>?Hμyf6WM NXv.̂\Ԗt3y NkBy`umIK53g\m龙ѫӓCWCW'&RGƓm^;,q5ӝE=Vmq`SCSUWA gtၜvt{Zi]cX F^gi4GfB3Vv3ayݞҘ@2Z~F > :=~xOt3V(P6C&拮a nK+f䊶&;z嘗`!B$w+y*0 fnrz"E 8 vT3դG-Ձl~(H/ZK-W7{wI\E7z,B+8x`@RIţ R~!?}x)יkx\VE#mӫl#<*.[^o\bk&%))OlP!R۪t5;/VZŨt_#8Ѥ)q"_1 ¿T2?:5'9<$`!oRQ|ZgaK xA"ES_}NVH7"wKx;WKakt^.?R[?N ?b]eZt_E9dN3%,Qr<ljbbCU:jQ;[1|{O* *# $pBPK|+?PK!6org/apache/maven/wrapper/SystemPropertiesHandler.classUY[W~¸AEԢQib P &3d"Uo<sk1ΣI!0fG1{S$O\|pk/!NӘ#=ŧ|t/SJ!z(-,RuGx}j|H_"~7[6khs8z|9+&l}PK{`- PK!3org/apache/maven/wrapper/WrapperConfiguration.classSUǿB҅jĆ-BZ I*mCI0XְT%tFƎ@CҿVz]eiDx@soG?WAThk f} sRan],u;68#0hwQ17)FMs qt7bD$/s/=4ƤΈ,+Hao0>gs3&ͪ!S#KR_pߛ'AÏiΠѴzÚbYpa.es&1 DɊ58ىh<=HIOҢy2@y2I=転dF~Ft `K􍾞ͥ?@>.髞^k%= a@m-B],7F+|MMBQϩO\?FPAc";@WX {j^~VAhHA  O Ka5) @ؔ5r#3ul8o64M$+bYUꠑeTILjFrDmhvŔijeq)xOM wg,ZH&LabMkVA2V;z+=fFbakuVa >ܯbbLy3 6:TsA4!V  ZG bN|-ЌFN,Nֈ8 afb +Xr%k!rHŻgςxIjŜmL}gz^8 ]* ZnZ͘L;*v @M;XB7`+v3'rT+ScEb1ڃ8H!7؀buDj!k"VX)#8˚Z&imoixy,f2梐="*IR^ +c!R~hZyg5|VVP͍MvB<RaJnUH*TLH~ZEO>B?LFljB3鲑Y<8zb6#)/j˜)` ⷇ld2g̮ҐAzf|*,_9 W6 U˜lV$W եe$&a\Ty@*>#m$):-'T|_A(=g; -#~Iŗ抉T^OF0E@ I/hj˴e74WU&5-Q(PA|\2?T-M?/2]t=WVPŏc]3*1#e/ADU@jHgM!#WxQgSDKLEI@jƦ;A]R>qK{mdMfZ&%Y(.`_ l^ůkHr*+8yS{jD">-@[}c.u:^ewwIb%s6v"{cxs][&zFb;=n;q qv*;!ۯb vH1d[5 ǯu 8.%10> lsfȳs9359gEyv6;[%|eFųxy?wj/˹gP qt' A8Wh=>%F%Z\ j,+b3)/(qYŒ|l!: OI+gyEe_kV.B-A n`Rmq#k Q"\k K7rHP (9xLw(ݎ1g'k1ᷤDho\1&#m%.~/K_彲4 CЙQI>*ۍRbs>E!I[0I)䦤5, WA+= uOI3Y-iwxcw%0\kY"z0R!`o_ğ$ "3B0+A4M``MaէM & Ckh;QC$K718ŪuT5Rrⱊdlsa1Uqu(Vsy+l ?10MTu)^𤸡qQPKǣ9,PK!org/apache/maven/wrapper/cli/PKPK!?org/apache/maven/wrapper/cli/AbstractCommandLineConverter.classUNA=#JmWXZ*ؚPk"!BEKYLڤЇj.E-?v.|s ??~XF} k*7^Ol^ [7JY967J̭iu,lG!( G%n#a8!3,wcϘl0x( "Q'a)ûku=8E?}t]tnݞ^OaiK7б0dp #qZesi CƄxv^S'.ú蕯g0iCG.<ܜ`U+uۦ|[滽s& >]yy:}AROo/4ۤɨv; SqڰaP?z)2F=/BcfQb.)OAK6p_K.40尛!eDu缭Mj9z8Q <H(^X+k~>’=ZTmAk ٕ] Ҡ Z0Bm3bՇVcM#v4"%H^b*gIBTĚN+&R$= gE= d@,y99gׯ\Ǐ"f +MYRSEyGSlR Zjzv,Yq,MgbQ7MΩ 5Sght͙bEc9aPC!(v \~T\WGzAed E.dKIlf̫B:CW4ݖwTAe+bd{ʗЩF[@NA$đ`8OvNh6ؒLי zgQmסvd]<ےRIe-ˎy'3SidHlovc2J%Nl1^=Eu"&N> > j!Ň"NJH1<8{zL2c̊aoE_Qэ %6RxYv"2+>E!,;ROv:O$b{W%|T,tui׷UI 9 +BY7ԽMfXW"d8WwS*ofiYJ.:Fs/d2My&aψ ]{ Kr'^>ܠ4kŕWԍ bUFKIŐk1O<$= 7q5rȲQ'N=gYl5Sia47"}0?_hІd? U?}wd"xj$iՄwte, Խ\;2yѮ"." TU${vi PuQ҈#՗s+?f6Sv-:XKpFeL1}O&0] M9a_ y/<-C,p-~(}.˄ qb lILhfc`PwP@e Iߐ(,ؤԸs}sqX+cяEgVc`Xe W?PKj F PK!?org/apache/maven/wrapper/cli/CommandLineArgumentException.classAO0Et FG!1DŃe4fn'~?о_?^\D*M#N)L(bv}n bpnL$. yRۧ³S k.x%9_~":!A lQAPҝ`䀎|FPqBC*Η|21A8^;* gڍDOP .McŬX0.z_/4 E+"Ij7UUyNF=KvoʪGJYǶj (vQR */YasG't![%LG8,V׵OPKm6TgPK!7org/apache/maven/wrapper/cli/CommandLineConverter.classR]O0;eĠ&&K4^ulRGK1Hѱgsu8"Pe@YgPɒ%CN;q11N,2)J #12Ї Py?ja]ܾ<cڹ$B <,H$pjZuSE]S>FˎCSZ3礏Lq0Ybu-_/U\L<5Y Ќu*Lx"}㡢81eljYk.o/J+TPu4 [6 ;]9PK=8LPK!4org/apache/maven/wrapper/cli/CommandLineOption.classU[WW'ITXXDC"ĻV@AiLfKKڇY_|h .Z]}kgodȝjW̙s9_phhLMxts9J'MK]Ӷ4 toDְ2-r4.t%ݢkf X03)0X;@-ieƮC7L1'-wYN&F@k1ٙczDFċiwdPˆcф*npMMĪq2ݫ*iW:FV / ě4& :"h/i8D6 Q:ڱGqLÀ@di"Hŕ;7qvNjc~:jڎ@OtCX'NaT.JͮN3%R v1llJy\pA T p51h#J芎1S{Fa΋**Rs܆tK;ed Ts4w;u+*}ԆY#`FgjMWJj~mNVU ]yf!PujUৣTyGG!!g vTdLjrhqhf n锭R:`}UH~f@`YieMOjC(_ N=w/+`Ӛ эP{嵦:k0# ,ֿg@Fcӧj.SVz6k?hAPyqf>+6|yf4l좓Lu@z:21l>ޖ98kA/}Y!!F%88^BO W^m#Ɛ F\wç^\ w!Z1~L=8pU x1}:Ӌ &ڂI\)MK&nK>* Vj1*nco|j/!X?%N #PL3s8cs>F5z hi6iƒ)KaSb9?}0w)$3z\;X]~`{`x$Ѻ1}Gߢ6z`>v({}]aϳ f#yIBMXGm^{ uZfQ'ݯS,]&Aho{uZ.q咏R(< A4+M^r^]>/imbA%1sa9g|3sfϯ bFApܔ.X34m}٬FN`_ 7gt',7%7Vb!¸OCYrp'?ZY"ΪY B*T^B_g<1ipBrksbSiaZv*V~|Ic*qIAߟ- qP# ƒ mxVZXᆂ# 7qL44+*e)S!0 &}vЂ *!UJr|=ClEk 3s!*0 CuzsTDq_~Q ?rA.oAd.&_u.sFVFt6\Ü(k+!#hӶmLu+d)`A凂aoO+s"O#Z6~QS|N*|N0wSr-5݁4QU4:G#Xфf 1<ZV߱x#h|텾hEx9ʒ{{eyn}^f}{H4fA+"Lyw"CGAlu@tF=.uQ9fb^!t btSQmɯׄKQˎK+6Mc"hJ&&D犢nc*G>]lՕq`:nI)n3үbU4oRaKsB KWJ,K@_U끡’^-6}w@ڔC0 d p>Vk/Mm0&4FBkЎg~am> }K_cj w_pυF?c655sTSPFj6f@$nI'r}L #EnױV: ͍߮|0#8CWO8a;Y*F#BE֑nbg 'vOFuwM9hsga[=eq8Oޯ9Ҩ ǟMg=H8OGʪ)9]P1MH)Q N/dj&t_ݍ)ɺ]#x\>~nDpHI$(^ Qăywxw1(gi ӿ@{bdFTB}Ȗ3|4Ҭ{r\*dzǘ'(EvPќ<}O1$pPԏ6$FX0Uh--0ZM}%3xÜӻLLW`ZV68/p׊CڿPK PK!Torg/apache/maven/wrapper/cli/CommandLineParser$CaseInsensitiveStringComparator.classS[OAftlVPQz_K&&M$)P2d;no?L|0>@c999?~}`;,@=>3T(^;:J%jPtT(T(#9HK51< COs5>A ˰{'xT2j1ؕj!ND6\8ǰlLFBc_0}Sg&:!an4AlQJYٜT;9`$[kxPJ1PZ.VoOX7yyW0d@.hN)`915^(Cr3 CL@fks@3"ݓCţYGҢn< Eΰ6oMg ,Z$#H.Ծ  .}~"O>I243$',gF4D*Y ZvZK2ST=ӸRe,3l.i"bQjйcחi+Vuvڦ@v,+Ń?PKG*PK!Korg/apache/maven/wrapper/cli/CommandLineParser$KnownOptionParserState.classXwUC5c#рKҠb0Ch`d3hL ;UmUu,*nq!8c`Lqߎ?ſ@ts?z8tw彗zk2Z_htZ㉔l hf0v͍5dHe# BJ*@7چ'pM  |85GSg'@۴T#16 jTx5Rvqinagjn&157fBZ75P{7!kK="3+|' xUP1'0! JPb|7b աqL7%0SFa| 0> {a|PKF{)6NMPK!Jorg/apache/maven/wrapper/cli/CommandLineParser$MissingOptionArgState.class[OAӖ.[. ( 5E+`j۴Lʚfv~$QH|gvZ/MIӝ9s~sif`x᩺-, i)heZ\˭-WPol߷e}؞\R̀"|h ^dx^)i--`a%=PaH-{[@}&20v >̂D kmǭ WƹWN+[a*ض}N/n[1JҠ?VY*X?/r[{a^?rNrUROE0Oy(AUe";U=|Ezr6Y莻'oz;&Vm=:o +)Zv ? ioa{RZ,!0聦] -Nd$+Ak_(~"OfסAsa0A:1D@;e9:CF5yLpMNq)P Ɯt+@WJ3n/MDM\.]T ~ j0i> Ԣ1ۄf (ƨGH3t8L%ęc J1d>qlFjV3n12;R|5X͕w휚b`) tGl;o.:KJeO;˴TC.4ZDPK=PK!Eorg/apache/maven/wrapper/cli/CommandLineParser$OptionComparator.classT[OQ-r- j[.]JULjHPNʒv I l7 - Ň3gvfw9_} g.*;R=imQJ[/ =kU*|-lGUװLW-\"=Y7veN5(%4eB0$ֶ #4\#k-i[eI[EQ1a- dZqby2'saD1aj-6!\'KҭD2 sA #WچY:&aPr3g&m0F!2Gu]czT ȟɟGLd<&^; GLG{ $2\$pa*^L|cKfK2䶼{Hf[IFZb!s 57[>ϯH`<fKC=CM)U `LԸ[ ZjeF%3MigqayLLF8RW!c˻,e!Y veob=Rw@7zXVbt0WdBBL8S&g8Bs_`B Gh`%4 k^pO~Rӌ Ql| ݩoGs)WƦය+FYF:>m;M~'eAUogff0@Xq1  ưfj1av_ 0H.,ܖXvcBQ]$IUWw৻X|Wޛ 7_P' noPK ҔPK!Aorg/apache/maven/wrapper/cli/CommandLineParser$OptionString.classS]OQ=SZk .+~G1&&4|)K |DJ?dDnWޝ{f̙o{CMCP%^VKlIzv[:ւj xBL.#V҄+!'&ӍsGRo\/R ~Ca \T0h ~e1xi&b͕Jo .G0;! M2zmW[-;\*8!U8 ]7E\"a$(|D넑cS~2a6dcWՌ&BkQPz B(QS)L3%d#̢B n`(*_D/!Pa2 '/J'{+f`˧ZbOg'W 5#TO 8 j*Uo1n:V]2gv3gwN{LCLti[ Ŗ*b4)󆣕o\a1]\a0T(!㾚 nDJYUA(9{\O,U3bn0'1#gq~E}"v|tPKvfPK!Korg/apache/maven/wrapper/cli/CommandLineParser$OptionStringComparator.classTMOA~feeY("ZPAh)vҨiDoCK y/hb/TΝb #HÚ2N641a6Gs |#Ba6X yg. ma rc,4Y1Mt?LOL8R2{qR݂w\/N'yɚAcPK7yPK!@org/apache/maven/wrapper/cli/CommandLineParser$ParserState.classn@M:uSI#b% E !EmTY8ĕ=nĆ H,x q4ٔXs{?3/pd#Gx+I7WRvwQ 5J Kn"i"/ĕpiBz aW~򊐯{ <֊X*dp'a_s$҉<M>yi%#?&w_aS_rqGUMB*,y6flfEE`"aa3/8C6"5#`@I75gG$R~|j@x][Y9 nt=7:4NJID>Ͳfм9ݟʬy♛͙ˑ8}C /rpx6AEp܀tPJAe]9nT6krf%&]m ?#~OxW]#y\W=2dh|2i瘛Yl+ +j9[oPKtSPK!Morg/apache/maven/wrapper/cli/CommandLineParser$UnknownOptionParserState.classU[OQWX(H+ ] /H* Aړ6-A.^|9 T ݙs739q܉#DxESTD~Ye"mst|2rY؅9˖ ­JwvV'rޢ'<GE&BZs-b5'[$ν+, h.ze#K}bmyWfVSf&GL;!nHfҭB6u鈣Mi}:ڡ)-#[K}*JRqE)'\K͈lU tԔ1]E=)X+KV3y۱7z?[qcq$`b?!p6ktW ͔ B(f:Ts6"AByaʎչOCgLJʪ H [X@g$$Tԃ n-NS)m19D+BrIZB ?6؂^&yc`j 7 34Mn­*unt$u<53\CY7o,]:V!Ӻe=:}7=-a)(9:jӾ㫸m‰wxGhFlN ;W,_Ã1+Lb%ۙl _ fG}^E 7t<] /fnYΚaRU郾&` v V3 e6v/TYWTw uNlq(dmT(=UT</5{5|=҅=>r,ȧ*NP+>/Eu`ӡ8j%b H0xVRЇt1f[,j:^Q`HfT;yHǫ H՟֫:rQ vo G2,87^;#v]6IY5[A N0* p'Q`VA/31F-~KTaǪ Q4BMa4$KpiwL+ȟCq2ψt2՚R˺E;G4Hr,MtfI1LFpUV;2^xwlX5'؞SAjD.(hWp |'. +\]&dҭ.헥iNxKRRh22*5s"o0"elYD$h2+%̻ZJ.vѱZjeu\S$uQ˹iꐖjR#?.] )=WRvOSnZ#2Ǵƿ0Fuk!*Ib5vDR7Qn|l&owg$&:X^^f2צzqn9'J6RwZ#<>Yu:Oٔat!&_f~vJB\ϭN4N%9oe^*J~]3$1MݵLIbI`}"٪r힣%9' CwzF'&OMj ۢ(Sь"_L0*1ˍ T *Q=lRW[OX«|Nv@ )SLȠELkb-L֢3hhw2Z[px:?\N6s~"xXpJ K|#.W{>+ͱ*^ubć,ji=c5g0M4fhF6a3E|̑]S$̼[%Nø_̿n6aZƲUۼn6Bf'ZL?-O91o)jrPmf)N8m/@o1|zε| 7A1L$ב3V: $x": (e)v+ZͫyNzQ2'ӷ,-Z%v-p _=( ^RA0={YHTTzCnPd9mu-J(5a<՜ ~(KjVp^WWځjz1gRfw'I nZq8Pe_hX;Zڼ )e*t:J] Ӱc-h@+VMڱ28. n|ʼn䱃)DD葩,b| nYiǭyn^.'q|[9+COaxPC!s<". Qi-ʀOWgL .ğ&o[\%w"R{OSgͪ9~xN!#4t5碵n%>۔즏S9<XvUfU:ץ֣ǒKVnzGx"=(82;1ĊY97Acªa|_B>#b8Ucb|^?F~3;g@mnњͼբ~4x=qq{ݬu%RM!PD?&kQkJy]eG^Pz^G{ qxddtڌf:<2PǹX@gA̓|j6Q2#+" bO*/WݜVX7 %2x~2/]N uÖhōY6 .OҙRgynoVMР6YjD]~J_y];j)K@_4dp>d8~Ǯ#Q#?ѵ.|xw'7Y8,,r]decy璛-pg3L~̈n^q%˭r[#$j9?PK5(PK!4org/apache/maven/wrapper/cli/ParsedCommandLine.classVi{~ȃ1( F`-`]dyMk,t_>$S˷>Ooi{g$K8 4_4w9=G_o-;֋zfH/F!).1kiI/d'͂AH`E}YOB.=sq6YEǴ ѕY6 9L*cSzqP`ì+N6w&W]' ،pmdwTeph]srd\vl}Ε莎64K5Kj2 3,5Qc0~>o L }6 ~H_1+kDDM"LEUm HDܫ!o"EQZаv ܳj5b?k[-؋D=iERٔsDz:5|Nx-H?] igfKF<70aw#(# {PC8*bl Qʱ!u ՚+|Y30],$40%NDҴ"9+ˈ!N>fc96[ 9&"X:U|ƲЊÑ/b.&CPp=)+ 1_N}`eah#s w2eEn.-)dOZ&IƋ8'48\%b9h4|WnȿTkGf>kQdьE@*.'5<܍x1=Koߤ|Kʢ$uZvT=Os4n%Z e 3@)@+zL3fI dz^÷1cݔUŧơHa5icV>O;UKl ~ ;独S25\ WMFڈ;Q$8ٌ&bdǁ?;j2krzR/g ?b) lo'u@a_i^2{בF=U|h~Ri Z ,m)Y*:xC{ @6;g'Ze;cYw6` D|-q,f.[8:o.+m49>y$os&]G8~]9unaU軅}8B8r MW=Y'X, W;>op#2&lǽ؁=؅(vgu8Idkh ӌ(Y)::N9213< Zjr8oڋ/B0 nمvKܵO)D߸( 媼gpȒ Sa܁U䅶_A4՞s>վ>P,8,f p8@e$ab<уp,qo\ryi\R\6sF8A˼c'sL.C5\Jl{<-D2V%/ q=PDQnT~Ot}έuJ>@8t"Oת uhO긟ػ8a4'UdV!W `%@Mr5u^%T JnIďZRqJ uBʬe"=_$ 5WpE;Mf? `5i{:פM+5~y,xeZ }8[UE蒺'zӥjZ[t W|]PK!@zPK!:org/apache/maven/wrapper/cli/ParsedCommandLineOption.classS]OA=Ӗn)KUB[+EĄxIdm[>&*Ae_vv{g'+1֭TZS{mFCXZеjFVf9bauSAaxpfE%!xhY9lٺe/-K0,;;XJvJ95"Ydl" ?U#`anYP`?*d̟j{z "K(rK{/:qG(`K${G IS*oz4ܮ+ -nln7%!NInx.qnǫ0ø}:\3'zI$% "$ߺBXf:xeznfZbPF4=댬3qɐ)N%#ݣuf'xWxnUZ5aڒ]pXQ.]J%zp%CkYk؇ Be3]zf;%]:Vv>hǤ;@'hNAM sod7#h.^ˤc=O0=ܯWcnNǸo#q̕lWL-ܦ*wUFQ';A'8Cqwx^u;gKppbn# 봧!<:QW;(>-zPK=!C@PK!Horg/apache/maven/wrapper/cli/ProjectPropertiesCommandLineConverter.classMO"ADB]ua L<(fOd%xorh33=i JO&(cπư]CՕNu=8"J7`7c{-☵huǞb+FPD-."OhyohW#BDFҜr !R}.# Q %ߣZ&T2ϊy3Ce;&la\FUX|k6!A\2~ [J<}a5&giZŽ]R3MέҎɠL M4:$񝆓F\o]5~kf2"`mf`c\du G,lc!-nb`u%W638W]CwOnΣvc=@ kPKBm5PK!Gorg/apache/maven/wrapper/cli/SystemPropertiesCommandLineConverter.classN1CB-r.bEBXpReLN'f#*+$<@ B!Ջs^ S}W GqZ+[0 C 2ⶊ&Ⱥ"nAb#IsB(}B\EK+XD/O1P*O}eϊE3Sg;$rUlF7X::!VAXNO,`pc<3Na1org/apache/maven/wrapper/PathAssembler$LocalDistribution.classPK!|+?,3org/apache/maven/wrapper/PathAssembler.classPK!{`- 6!;org/apache/maven/wrapper/SystemPropertiesHandler.classPK!?a( 3m@org/apache/maven/wrapper/WrapperConfiguration.classPK!ǣ9,.fDorg/apache/maven/wrapper/WrapperExecutor.classPK!SMorg/apache/maven/wrapper/cli/PK!dQvT?Morg/apache/maven/wrapper/cli/AbstractCommandLineConverter.classPK!j F I Qorg/apache/maven/wrapper/cli/AbstractPropertiesCommandLineConverter.classPK!m6Tg?/Vorg/apache/maven/wrapper/cli/CommandLineArgumentException.classPK!=8L7Worg/apache/maven/wrapper/cli/CommandLineConverter.classPK!6WK 4Yorg/apache/maven/wrapper/cli/CommandLineOption.classPK!k-% I_org/apache/maven/wrapper/cli/CommandLineParser$AfterFirstSubCommand.classPK!['Aborg/apache/maven/wrapper/cli/CommandLineParser$AfterOptions.classPK! Jeorg/apache/maven/wrapper/cli/CommandLineParser$BeforeFirstSubCommand.classPK!G*Tjorg/apache/maven/wrapper/cli/CommandLineParser$CaseInsensitiveStringComparator.classPK!F{)6NMKlorg/apache/maven/wrapper/cli/CommandLineParser$KnownOptionParserState.classPK! IJtorg/apache/maven/wrapper/cli/CommandLineParser$MissingOptionArgState.classPK!=Kworg/apache/maven/wrapper/cli/CommandLineParser$OptionAwareParserState.classPK!KEzorg/apache/maven/wrapper/cli/CommandLineParser$OptionComparator.classPK! ҔF}org/apache/maven/wrapper/cli/CommandLineParser$OptionParserState.classPK!vfAorg/apache/maven/wrapper/cli/CommandLineParser$OptionString.classPK!7yKorg/apache/maven/wrapper/cli/CommandLineParser$OptionStringComparator.classPK!tS@܅org/apache/maven/wrapper/cli/CommandLineParser$ParserState.classPK!O<M6org/apache/maven/wrapper/cli/CommandLineParser$UnknownOptionParserState.classPK!5(4xorg/apache/maven/wrapper/cli/CommandLineParser.classPK!!@z4org/apache/maven/wrapper/cli/ParsedCommandLine.classPK!=!C@:٣org/apache/maven/wrapper/cli/ParsedCommandLineOption.classPK!Bm5Horg/apache/maven/wrapper/cli/ProjectPropertiesCommandLineConverter.classPK!v겉&Gorg/apache/maven/wrapper/cli/SystemPropertiesCommandLineConverter.classPK..zt-exec-zt-exec-1.11/.mvn/wrapper/maven-wrapper.properties000077500000000000000000000001631350762700300236360ustar00rootroot00000000000000distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.5.4/apache-maven-3.5.4-bin.zipzt-exec-zt-exec-1.11/.travis.yml000066400000000000000000000000621350762700300165020ustar00rootroot00000000000000language: java jdk: - oraclejdk8 - oraclejdk9 zt-exec-zt-exec-1.11/Changelog.txt000066400000000000000000000041701350762700300170250ustar00rootroot00000000000000******************************************** ZT Exec Changelog ******************************************** 1.11 (5th of July 2019) * Improved usage - eliminated cases of log and throw * Removed dependency on Apache's commons-io library * Use ping instead of sleep on Windows to test timeout exceptions * Some bug fixes 1.10 (1st August 2017) * Added support for flushing output after each write * Added support for hooks for thread executor creation * Added support of preserving MDC context of the caller thread * Changed LogOutpuStream to handle line breaks like ProcessOutput 1.9 (12th April 2016) * Fixed using empty arguments on Windows * Fixed closing stdin on Java 8 * Fixed redirecting PipedInputStream. * Added ProcessInitException to expose error code * Added ProcessExecutor.checkExitValue() for unit testing * Added getters to ProcessExecutor 1.8 (17th March 2015) * Fixed blocking JVM shutdown * Improved TimeoutException message * Improved Slf4jStream * Added ProcessExecutor.closeTimeout() * Added ProcessOutput.getLines() * Added ProcessOutput.command(Iterable) * Added ProcessListener.afterFinish() and InvalidOutputException support * Added Level class 1.7 (30th June 2014) * Fixed ProcessExecutor.commandSplit() * Added ProcessExecutor.stopper(ProcessStopper) to customize stopping in case of timeout or cancellation * Added ProcessExecutor.setMessageLogger() to customize log message level * Added ProcessExecutor.executeNoTimeout() to avoid catching TimeoutException * Added ProcessExecutor.environment(String, String) for convenience * Improved logging and error handling * Added get-prefixes to StartedProcess methods (old ones are deprecated) 1.6 (30th January 2014) * Improved Slf4j logging support * Added ProcessExecutor.redirectInput() * Improved adding/removing destroyers and listeners * InvalidExitValueException now includes process output if it was read * Added get-prefixes to some methods (old ones are deprecated) 1.5 (14th October 2013) * By default any exit code is now allowed (use exitValueNormal() to only allow zero) * Fixed an issue with starting processes on JVM shutdown * Fixed an issue with supporting Java 1.5 zt-exec-zt-exec-1.11/LICENSE000066400000000000000000000261261350762700300154070ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright 2013 ZeroTurnaround LLC. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. zt-exec-zt-exec-1.11/NOTICE.txt000066400000000000000000000004601350762700300161150ustar00rootroot00000000000000==== The following is the original NOTICE.txt file from the Apache Commons Exec project that this project is derived from. Apache Commons Exec Copyright 2005-2010 The Apache Software Foundation This product includes software developed by The Apache Software Foundation (http://www.apache.org/). zt-exec-zt-exec-1.11/README.md000066400000000000000000000146471350762700300156660ustar00rootroot00000000000000ZT Process Executor ================ ### Continuous Integration [![Build Status](https://travis-ci.org/zeroturnaround/zt-exec.png)](https://travis-ci.org/zeroturnaround/zt-exec) ### Quick Overview The project was created to merge similar functionality of projects at [ZeroTurnaround](http://zeroturnaround.com/) into a single codebase. It's designed to be powerful but still simple to use. By using a single class **ProcessExecutor** the user gets the functionality from both **java.lang.ProcessBuilder** and [Apache Commons Exec](http://commons.apache.org/proper/commons-exec/). ### Installation [![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.zeroturnaround/zt-exec/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.zeroturnaround/zt-exec) The project artifacts are available in [Maven Central Repository](http://search.maven.org/#browse%7C1982316413). To include it in your maven project then you have to specify the dependency. ```xml ... org.zeroturnaround zt-exec 1.10 ... ``` ## Motivation There are many approaches to take when running external processes from Java. There are the **JRE** options such as the **Runtime.exec()** and **ProcessBuilder**. Also there is the [Apache Commons Exec](http://commons.apache.org/proper/commons-exec/). Nevertheless we created yet another process library (**YAPL**). Some of the reasons for this crazy endeavour * Improved handling of streams * Reading/writing to streams * Redirecting stderr to stdout * Improved handling of timeouts * Improved checking of exit codes * Improved API * One liners for quite complex usecases * One liners to get process output into a String * Access to the **Process** object available * Support for async processes ( **Future** ) * Improved logging with [SLF4J API](http://www.slf4j.org/) * Support for multiple processes **Can zt-exec also kill processes?** No. There is [zt-process-killer](https://github.com/zeroturnaround/zt-process-killer) for that. ## Examples * Output is pumped to NullOutputStream ```java new ProcessExecutor().command("java", "-version").execute(); ```
* Returning the exit code * Output is pumped to NullOutputStream ```java int exit = new ProcessExecutor().command("java", "-version") .execute().getExitValue(); ```
* Return output as UTF8 String ```java String output = new ProcessExecutor().command("java", "-version") .readOutput(true).execute() .outputUTF8(); ```
* Pumping the output to a logger ```java new ProcessExecutor().command("java", "-version") .redirectOutput(Slf4jStream.of(LoggerFactory.getLogger(getClass().getName() + ".MyProcess")).asInfo()).execute(); ```
* Pumping the output to a logger (short form for previous) ```java new ProcessExecutor().command("java", "-version") .redirectOutput(Slf4jStream.of("MyProcess").asInfo()).execute(); ```
* Pumping the output to the logger of the caller class ```java new ProcessExecutor().command("java", "-version") .redirectOutput(Slf4jStream.ofCaller().asInfo()).execute(); ```
* Pumping the output to a logger * Returning output as UTF8 String ```java String output = new ProcessExecutor().command("java", "-version") .redirectOutput(Slf4jStream.of(getClass()).asInfo()) .readOutput(true).execute().outputUTF8(); ```
* Pumping the stderr to a logger * Returning the output as UTF8 String ```java String output = new ProcessExecutor().command("java", "-version") .redirectError(Slf4jStream.of(getClass()).asInfo()) .readOutput(true).execute() .outputUTF8(); ```
* Running with a timeout of **60** seconds * Output pumped to NullOutputStream ```java try { new ProcessExecutor().command("java", "-version") .timeout(60, TimeUnit.SECONDS).execute(); } catch (TimeoutException e) { // process is automatically destroyed } ```
* Pumping output to another OutputStream ```java OutputStream out = ...; new ProcessExecutor().command("java", "-version") .redirectOutput(out).execute(); ```
* Handling output line-by-line while process is running ```java new ProcessExecutor().command("java", "-version") .redirectOutput(new LogOutputStream() { @Override protected void processLine(String line) { ... } }) .execute(); ```
* Destroy the running process when VM exits * Output pumped to NullOutputStream ```java new ProcessExecutor().command("java", "-version").destroyOnExit().execute(); ```
* Run process with a specific environment variable * Output pumped to NullOutputStream ```java new ProcessExecutor().command("java", "-version") .environment("foo", "bar").execute(); ```
* Run process with a specific environment * Output pumped to NullOutputStream ```java Map env = ... new ProcessExecutor().command("java", "-version") .environment(env).execute(); ```
* Throw exception when wrong exit code * Output is pumped to NullOutputStream ```java try { new ProcessExecutor().command("java", "-version") .exitValues(3).execute(); } catch (InvalidExitValueException e) { System.out.println("Process exited with " + e.getExitValue()); } ```
* Throw exception when wrong exit code * Return output as UTF8 String ```java String output; boolean success = false; try { output = new ProcessExecutor().command("java", "-version") .readOutput(true).exitValues(3) .execute().outputUTF8(); success = true; } catch (InvalidExitValueException e) { System.out.println("Process exited with " + e.getExitValue()); output = e.getResult().outputUTF8(); } ```
* Starting process in the background * Output is pumped to NullOutputStream ```java Future future = new ProcessExecutor() .command("java", "-version") .start().getFuture(); // do some stuff future.get(60, TimeUnit.SECONDS); ```
* Start process in the background * Return output as UTF8 String ```java Future future = new ProcessExecutor() .command("java", "-version") .readOutput(true) .start().getFuture(); // do some stuff String output = future.get(60, TimeUnit.SECONDS).outputUTF8(); ``` zt-exec-zt-exec-1.11/get_release_commands.sh000077500000000000000000000047301350762700300210760ustar00rootroot00000000000000#!/bin/sh if [[ "$1" = "-h" ]] || [[ "$1" = "--help" ]]; then echo "Usage: './get_release_commands.sh VERSION_TO_RELEASE [NEW_DEV_VERSION]'" echo "Prints out commands to run to release zt-exec to Maven Central." echo "VERSION_TO_RELEASE must be a number (integer or floating). NEW_DEV_VERSION is optional" exit 0 fi if ! [[ "$1" =~ ^[0-9]*\.?[0-9]*$ ]] || [[ "$1z" = "z" ]]; then echo "Not a valid version number given, use -h to get usage options" exit 1 fi version=$1 version_after_dot=${version##*.} version_str_length=${#version}-${#version_after_dot} incr_last_digit=$((${version_after_dot}+1)) version_without_last_digit=${version: 0:${version_str_length}} new_version="${version_without_last_digit}${incr_last_digit}-SNAPSHOT" if [[ "$2z" = "z" ]]; then echo "No new development version given using ${new_version}" else new_version=$2 echo "New development version will be ${new_version}" fi echo "To release zt-exec version ${version} run these commands:" echo "" echo "1) set release version" echo "mvn versions:set -DnewVersion=${version}" echo "" echo "2) commit & tag" echo "git add pom.xml; " echo "git commit -m \"Prepare release zt-exec-${version}\"" echo "git tag zt-exec-${version}" echo "" echo "3) build release" echo "mvn clean install" echo "" echo "4) generate javadoc archive" echo "mvn javadoc:jar" echo "" echo "5) generate sources archive" echo "mvn source:jar" echo "" echo "6) deploy and sign releases archive" echo "mvn gpg:sign-and-deploy-file -Durl=https://oss.sonatype.org/service/local/staging/deploy/maven2/ -DrepositoryId=sonatype-nexus-staging -DpomFile=pom.xml -Dfile=target/zt-exec-$1.jar" echo "" echo "7) deploy and sign sources archive" echo "mvn gpg:sign-and-deploy-file -Durl=https://oss.sonatype.org/service/local/staging/deploy/maven2/ -DrepositoryId=sonatype-nexus-staging -DpomFile=pom.xml -Dfile=target/zt-exec-$1-sources.jar -Dclassifier=sources" echo "" echo "8) deploy and sign javadoc archive" echo "mvn gpg:sign-and-deploy-file -Durl=https://oss.sonatype.org/service/local/staging/deploy/maven2/ -DrepositoryId=sonatype-nexus-staging -DpomFile=pom.xml -Dfile=target/zt-exec-$1-javadoc.jar -Dclassifier=javadoc" echo "" echo "9) set new development version" echo "mvn versions:set -DnewVersion=${new_version}" echo "git add pom.xml; " echo "git commit -m \"prepare for next development iteration\"" echo "" echo "10) push to GitHub" echo "git push" echo "git push --tags" echo "" echo "11) clean local repo" echo "git clean -f" zt-exec-zt-exec-1.11/mvnw000077500000000000000000000216311350762700300153130ustar00rootroot00000000000000#!/bin/sh # ---------------------------------------------------------------------------- # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # ---------------------------------------------------------------------------- # ---------------------------------------------------------------------------- # Maven2 Start Up Batch script # # Required ENV vars: # ------------------ # JAVA_HOME - location of a JDK home dir # # Optional ENV vars # ----------------- # M2_HOME - location of maven2's installed home dir # MAVEN_OPTS - parameters passed to the Java VM when running Maven # e.g. to debug Maven itself, use # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 # MAVEN_SKIP_RC - flag to disable loading of mavenrc files # ---------------------------------------------------------------------------- if [ -z "$MAVEN_SKIP_RC" ] ; then if [ -f /etc/mavenrc ] ; then . /etc/mavenrc fi if [ -f "$HOME/.mavenrc" ] ; then . "$HOME/.mavenrc" fi fi # OS specific support. $var _must_ be set to either true or false. cygwin=false; darwin=false; mingw=false case "`uname`" in CYGWIN*) cygwin=true ;; MINGW*) mingw=true;; Darwin*) darwin=true # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home # See https://developer.apple.com/library/mac/qa/qa1170/_index.html if [ -z "$JAVA_HOME" ]; then if [ -x "/usr/libexec/java_home" ]; then export JAVA_HOME="`/usr/libexec/java_home`" else export JAVA_HOME="/Library/Java/Home" fi fi ;; esac if [ -z "$JAVA_HOME" ] ; then if [ -r /etc/gentoo-release ] ; then JAVA_HOME=`java-config --jre-home` fi fi if [ -z "$M2_HOME" ] ; then ## resolve links - $0 may be a link to maven's home PRG="$0" # need this for relative symlinks while [ -h "$PRG" ] ; do ls=`ls -ld "$PRG"` link=`expr "$ls" : '.*-> \(.*\)$'` if expr "$link" : '/.*' > /dev/null; then PRG="$link" else PRG="`dirname "$PRG"`/$link" fi done saveddir=`pwd` M2_HOME=`dirname "$PRG"`/.. # make it fully qualified M2_HOME=`cd "$M2_HOME" && pwd` cd "$saveddir" # echo Using m2 at $M2_HOME fi # For Cygwin, ensure paths are in UNIX format before anything is touched if $cygwin ; then [ -n "$M2_HOME" ] && M2_HOME=`cygpath --unix "$M2_HOME"` [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` [ -n "$CLASSPATH" ] && CLASSPATH=`cygpath --path --unix "$CLASSPATH"` fi # For Mingw, ensure paths are in UNIX format before anything is touched if $mingw ; then [ -n "$M2_HOME" ] && M2_HOME="`(cd "$M2_HOME"; pwd)`" [ -n "$JAVA_HOME" ] && JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" # TODO classpath? fi if [ -z "$JAVA_HOME" ]; then javaExecutable="`which javac`" if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then # readlink(1) is not available as standard on Solaris 10. readLink=`which readlink` if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then if $darwin ; then javaHome="`dirname \"$javaExecutable\"`" javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" else javaExecutable="`readlink -f \"$javaExecutable\"`" fi javaHome="`dirname \"$javaExecutable\"`" javaHome=`expr "$javaHome" : '\(.*\)/bin'` JAVA_HOME="$javaHome" export JAVA_HOME fi fi fi if [ -z "$JAVACMD" ] ; then if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables JAVACMD="$JAVA_HOME/jre/sh/java" else JAVACMD="$JAVA_HOME/bin/java" fi else JAVACMD="`which java`" fi fi if [ ! -x "$JAVACMD" ] ; then echo "Error: JAVA_HOME is not defined correctly." >&2 echo " We cannot execute $JAVACMD" >&2 exit 1 fi if [ -z "$JAVA_HOME" ] ; then echo "Warning: JAVA_HOME environment variable is not set." fi CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher # traverses directory structure from process work directory to filesystem root # first directory with .mvn subdirectory is considered project base directory find_maven_basedir() { if [ -z "$1" ] then echo "Path not specified to find_maven_basedir" return 1 fi basedir="$1" wdir="$1" while [ "$wdir" != '/' ] ; do if [ -d "$wdir"/.mvn ] ; then basedir=$wdir break fi # workaround for JBEAP-8937 (on Solaris 10/Sparc) if [ -d "${wdir}" ]; then wdir=`cd "$wdir/.."; pwd` fi # end of workaround done echo "${basedir}" } # concatenates all lines of a file concat_lines() { if [ -f "$1" ]; then echo "$(tr -s '\n' ' ' < "$1")" fi } BASE_DIR=`find_maven_basedir "$(pwd)"` if [ -z "$BASE_DIR" ]; then exit 1; fi ########################################################################################## # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central # This allows using the maven wrapper in projects that prohibit checking in binary data. ########################################################################################## if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then if [ "$MVNW_VERBOSE" = true ]; then echo "Found .mvn/wrapper/maven-wrapper.jar" fi else if [ "$MVNW_VERBOSE" = true ]; then echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." fi jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.0/maven-wrapper-0.4.0.jar" while IFS="=" read key value; do case "$key" in (wrapperUrl) jarUrl="$value"; break ;; esac done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" if [ "$MVNW_VERBOSE" = true ]; then echo "Downloading from: $jarUrl" fi wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" if command -v wget > /dev/null; then if [ "$MVNW_VERBOSE" = true ]; then echo "Found wget ... using wget" fi wget "$jarUrl" -O "$wrapperJarPath" elif command -v curl > /dev/null; then if [ "$MVNW_VERBOSE" = true ]; then echo "Found curl ... using curl" fi curl -o "$wrapperJarPath" "$jarUrl" else if [ "$MVNW_VERBOSE" = true ]; then echo "Falling back to using Java to download" fi javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" if [ -e "$javaClass" ]; then if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then if [ "$MVNW_VERBOSE" = true ]; then echo " - Compiling MavenWrapperDownloader.java ..." fi # Compiling the Java class ("$JAVA_HOME/bin/javac" "$javaClass") fi if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then # Running the downloader if [ "$MVNW_VERBOSE" = true ]; then echo " - Running MavenWrapperDownloader.java ..." fi ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") fi fi fi fi ########################################################################################## # End of extension ########################################################################################## export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} if [ "$MVNW_VERBOSE" = true ]; then echo $MAVEN_PROJECTBASEDIR fi MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" # For Cygwin, switch paths to Windows format before running java if $cygwin; then [ -n "$M2_HOME" ] && M2_HOME=`cygpath --path --windows "$M2_HOME"` [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` [ -n "$CLASSPATH" ] && CLASSPATH=`cygpath --path --windows "$CLASSPATH"` [ -n "$MAVEN_PROJECTBASEDIR" ] && MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` fi WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain exec "$JAVACMD" \ $MAVEN_OPTS \ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" zt-exec-zt-exec-1.11/mvnw.cmd000077500000000000000000000135231350762700300160560ustar00rootroot00000000000000@REM ---------------------------------------------------------------------------- @REM Licensed to the Apache Software Foundation (ASF) under one @REM or more contributor license agreements. See the NOTICE file @REM distributed with this work for additional information @REM regarding copyright ownership. The ASF licenses this file @REM to you under the Apache License, Version 2.0 (the @REM "License"); you may not use this file except in compliance @REM with the License. You may obtain a copy of the License at @REM @REM http://www.apache.org/licenses/LICENSE-2.0 @REM @REM Unless required by applicable law or agreed to in writing, @REM software distributed under the License is distributed on an @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @REM KIND, either express or implied. See the License for the @REM specific language governing permissions and limitations @REM under the License. @REM ---------------------------------------------------------------------------- @REM ---------------------------------------------------------------------------- @REM Maven2 Start Up Batch script @REM @REM Required ENV vars: @REM JAVA_HOME - location of a JDK home dir @REM @REM Optional ENV vars @REM M2_HOME - location of maven2's installed home dir @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven @REM e.g. to debug Maven itself, use @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files @REM ---------------------------------------------------------------------------- @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' @echo off @REM set title of command window title %0 @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% @REM set %HOME% to equivalent of $HOME if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") @REM Execute a user defined script before this one if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre @REM check for pre script, once with legacy .bat ending and once with .cmd ending if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" :skipRcPre @setlocal set ERROR_CODE=0 @REM To isolate internal variables from possible post scripts, we use another setlocal @setlocal @REM ==== START VALIDATION ==== if not "%JAVA_HOME%" == "" goto OkJHome echo. echo Error: JAVA_HOME not found in your environment. >&2 echo Please set the JAVA_HOME variable in your environment to match the >&2 echo location of your Java installation. >&2 echo. goto error :OkJHome if exist "%JAVA_HOME%\bin\java.exe" goto init echo. echo Error: JAVA_HOME is set to an invalid directory. >&2 echo JAVA_HOME = "%JAVA_HOME%" >&2 echo Please set the JAVA_HOME variable in your environment to match the >&2 echo location of your Java installation. >&2 echo. goto error @REM ==== END VALIDATION ==== :init @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". @REM Fallback to current working directory if not found. set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir set EXEC_DIR=%CD% set WDIR=%EXEC_DIR% :findBaseDir IF EXIST "%WDIR%"\.mvn goto baseDirFound cd .. IF "%WDIR%"=="%CD%" goto baseDirNotFound set WDIR=%CD% goto findBaseDir :baseDirFound set MAVEN_PROJECTBASEDIR=%WDIR% cd "%EXEC_DIR%" goto endDetectBaseDir :baseDirNotFound set MAVEN_PROJECTBASEDIR=%EXEC_DIR% cd "%EXEC_DIR%" :endDetectBaseDir IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig @setlocal EnableExtensions EnableDelayedExpansion for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% :endReadAdditionalConfig SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.0/maven-wrapper-0.4.0.jar" FOR /F "tokens=1,2 delims==" %%A IN (%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties) DO ( IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B ) @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central @REM This allows using the maven wrapper in projects that prohibit checking in binary data. if exist %WRAPPER_JAR% ( echo Found %WRAPPER_JAR% ) else ( echo Couldn't find %WRAPPER_JAR%, downloading it ... echo Downloading from: %DOWNLOAD_URL% powershell -Command "(New-Object Net.WebClient).DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')" echo Finished downloading %WRAPPER_JAR% ) @REM End of extension %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* if ERRORLEVEL 1 goto error goto end :error set ERROR_CODE=1 :end @endlocal & set ERROR_CODE=%ERROR_CODE% if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost @REM check for post script, once with legacy .bat ending and once with .cmd ending if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" :skipRcPost @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' if "%MAVEN_BATCH_PAUSE%" == "on" pause if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% exit /B %ERROR_CODE% zt-exec-zt-exec-1.11/pom.xml000066400000000000000000000151131350762700300157110ustar00rootroot00000000000000 4.0.0 org.zeroturnaround zt-exec jar ZT Process Executor 1.11 scm:git:git@github.com:zeroturnaround/zt-exec.git scm:git:git@github.com:zeroturnaround/zt-exec.git scm:git:git@github.com:zeroturnaround/zt-exec.git sonatype-nexus-staging Sonatype OSS Staging https://oss.sonatype.org/service/local/staging/deploy/maven2 default sonatype-nexus-snapshots Sonatype OSS Snapshots https://oss.sonatype.org/content/repositories/snapshots default UTF-8 UTF-8 org.slf4j slf4j-api 1.7.2 junit junit 4.11 test ch.qos.logback logback-classic 1.1.2 test org.apache.commons commons-lang3 3.5 test commons-io commons-io 2.5 test org.apache.maven.plugins maven-compiler-plugin 3.5.1 1.6 1.6 org.apache.maven.plugins maven-jar-plugin 2.3.1 false org.apache.maven.plugins maven-javadoc-plugin 3.0.1 attach-javadocs jar org.apache.maven.plugins maven-release-plugin 2.5.3 org.apache.maven.plugins maven-source-plugin 3.0.0 attach-sources jar release-sign-artifacts performRelease true org.apache.maven.plugins maven-release-plugin https://svn.apache.org/repos/asf/maven/components/releases forked-path org.apache.maven.plugins maven-gpg-plugin 1.4 sign-artifacts verify sign ZeroTurnaround http://zeroturnaround.com/ https://github.com/zeroturnaround/zt-exec A lightweight library to execute external processes from Java. rein Rein rein@zeroturnaround.com http://www.linkedin.com/in/reinra ZeroTurnaround http://zeroturnaround.com toomasr Toomas toomas@zeroturnaround.com http://www.linkedin.com/in/toomasr ZeroTurnaround http://zeroturnaround.com The Apache Software License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0.txt A business-friendly OSS license zt-exec-zt-exec-1.11/src/000077500000000000000000000000001350762700300151625ustar00rootroot00000000000000zt-exec-zt-exec-1.11/src/main/000077500000000000000000000000001350762700300161065ustar00rootroot00000000000000zt-exec-zt-exec-1.11/src/main/java/000077500000000000000000000000001350762700300170275ustar00rootroot00000000000000zt-exec-zt-exec-1.11/src/main/java/org/000077500000000000000000000000001350762700300176165ustar00rootroot00000000000000zt-exec-zt-exec-1.11/src/main/java/org/zeroturnaround/000077500000000000000000000000001350762700300227175ustar00rootroot00000000000000zt-exec-zt-exec-1.11/src/main/java/org/zeroturnaround/exec/000077500000000000000000000000001350762700300236435ustar00rootroot00000000000000zt-exec-zt-exec-1.11/src/main/java/org/zeroturnaround/exec/InvalidExitUtil.java000066400000000000000000000042001350762700300275600ustar00rootroot00000000000000package org.zeroturnaround.exec; import java.util.Set; import java.util.concurrent.TimeoutException; /** * Helper for checking the exit code of the finished process. */ class InvalidExitUtil { /** * In case {@link InvalidExitValueException} or {@link TimeoutException} is thrown and we have read the process output * we include the output up to this length in the error message. If the output is longer we truncate it. */ private static final int MAX_OUTPUT_SIZE_IN_ERROR_MESSAGE = 5000; /** * Check the process exit value. */ public static void checkExit(ProcessAttributes attributes, ProcessResult result) { Set allowedExitValues = attributes.getAllowedExitValues(); if (allowedExitValues != null && !allowedExitValues.contains(result.getExitValue())) { StringBuilder sb = new StringBuilder(); sb.append("Unexpected exit value: ").append(result.getExitValue()); sb.append(", allowed exit values: ").append(allowedExitValues); addExceptionMessageSuffix(attributes, sb, result.hasOutput() ? result.getOutput() : null); throw new InvalidExitValueException(sb.toString(), result); } } public static void addExceptionMessageSuffix(ProcessAttributes attributes, StringBuilder sb, ProcessOutput output) { sb.append(", executed command ").append(attributes.getCommand()); if (attributes.getDirectory() != null) { sb.append(" in directory ").append(attributes.getDirectory()); } if (!attributes.getEnvironment().isEmpty()) { sb.append(" with environment ").append(attributes.getEnvironment()); } if (output != null) { int length = output.getBytes().length; String out = output.getString(); if (out.length() <= MAX_OUTPUT_SIZE_IN_ERROR_MESSAGE) { sb.append(", output was ").append(length).append(" bytes:\n").append(out.trim()); } else { sb.append(", output was ").append(length).append(" bytes (truncated):\n"); int halfLimit = MAX_OUTPUT_SIZE_IN_ERROR_MESSAGE / 2; sb.append(out.substring(0, halfLimit)).append("\n...\n").append(out.substring(out.length() - halfLimit).trim()); } } } } zt-exec-zt-exec-1.11/src/main/java/org/zeroturnaround/exec/InvalidExitValueException.java000066400000000000000000000024031350762700300316010ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec; /** * Process finished with a forbidden exit value. * * @author Rein Raudjärv * * @see ProcessExecutor#exitValues(Integer...) */ public class InvalidExitValueException extends InvalidResultException { private static final long serialVersionUID = 1L; /** * @param message the detail message of the exception * @param result result of execution (contains also the exit value) */ public InvalidExitValueException(String message, ProcessResult result) { super(message, result); } } zt-exec-zt-exec-1.11/src/main/java/org/zeroturnaround/exec/InvalidOutputException.java000066400000000000000000000025151350762700300311770ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec; import org.zeroturnaround.exec.listener.ProcessListener; /** * Process finished with an unexpected output. * * @author Rein Raudjärv * @see ProcessListener#afterFinish(Process, ProcessResult) * @since 1.8 */ public class InvalidOutputException extends InvalidResultException { private static final long serialVersionUID = 1L; /** * @param message the detail message of the exception * @param result result of execution (contains also the exit value) */ public InvalidOutputException(String message, ProcessResult result) { super(message, result); } } zt-exec-zt-exec-1.11/src/main/java/org/zeroturnaround/exec/InvalidResultException.java000066400000000000000000000035661350762700300311640ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec; /** * Process finished with an unexpected result. * * @author Rein Raudjärv * @since 1.8 */ public class InvalidResultException extends RuntimeException { private static final long serialVersionUID = 1L; /** * Actual exit value and process output. */ private final ProcessResult result; /** * @param message the detail message of the exception * @param result result of execution (contains also the exit value) */ public InvalidResultException(String message, ProcessResult result) { super(message); this.result = result; } /** * @return actual process result. */ public ProcessResult getResult() { return result; } /** * @return the exit value of the finished process. */ public int getExitValue() { return result.getExitValue(); } /** * @return actual process result. * @deprecated use {@link #getResult()} */ public ProcessResult result() { return getResult(); } /** * @return the exit value of the finished process. * @deprecated use {@link #getExitValue()} */ public int exitValue() { return getExitValue(); } } zt-exec-zt-exec-1.11/src/main/java/org/zeroturnaround/exec/MDCCallableAdapter.java000066400000000000000000000011351350762700300300320ustar00rootroot00000000000000package org.zeroturnaround.exec; import java.util.Map; import java.util.concurrent.Callable; import org.slf4j.MDC; /** * Restores the MDC context map for the target action. */ public class MDCCallableAdapter implements Callable { private final Callable target; private final Map contextMap; public MDCCallableAdapter(Callable target, Map contextMap) { this.target = target; this.contextMap = contextMap; } public T call() throws Exception { MDC.setContextMap(contextMap); try { return target.call(); } finally { MDC.clear(); } } } zt-exec-zt-exec-1.11/src/main/java/org/zeroturnaround/exec/MDCRunnableAdapter.java000066400000000000000000000010241350762700300300760ustar00rootroot00000000000000package org.zeroturnaround.exec; import java.util.Map; import org.slf4j.MDC; /** * Restores the MDC context map for the target action. */ public class MDCRunnableAdapter implements Runnable { private final Runnable target; private final Map contextMap; public MDCRunnableAdapter(Runnable target, Map contextMap) { this.target = target; this.contextMap = contextMap; } public void run() { MDC.setContextMap(contextMap); try { target.run(); } finally { MDC.clear(); } } } zt-exec-zt-exec-1.11/src/main/java/org/zeroturnaround/exec/MessageLogger.java000066400000000000000000000022211350762700300272270ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec; import org.slf4j.Logger; /** * Logs messages at certain level. */ public interface MessageLogger { /** * Log a message at certain level according to the specified format and arguments. * * @param log logger to be used. * @param format the format string * @param arguments a list of arguments */ void message(Logger log, String format, Object... arguments); } zt-exec-zt-exec-1.11/src/main/java/org/zeroturnaround/exec/MessageLoggers.java000066400000000000000000000037121350762700300274200ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec; import org.slf4j.Logger; import org.zeroturnaround.exec.stream.slf4j.Level; /** * Contains {@link MessageLogger} instances for various log levels. */ public class MessageLoggers { public static final MessageLogger NOP = new MessageLogger() { public void message(Logger log, String format, Object... arguments) { // do nothing } }; public static final MessageLogger TRACE = new MessageLogger() { public void message(Logger log, String format, Object... arguments) { log.trace(format, arguments); } }; public static final MessageLogger DEBUG = new MessageLogger() { public void message(Logger log, String format, Object... arguments) { log.debug(format, arguments); } }; public static final MessageLogger INFO = new MessageLogger() { public void message(Logger log, String format, Object... arguments) { log.info(format, arguments); } }; public static final MessageLogger get(Level level) { switch (level) { case TRACE: return TRACE; case DEBUG: return DEBUG; case INFO: return INFO; default: throw new IllegalArgumentException("Invalid level " + level); } } private MessageLoggers() { // hide } } zt-exec-zt-exec-1.11/src/main/java/org/zeroturnaround/exec/ProcessAttributes.java000066400000000000000000000040101350762700300301660ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec; import java.io.File; import java.util.List; import java.util.Map; import java.util.Set; /** * Immutable set of attributes used to start a process. */ class ProcessAttributes { /** * The external program and its arguments. */ private final List command; /** * Working directory, null in case of current working directory. */ private final File directory; /** * Environment variables which are added (removed in case of null values) to the started process. */ private final Map environment; /** * Set of accepted exit codes or null if all exit codes are allowed. */ private final Set allowedExitValues; public ProcessAttributes(List command, File directory, Map environment, Set allowedExitValues) { this.command = command; this.directory = directory; this.environment = environment; this.allowedExitValues = allowedExitValues; } public List getCommand() { return command; } public File getDirectory() { return directory; } public Map getEnvironment() { return environment; } public Set getAllowedExitValues() { return allowedExitValues; } } zt-exec-zt-exec-1.11/src/main/java/org/zeroturnaround/exec/ProcessExecutor.java000066400000000000000000001263431350762700300276540ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.MDC; import org.zeroturnaround.exec.close.ProcessCloser; import org.zeroturnaround.exec.close.StandardProcessCloser; import org.zeroturnaround.exec.close.TimeoutProcessCloser; import org.zeroturnaround.exec.listener.*; import org.zeroturnaround.exec.stop.DestroyProcessStopper; import org.zeroturnaround.exec.stop.NopProcessStopper; import org.zeroturnaround.exec.stop.ProcessStopper; import org.zeroturnaround.exec.stream.*; import org.zeroturnaround.exec.stream.slf4j.Slf4jDebugOutputStream; import org.zeroturnaround.exec.stream.slf4j.Slf4jInfoOutputStream; import org.zeroturnaround.exec.stream.slf4j.Slf4jStream; import java.io.*; import java.util.*; import java.util.Map.Entry; import java.util.concurrent.*; /** * Helper for executing sub processes. *

* It's implemented as a wrapper of {@link ProcessBuilder} complementing it with additional features such as: *

*
    *
  • Handling process streams (copied from Commons Exec library).
  • *
  • Destroying process on VM exit (copied from Commons Exec library).
  • *
  • Checking process exit code.
  • *
  • Setting a timeout for running the process and automatically stopping it in case of timeout.
  • *
  • Either waiting for the process to finish ({@link #execute()}) or returning a {@link Future} ({@link #start()}.
  • *
  • Reading the process output stream into a buffer ({@link #readOutput(boolean)}, {@link ProcessResult}).
  • *
* *

* The default configuration for executing a process is following: *

*
    *
  • Process is not automatically destroyed on VM exit.
  • *
  • Error stream is redirected to its output stream. Use {@link #redirectErrorStream(boolean)} to override it.
  • *
  • Output stream is pumped to a {@link NullOutputStream}, Use {@link #streams(ExecuteStreamHandler)}, {@link #redirectOutput(OutputStream)}, * or any of the redirectOutputAs* methods.to override it.
  • *
  • Any exit code is allowed. Use {@link #exitValues(Integer...)} to override it.
  • *
  • In case of timeout or cancellation {@link Process#destroy()} is invoked.
  • *
* * @author Rein Raudjärv * @see ProcessResult */ public class ProcessExecutor { private static final Logger log = LoggerFactory.getLogger(ProcessExecutor.class); private static final boolean IS_OS_WINDOWS = System.getProperty("os.name").startsWith("Windows"); public static final Integer[] DEFAULT_EXIT_VALUES = null; private static final Integer NORMAL_EXIT_VALUE = 0; public static final boolean DEFAULT_REDIRECT_ERROR_STREAM = true; /** * Process builder used by this executor. */ private final ProcessBuilder builder = new ProcessBuilder(); /** * Environment variables which are added (removed in case of null values) to the process being started. */ private final Map environment = new LinkedHashMap(); /** * Set of accepted exit codes or null if all exit codes are allowed. */ private Set allowedExitValues; /** * Timeout for running a process. If the process is running too long a {@link TimeoutException} is thrown and the process is destroyed. */ private Long timeout; private TimeUnit timeoutUnit; /** * Helper for stopping the process in case of timeout or cancellation. */ private ProcessStopper stopper; /** * Process stream Handler (copied from Commons Exec library). If null streams are not handled. */ private ExecuteStreamHandler streams; /** * Timeout for closing process' standard streams. In case this timeout is reached we just log a warning but don't throw an error. */ private Long closeTimeout; private TimeUnit closeTimeoutUnit; /** * true if the process output should be read to a buffer and returned by {@link ProcessResult#output()}. */ private boolean readOutput; /** * Process event handlers. */ private final CompositeProcessListener listeners = new CompositeProcessListener(); /** * Helper for logging messages about starting and waiting for the processes. */ private MessageLogger messageLogger = MessageLoggers.DEBUG; { // Run in case of any constructor exitValues(DEFAULT_EXIT_VALUES); stopper(DestroyProcessStopper.INSTANCE); redirectOutput(null); redirectError(null); destroyer(null); redirectErrorStream(DEFAULT_REDIRECT_ERROR_STREAM); } /** * Creates new {@link ProcessExecutor} instance. */ public ProcessExecutor() { } /** * Creates new {@link ProcessExecutor} instance for the given program and its arguments. * @param command The list containing the program and its arguments. */ public ProcessExecutor(List command) { command(command); } /** * Creates new {@link ProcessExecutor} instance for the given program and its arguments. * @param command A string array containing the program and its arguments. */ public ProcessExecutor(String... command) { command(command); } /** * Creates new {@link ProcessExecutor} instance for the given program and its arguments. * @param command The iterable containing the program and its arguments. * @since 1.8 */ public ProcessExecutor(Iterable command) { command(command); } /** * Returns this process executor's operating system program and arguments. * The returned list is a copy. * * @return this process executor's program and its arguments (not null). */ public List getCommand() { return new ArrayList(builder.command()); } /** * Sets the program and its arguments which are being executed. * * @param command The list containing the program and its arguments. * @return This process executor. */ public ProcessExecutor command(List command) { builder.command(fixArguments(command)); return this; } /** * Sets the program and its arguments which are being executed. * * @param command A string array containing the program and its arguments. * @return This process executor. */ public ProcessExecutor command(String... command) { builder.command(fixArguments(Arrays.asList(command))); return this; } /** * Sets the program and its arguments which are being executed. * * @param command The iterable containing the program and its arguments. * @return This process executor. * @since 1.8 */ public ProcessExecutor command(Iterable command) { List list = new ArrayList(); Iterator it = command.iterator(); while (it.hasNext()) { list.add(it.next()); } return command(list); } /** * Splits string by spaces and passes it to {@link ProcessExecutor#command(String...)}
* * NB: this method do not handle whitespace escaping, * "mkdir new\ folder" would be interpreted as * {"mkdir", "new\", "folder"} command. * * @param commandWithArgs A string array containing the program and its arguments. * @return This process executor. */ public ProcessExecutor commandSplit(String commandWithArgs) { builder.command(commandWithArgs.split("\\s+")); return this; } /** * Returns this process executor's working directory. * * Subprocesses subsequently started by this object will use this as their working directory. * The returned value may be {@code null} -- this means to use * the working directory of the current Java process, usually the * directory named by the system property {@code user.dir}, * as the working directory of the child process. * * @return this process executor's working directory */ public File getDirectory() { return builder.directory(); } /** * Sets this working directory for the process being executed. * The argument may be null -- this means to use the * working directory of the current Java process, usually the * directory named by the system property user.dir, * as the working directory of the child process. * * @param directory The new working directory * @return This process executor. */ public ProcessExecutor directory(File directory) { builder.directory(directory); return this; } /** * Returns this process executor's additional environment variables. * The returned value is not a copy. * * @return this process executor's environment variables (not null). */ public Map getEnvironment() { return environment; } /** * Adds additional environment variables for the process being executed. * * @param env environment variables added to the process being executed. * @return This process executor. */ public ProcessExecutor environment(Map env) { environment.putAll(env); return this; } /** * Adds a single additional environment variable for the process being executed. * * @param name name of the environment variable added to the process being executed. * @param value value of the environment variable added to the process being executed. * @return This process executor. * * @since 1.7 */ public ProcessExecutor environment(String name, String value) { environment.put(name, value); return this; } /** * Sets this process executor's redirectErrorStream property. * *

If this property is true, then any error output generated by subprocesses will be merged with the standard output. * This makes it easier to correlate error messages with the corresponding output. * The initial value is true.

* * @param redirectErrorStream The new property value * @return This process executor. */ public ProcessExecutor redirectErrorStream(boolean redirectErrorStream) { builder.redirectErrorStream(redirectErrorStream); return this; } /** * Allows any exit value for the process being executed. * * @return This process executor. */ public ProcessExecutor exitValueAny() { return exitValues((Integer[]) null); } /** * Allows only 0 as the exit value for the process being executed. * * @return This process executor. */ public ProcessExecutor exitValueNormal() { return exitValues(NORMAL_EXIT_VALUE); } /** * Sets the allowed exit value for the process being executed. * * @param exitValue single exit value or null if all exit values are allowed. * @return This process executor. */ public ProcessExecutor exitValue(Integer exitValue) { return exitValues(exitValue == null ? null : new Integer[] { exitValue } ); } /** * Sets the allowed exit values for the process being executed. * * @param exitValues set of exit values or null if all exit values are allowed. * @return This process executor. */ public ProcessExecutor exitValues(Integer... exitValues) { allowedExitValues = exitValues == null ? null : new HashSet(Arrays.asList(exitValues)); return this; } /** * Sets the allowed exit values for the process being executed. * * @param exitValues set of exit values or null if all exit values are allowed. * @return This process executor. */ public ProcessExecutor exitValues(int[] exitValues) { if (exitValues == null) return exitValueAny(); // Convert int[] -> Integer[] Integer[] array = new Integer[exitValues.length]; for (int i = 0; i < array.length; i++) array[i] = exitValues[i]; return exitValues(array); } /** * Sets a timeout for the process being executed. When this timeout is reached a {@link TimeoutException} is thrown and the process is destroyed. * This only applies to execute methods not start methods. * * @param timeout timeout for running a process. * @param unit the time unit of the timeout * @return This process executor. */ public ProcessExecutor timeout(long timeout, TimeUnit unit) { this.timeout = timeout; this.timeoutUnit = unit; return this; } /** * Sets the helper for stopping the process in case of timeout or cancellation. *

* By default {@link DestroyProcessStopper} is used which just invokes {@link Process#destroy()}. * * @param stopper helper for stopping the process (null means {@link NopProcessStopper} - process is not stopped). * @return This process executor. */ public ProcessExecutor stopper(ProcessStopper stopper) { if (stopper == null) { stopper = NopProcessStopper.INSTANCE; } this.stopper = stopper; return this; } /** * @return current stream handler for the process being executed. */ public ExecuteStreamHandler streams() { return streams; } /** * Sets a stream handler for the process being executed. * This will overwrite any stream redirection that was previously set to use the provided handler. * * @param streams the stream handler * @return This process executor. */ public ProcessExecutor streams(ExecuteStreamHandler streams) { validateStreams(streams, readOutput); this.streams = streams; return this; } /** * Sets a timeout for closing standard streams of the process being executed. * When this timeout is reached we log a warning but consider that the process has finished. * We also flush the streams so that all output read so far is available. *

* This can be used on Windows in case a process exits quickly but closing the streams blocks forever. *

*

* Closing timeout must fit into the general execution timeout (see {@link #timeout(long, TimeUnit)}). * By default there's no closing timeout. * * @param timeout timeout for closing streams of a process. * @param unit the time unit of the timeout * @return This process executor. */ public ProcessExecutor closeTimeout(long timeout, TimeUnit unit) { this.closeTimeout = timeout; this.closeTimeoutUnit = unit; return this; } /** * Sets the input stream to redirect to the process' input stream. * If this method is invoked multiple times each call overwrites the previous. * * @param input input stream that will be written to the process input stream (null means nothing will be written to the process input stream). * @return This process executor. */ public ProcessExecutor redirectInput(InputStream input) { PumpStreamHandler pumps = pumps(); // Only set the input stream handler, preserve the same output and error stream handler return streams(new PumpStreamHandler(pumps == null ? null : pumps.getOut(), pumps == null ? null : pumps.getErr(), input)); } /** * Redirects the process' output stream to given output stream. * If this method is invoked multiple times each call overwrites the previous. * Use {@link #redirectOutputAlsoTo(OutputStream)} if you want to redirect the output to multiple streams. * * @param output output stream where the process output is redirected to (null means {@link NullOutputStream} which acts like a /dev/null). * @return This process executor. */ public ProcessExecutor redirectOutput(OutputStream output) { if (output == null) output = NullOutputStream.NULL_OUTPUT_STREAM; PumpStreamHandler pumps = pumps(); // Only set the output stream handler, preserve the same error stream handler return streams(new PumpStreamHandler(output, pumps == null ? null : pumps.getErr(), pumps == null ? null : pumps.getInput())); } /** * Redirects the process' error stream to given output stream. * If this method is invoked multiple times each call overwrites the previous. * Use {@link #redirectErrorAlsoTo(OutputStream)} if you want to redirect the error to multiple streams. *

* Calling this method automatically disables merging the process error stream to its output stream. *

* * @param output output stream where the process error is redirected to (null means {@link NullOutputStream} which acts like a /dev/null). * @return This process executor. */ public ProcessExecutor redirectError(OutputStream output) { if (output == null) output = NullOutputStream.NULL_OUTPUT_STREAM; PumpStreamHandler pumps = pumps(); // Only set the error stream handler, preserve the same output stream handler streams(new PumpStreamHandler(pumps == null ? null : pumps.getOut(), output, pumps == null ? null : pumps.getInput())); redirectErrorStream(false); return this; } /** * Redirects the process' output stream also to a given output stream. * This method can be used to redirect output to multiple streams. * * @param output the stream to redirect this output to * @return This process executor. */ public ProcessExecutor redirectOutputAlsoTo(OutputStream output) { return streams(redirectOutputAlsoTo(pumps(), output)); } /** * Redirects the process' error stream also to a given output stream. * This method can be used to redirect error to multiple streams. *

* Calling this method automatically disables merging the process error stream to its output stream. *

* * @param output the output stream to redirect the error stream to * @return This process executor. */ public ProcessExecutor redirectErrorAlsoTo(OutputStream output) { streams(redirectErrorAlsoTo(pumps(), output)); redirectErrorStream(false); return this; } /** * @return current PumpStreamHandler (maybe null). * @throws IllegalStateException if the current stream handler is not an instance of {@link PumpStreamHandler}. * * @see #streams() */ public PumpStreamHandler pumps() { if (streams == null) return null; if (!(streams instanceof PumpStreamHandler)) throw new IllegalStateException("Only PumpStreamHandler is supported."); return (PumpStreamHandler) streams; } /** * Redirects the process' output stream also to a given output stream. * * @return new stream handler created. */ private static PumpStreamHandler redirectOutputAlsoTo(PumpStreamHandler pumps, OutputStream output) { if (output == null) throw new IllegalArgumentException("OutputStream must be provided."); OutputStream current = pumps.getOut(); if (current != null && !(current instanceof NullOutputStream)) { output = new TeeOutputStream(current, output); } return new PumpStreamHandler(output, pumps.getErr(), pumps.getInput()); } /** * Redirects the process' error stream also to a given output stream. * * @return new stream handler created. */ private static PumpStreamHandler redirectErrorAlsoTo(PumpStreamHandler pumps, OutputStream output) { if (output == null) throw new IllegalArgumentException("OutputStream must be provided."); OutputStream current = pumps.getErr(); if (current != null && !(current instanceof NullOutputStream)) { output = new TeeOutputStream(current, output); } return new PumpStreamHandler(pumps.getOut(), output, pumps.getInput()); } /** * Sets this process executor's readOutput property. * *

If this property is true, * the process output should be read to a buffer and returned by {@link ProcessResult#output()}. * The initial value is false.

* * @param readOutput The new property value * @return This process executor. */ public ProcessExecutor readOutput(boolean readOutput) { validateStreams(streams, readOutput); this.readOutput = readOutput; return this; } /** * Validates that if readOutput is true the output could be read with the given {@link ExecuteStreamHandler} instance. */ private void validateStreams(ExecuteStreamHandler streams, boolean readOutput) { if (readOutput && !(streams instanceof PumpStreamHandler)) throw new IllegalStateException("Only PumpStreamHandler is supported if readOutput is true."); } /** * Logs the process' output to a given {@link Logger} with info level. * * @param log the logger to process the output to * @return This process executor. * @deprecated use {@link #redirectOutput(OutputStream)} and {@link Slf4jStream} */ public ProcessExecutor info(Logger log) { return redirectOutput(new Slf4jInfoOutputStream(log)); } /** * Logs the process' output to a given {@link Logger} with debug level. * * @param log the logger to process the output to * @return This process executor. * @deprecated use {@link #redirectOutput(OutputStream)} and {@link Slf4jStream} */ public ProcessExecutor debug(Logger log) { return redirectOutput(new Slf4jDebugOutputStream(log)); } /** * Logs the process' output to a {@link Logger} with given name using info level. * * @param name the name of the logger to process the output to * @return This process executor. * @deprecated use {@link #redirectOutput(OutputStream)} and {@link Slf4jStream} */ public ProcessExecutor info(String name) { return info(getCallerLogger(name)); } /** * Logs the process' output to a {@link Logger} with given name using debug level. * * @param name the name of the logger to process the output to * @return This process executor. * @deprecated use {@link #redirectOutput(OutputStream)} and {@link Slf4jStream} */ public ProcessExecutor debug(String name) { return debug(getCallerLogger(name)); } /** * Logs the process' output to a {@link Logger} of the caller class using info level. * * @return This process executor. * @deprecated use {@link #redirectOutput(OutputStream)} and {@link Slf4jStream} */ public ProcessExecutor info() { return info(getCallerLogger(null)); } /** * Logs the process' output to a {@link Logger} of the caller class using debug level. * @return This process executor. * @deprecated use {@link #redirectOutput(OutputStream)} and {@link Slf4jStream} */ public ProcessExecutor debug() { return debug(getCallerLogger(null)); } /** * Logs the process' output to a given {@link Logger} with info level. * * @param log the logger to output the message to * @return This process executor. * @deprecated use {@link #redirectOutput(OutputStream)} and {@link Slf4jStream} */ public ProcessExecutor redirectOutputAsInfo(Logger log) { return redirectOutput(new Slf4jInfoOutputStream(log)); } /** * Logs the process' output to a given {@link Logger} with debug level. * * @param log the logger to output the message to * @return This process executor. * @deprecated use {@link #redirectOutput(OutputStream)} and {@link Slf4jStream} */ public ProcessExecutor redirectOutputAsDebug(Logger log) { return redirectOutput(new Slf4jDebugOutputStream(log)); } /** * Logs the process' output to a {@link Logger} with given name using info level. * * @param name the name of the logger to log to * @return This process executor. * @deprecated use {@link #redirectOutput(OutputStream)} and {@link Slf4jStream} */ public ProcessExecutor redirectOutputAsInfo(String name) { return redirectOutputAsInfo(getCallerLogger(name)); } /** * Logs the process' output to a {@link Logger} with given name using debug level. * * @param name the name of the logger to process output to * @return This process executor. * @deprecated use {@link #redirectOutput(OutputStream)} and {@link Slf4jStream} */ public ProcessExecutor redirectOutputAsDebug(String name) { return redirectOutputAsDebug(getCallerLogger(name)); } /** * Logs the process' output to a {@link Logger} of the caller class using info level. * @return This process executor. * @deprecated use {@link #redirectOutput(OutputStream)} and {@link Slf4jStream} */ public ProcessExecutor redirectOutputAsInfo() { return redirectOutputAsInfo(getCallerLogger(null)); } /** * Logs the process' output to a {@link Logger} of the caller class using debug level. * @return This process executor. * @deprecated use {@link #redirectOutput(OutputStream)} and {@link Slf4jStream} */ public ProcessExecutor redirectOutputAsDebug() { return redirectOutputAsDebug(getCallerLogger(null)); } /** * Logs the process' error to a given {@link Logger} with info level. * * @param log the logger to process output to * @return This process executor. * @deprecated use {@link #redirectError(OutputStream)} and {@link Slf4jStream} */ public ProcessExecutor redirectErrorAsInfo(Logger log) { return redirectError(new Slf4jInfoOutputStream(log)); } /** * Logs the process' error to a given {@link Logger} with debug level. * * @param log the logger to process the error to * @return This process executor. * @deprecated use {@link #redirectError(OutputStream)} and {@link Slf4jStream} */ public ProcessExecutor redirectErrorAsDebug(Logger log) { return redirectError(new Slf4jDebugOutputStream(log)); } /** * Logs the process' error to a {@link Logger} with given name using info level. * * @param name the name of the logger to process the error to * @return This process executor. * @deprecated use {@link #redirectError(OutputStream)} and {@link Slf4jStream} */ public ProcessExecutor redirectErrorAsInfo(String name) { return redirectErrorAsInfo(getCallerLogger(name)); } /** * Logs the process' error to a {@link Logger} with given name using debug level. * * @param name the name of the logger to process the error to * @return This process executor. * @deprecated use {@link #redirectError(OutputStream)} and {@link Slf4jStream} */ public ProcessExecutor redirectErrorAsDebug(String name) { return redirectErrorAsDebug(getCallerLogger(name)); } /** * Logs the process' error to a {@link Logger} of the caller class using info level. * @return This process executor. * @deprecated use {@link #redirectError(OutputStream)} and {@link Slf4jStream} */ public ProcessExecutor redirectErrorAsInfo() { return redirectErrorAsInfo(getCallerLogger(null)); } /** * Logs the process' error to a {@link Logger} of the caller class using debug level. * @return This process executor. * @deprecated use {@link #redirectError(OutputStream)} and {@link Slf4jStream} */ public ProcessExecutor redirectErrorAsDebug() { return redirectErrorAsDebug(getCallerLogger(null)); } /** * Creates a {@link Logger} for the {@link ProcessExecutor}'s caller class. * * @param name name of the logger. * @return SLF4J Logger instance. */ private Logger getCallerLogger(String name) { return LoggerFactory.getLogger(CallerLoggerUtil.getName(name, 2)); } /** * Adds a process destroyer to be notified when the process starts and stops. * @param destroyer helper for destroying all processes on certain event such as VM exit (not null). * * @return This process executor. */ public ProcessExecutor addDestroyer(ProcessDestroyer destroyer) { return addListener(new DestroyerListenerAdapter(destroyer)); } /** * Sets the process destroyer to be notified when the process starts and stops. *

* This methods always removes any other {@link ProcessDestroyer} registered. Use {@link #addDestroyer(ProcessDestroyer)} to keep the existing ones. * * @param destroyer helper for destroying all processes on certain event such as VM exit (maybe null). * * @return This process executor. */ public ProcessExecutor destroyer(ProcessDestroyer destroyer) { removeListeners(DestroyerListenerAdapter.class); if (destroyer != null) addListener(new DestroyerListenerAdapter(destroyer)); return this; } /** * Sets the started process to be destroyed on VM exit (shutdown hooks are executed). * If this VM gets killed the started process may not get destroyed. *

* To undo this command call destroyer(null). * * @return This process executor. */ public ProcessExecutor destroyOnExit() { return destroyer(ShutdownHookProcessDestroyer.INSTANCE); } /** * Unregister all existing process event handlers and register new one. * @param listener process event handler to be set (maybe null). * * @return This process executor. */ public ProcessExecutor listener(ProcessListener listener) { clearListeners(); if (listener != null) addListener(listener); return this; } /** * Register new process event handler. * @param listener process event handler to be added. * * @return This process executor. */ public ProcessExecutor addListener(ProcessListener listener) { listeners.add(listener); return this; } /** * Unregister existing process event handler. * @param listener process event handler to be removed. * * @return This process executor. */ public ProcessExecutor removeListener(ProcessListener listener) { listeners.remove(listener); return this; } /** * Unregister existing process event handlers of given type or its sub-types. * @param listenerType process event handler type. * * @return This process executor. */ public ProcessExecutor removeListeners(Class listenerType) { listeners.removeAll(listenerType); return this; } /** * Unregister all existing process event handlers. * * @return This process executor. */ public ProcessExecutor clearListeners() { listeners.clear(); return this; } /** * Changes how most common messages about starting and waiting for processes are actually logged. * By default {@link MessageLoggers#DEBUG} is used. * However if someone is executing a process every second {@link MessageLoggers#TRACE} may be used e.g. * * @param messageLogger message logger for certain level. * * @return This process executor. */ public ProcessExecutor setMessageLogger(MessageLogger messageLogger) { this.messageLogger = messageLogger; return this; } /** * Executes the sub process. This method waits until the process exits, a timeout occurs or the caller thread gets interrupted. * In the latter cases the process gets destroyed as well. * * @return exit code of the finished process. * @throws IOException an error occurred when process was started or stopped. * @throws InterruptedException this thread was interrupted. * @throws TimeoutException timeout set by {@link #timeout(long, TimeUnit)} was reached. * @throws InvalidExitValueException if invalid exit value was returned (@see {@link #exitValues(Integer...)}). */ public ProcessResult execute() throws IOException, InterruptedException, TimeoutException, InvalidExitValueException { return waitFor(startInternal()); } /** * Executes the sub process. This method waits until the process exits. * Value passed to {@link #timeout(long, TimeUnit)} is ignored (use {@link #execute()} for timeout). * * @return exit code of the finished process. * @throws IOException an error occurred when process was started or stopped. * @throws InterruptedException this thread was interrupted. * @throws InvalidExitValueException if invalid exit value was returned (@see {@link #exitValues(Integer...)}). */ public ProcessResult executeNoTimeout() throws IOException, InterruptedException, InvalidExitValueException { return startInternal().call(); } /** * Check the exit value of given process result. This can be used by unit tests. * * @param result process result which maybe constructed by a unit test. * @throws InvalidExitValueException if the given exit value was rejected. */ public void checkExitValue(ProcessResult result) throws InvalidExitValueException { InvalidExitUtil.checkExit(getAttributes(), result); } /** * Start the sub process. This method does not wait until the process exits. * Value passed to {@link #timeout(long, TimeUnit)} is ignored. * Use {@link Future#get()} to wait for the process to finish. * Invoke future.cancel(true); to destroy the process. * * @return Future representing the exit value of the finished process. * @throws IOException an error occurred when process was started. */ public StartedProcess start() throws IOException { WaitForProcess task = startInternal(); ExecutorService service = newExecutor(task); Future future = invokeSubmit(service, task); // Previously submitted tasks are executed but no new tasks will be accepted. // However sub classes could return null as the ExecutorService if (service != null) { service.shutdown(); } return new StartedProcess(task.getProcess(), future); } /** * Start the process and its stream handlers. * * @return process the started process. * @throws IOException the process or its stream handlers couldn't start (in the latter case we also destroy the process). */ protected final WaitForProcess startInternal() throws IOException { // Invoke listeners - they can modify this executor listeners.beforeStart(this); if (builder.command().isEmpty()) { throw new IllegalStateException("Command has not been set."); } validateStreams(streams, readOutput); applyEnvironment(); messageLogger.message(log, getExecutingLogMessage()); Process process = invokeStart(); messageLogger.message(log, "Started {}", process); ProcessAttributes attributes = getAttributes(); ExecuteStreamHandler newStreams = streams; ByteArrayOutputStream out = null; if (readOutput) { PumpStreamHandler pumps = (PumpStreamHandler) streams; out = new ByteArrayOutputStream(); newStreams = redirectOutputAlsoTo(pumps, out); } return startInternal(process, attributes, newStreams, out); } /** * Capture a snapshot of this process executor's main state. */ private ProcessAttributes getAttributes() { return new ProcessAttributes( getCommand(), getDirectory(), new LinkedHashMap(environment), allowedExitValues == null ? null : new HashSet(allowedExitValues)); } private Process invokeStart() throws IOException { try { return builder.start(); } catch (IOException e) { if (e.getClass().equals(IOException.class)) { String message = getExecutingErrorMessage(); ProcessInitException p = ProcessInitException.newInstance(message, e); if (p != null) { throw p; } throw new IOException(message, e); } throw e; } catch (RuntimeException e) { if (e.getClass().equals(IllegalArgumentException.class)) { throw new IllegalArgumentException(getExecutingErrorMessage(), e); } throw e; } } private String getExecutingLogMessage() { return "Executing " + getExecutingMessageParams(); } private String getExecutingErrorMessage() { return "Could not execute " + getExecutingMessageParams(); } private String getExecutingMessageParams() { String result = "" + builder.command(); if (builder.directory() != null) { result += " in " + builder.directory(); } if (!environment.isEmpty()) { result += " with environment " + environment; } result += "."; return result; } private WaitForProcess startInternal(Process process, ProcessAttributes attributes, ExecuteStreamHandler streams, ByteArrayOutputStream out) throws IOException { if (streams != null) { try { streams.setProcessInputStream(process.getOutputStream()); streams.setProcessOutputStream(process.getInputStream()); if (!builder.redirectErrorStream()) streams.setProcessErrorStream(process.getErrorStream()); } catch (IOException e) { process.destroy(); throw e; } streams.start(); } ProcessCloser closer = newProcessCloser(streams); WaitForProcess result = new WaitForProcess(process, attributes, stopper, closer, out, listeners.clone(), messageLogger); // Invoke listeners - changing this executor does not affect the started process any more listeners.afterStart(process, this); return result; } private ProcessCloser newProcessCloser(ExecuteStreamHandler streams) { if (closeTimeout == null) { return new StandardProcessCloser(streams); } return new TimeoutProcessCloser(streams, closeTimeout, closeTimeoutUnit); } /** * Wait until the process stops, a timeout occurs and the caller thread gets interrupted. * In the latter cases the process gets destroyed as well. */ private ProcessResult waitFor(WaitForProcess task) throws IOException, InterruptedException, TimeoutException { ProcessResult result; if (timeout == null) { // Use the current thread result = task.call(); } else { // Fork another thread to invoke Process.waitFor() ExecutorService service = newExecutor(task); // Copy values to not conflict with further executions long _timeout = timeout; TimeUnit unit = timeoutUnit; try { result = invokeSubmit(service, task).get(_timeout, unit); } catch (ExecutionException e) { Throwable c = e.getCause(); if (c instanceof IOException) { throw (IOException) c; } if (c instanceof InterruptedException) { throw (InterruptedException) c; } if (c instanceof InvalidExitValueException) { InvalidExitValueException i = (InvalidExitValueException) c; throw new InvalidExitValueException(i.getMessage(), i.getResult()); } if (c instanceof InvalidOutputException) { InvalidOutputException i = (InvalidOutputException) c; throw new InvalidOutputException(i.getMessage(), i.getResult()); } if (c.getClass().equals(InvalidResultException.class)) { InvalidResultException p = (InvalidResultException) c; throw new InvalidResultException(p.getMessage(), p.getResult()); } throw new IllegalStateException("Error occured while waiting for process to finish:", c); } catch (TimeoutException e) { messageLogger.message(log, "{} is running too long", task); throw newTimeoutException(_timeout, unit, task); } finally { // Interrupt the task if it's still running and release the ExecutorService's resources service.shutdownNow(); } } return result; } private ExecutorService newExecutor(WaitForProcess task) { return newExecutor(task.getProcess().toString()); } protected ExecutorService newExecutor(String processName) { // Use daemon thread as we don't want to postpone the shutdown // If #destroyOnExit() is used we wait for the process to be destroyed anyway final String name = "WaitForProcess-" + processName; ExecutorService service = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() { public Thread newThread(Runnable r) { Thread t = new Thread(r, name); t.setDaemon(true); return t; } }); return service; } /** * Override this to customize how the waiting task is started in the background. * * @param the type of the task * @param executor the executor service to submit the task on * @param task the task to be submitted * @return the future of the task */ protected Future invokeSubmit(ExecutorService executor, Callable task) { return executor.submit(wrapTask(task)); } /** * Override this to customize how the background task is created. * * @param the type of the Task * @param task the Task to be wrapped * @return the wrapped task */ protected Callable wrapTask(Callable task) { // Preserve the MDC context of the caller thread. Map contextMap = MDC.getCopyOfContextMap(); if (contextMap != null) { return new MDCCallableAdapter(task, contextMap); } return task; } private TimeoutException newTimeoutException(long timeout, TimeUnit unit, WaitForProcess task) { StringBuilder sb = new StringBuilder(); Process process = task.getProcess(); Integer exitValue = getExitCodeOrNull(process); if (exitValue == null) { sb.append("Timed out waiting for ").append(process).append(" to finish"); } else { sb.append("Timed out finishing ").append(process); sb.append(", exit value: ").append(exitValue); } sb.append(", timeout: ").append(timeout).append(" ").append(getUnitsAsString(timeout, unit)); task.addExceptionMessageSuffix(sb); TimeoutException result = new TimeoutException(sb.toString()); if (exitValue != null) { StackTraceElement[] stackTrace = task.getStackTrace(); if (stackTrace != null) { Exception cause = new Exception("Stack dump of worker thread."); cause.setStackTrace(stackTrace); result.initCause(cause); } } return result; } private static String getUnitsAsString(long d, TimeUnit unit) { String result = unit.toString().toLowerCase(); if (d == 1) { result = result.substring(0, result.length() - 1); } return result; } private static Integer getExitCodeOrNull(Process process) { try { return process.exitValue(); } catch (IllegalThreadStateException e) { return null; } } private void applyEnvironment() { if (environment.isEmpty()) { return; // skip } Map env = builder.environment(); for (Entry e : environment.entrySet()) { String key = e.getKey(); String value = e.getValue(); if (value == null) { env.remove(key); } else { env.put(key, value); } } } /** * Fixes the command line arguments on Windows by replacing empty arguments with "". Otherwise these arguments would be just skipped. * * @see http://bugs.java.com/view_bug.do?bug_id=7028124 * @see https://bugs.openjdk.java.net/browse/JDK-6518827 */ private static List fixArguments(List command) { if (!IS_OS_WINDOWS) { return command; } List result = new ArrayList(command); for (ListIterator it = result.listIterator(); it.hasNext(); ) { if ("".equals(it.next())) { it.set("\"\""); } } return result; } } zt-exec-zt-exec-1.11/src/main/java/org/zeroturnaround/exec/ProcessInitException.java000066400000000000000000000053051350762700300306320ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec; import java.io.IOException; /** * Creating a process failed providing an error code. * *

* Wraps an {@link IOException} like: *

    *
  • java.io.IOException: Cannot run program "ls": java.io.IOException: error=12, Cannot allocate memory
  • *
  • java.io.IOException: Cannot run program "ls": error=316, Unknown error: 316
  • *
*/ public class ProcessInitException extends IOException { private static final String BEFORE_CODE = " error="; private static final String AFTER_CODE = ", "; private static final String NEW_INFIX = " Error="; private final int errorCode; public ProcessInitException(String message, Throwable cause, int errorCode) { super(message, cause); this.errorCode = errorCode; } /** * @return error code raised when a process failed to start. */ public int getErrorCode() { return errorCode; } /** * Try to wrap a given {@link IOException} into a {@link ProcessInitException}. * * @param prefix prefix to be added in the message. * @param e existing exception possibly containing an error code in its message. * @return new exception containing the prefix, error code and its description in the message plus the error code value as a field, * null if we were unable to find an error code from the original message. */ public static ProcessInitException newInstance(String prefix, IOException e) { String m = e.getMessage(); if (m == null) { return null; } int i = m.lastIndexOf(BEFORE_CODE); if (i == -1) { return null; } int j = m.indexOf(AFTER_CODE, i); if (j == -1) { return null; } int code; try { code = Integer.parseInt(m.substring(i + BEFORE_CODE.length(), j)); } catch (NumberFormatException n) { return null; } return new ProcessInitException(prefix + NEW_INFIX + m.substring(i + BEFORE_CODE.length()), e, code); } } zt-exec-zt-exec-1.11/src/main/java/org/zeroturnaround/exec/ProcessOutput.java000066400000000000000000000055451350762700300273560ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.List; import java.util.StringTokenizer; /** * Standard output of a finished process. * * @author Rein Raudjärv * @see ProcessExecutor */ public class ProcessOutput { /** * Process output (not null). */ private final byte[] data; public ProcessOutput(byte[] data) { this.data = data; } /** * @return binary output of the finished process. */ public byte[] getBytes() { return data; } /** * @return output of the finished process converted to a String using platform's default encoding. */ public String getString() { return new String(getBytes()); } /** * @return output of the finished process converted to UTF-8 String. */ public String getUTF8() { return getString("UTF-8"); } /** * @return output of the finished process converted to a String. * * @param charset The name of a supported char set. */ public String getString(String charset) { try { return new String(getBytes(), charset); } catch (UnsupportedEncodingException e) { throw new IllegalStateException(e.getMessage()); } } /** * @return output lines of the finished process converted using platform's default encoding. */ public List getLines() { return getLinesFrom(getString()); } /** * @return output lines of the finished process converted using UTF-8. */ public List getLinesAsUTF8() { return getLinesFrom(getUTF8()); } /** * @return output lines of the finished process converted using a given char set. * * @param charset The name of a supported char set. */ public List getLines(String charset) { return getLinesFrom(getString(charset)); } static List getLinesFrom(String output) { // Split using both Windows and UNIX line separators List result = new ArrayList(); StringTokenizer st = new StringTokenizer(output, "\n\r"); while (st.hasMoreTokens()) { result.add(st.nextToken()); } return result; } } zt-exec-zt-exec-1.11/src/main/java/org/zeroturnaround/exec/ProcessResult.java000066400000000000000000000067721350762700300273370ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec; /** * Exit value and output of a finished process. * * @author Rein Raudjärv * @see ProcessExecutor */ public class ProcessResult { /** * Exit value of the finished process. */ private final int exitValue; /** * Process output or null if it wasn't read. */ private final ProcessOutput output; public ProcessResult(int exitCode, ProcessOutput output) { this.exitValue = exitCode; this.output = output; } /** * @return the exit value of the finished process. */ public int getExitValue() { return exitValue; } /** * @return the exit value of the finished process. * @deprecated use {@link #getExitValue()} */ public int exitValue() { return getExitValue(); } /** * @return true if the process output was read. */ public boolean hasOutput() { return output != null; } /** * @return output of the finished process. * You have to invoke {@link ProcessExecutor#readOutput(boolean)} to set the process output to be read. * * @throws IllegalStateException if the output was not read. */ public ProcessOutput getOutput() { if (output == null) throw new IllegalStateException("Process output was not read. To enable output reading please call ProcessExecutor.readOutput(true) before starting the process."); return output; } /** * @return binary output of the finished process. * You have to invoke {@link ProcessExecutor#readOutput(boolean)} to set the process output to be read. * * @throws IllegalStateException if the output was not read. */ public byte[] output() { return getOutput().getBytes(); } /** * @return output of the finished process converted to a String using platform's default encoding. * You have to invoke {@link ProcessExecutor#readOutput(boolean)} to set the process output to be read. * * @throws IllegalStateException if the output was not read. */ public String outputString() { return getOutput().getString(); } /** * @return output of the finished process converted to UTF-8 String. * You have to invoke {@link ProcessExecutor#readOutput(boolean)} to set the process output to be read. * * @throws IllegalStateException if the output was not read. */ public String outputUTF8() { return getOutput().getUTF8(); } /** * @return output of the finished process converted to a String. * You have to invoke {@link ProcessExecutor#readOutput(boolean)} to set the process output to be read. * * @param charset The name of a supported char set. * @throws IllegalStateException if the output was not read or the char set was not supported. */ public String outputString(String charset) { return getOutput().getString(charset); } } zt-exec-zt-exec-1.11/src/main/java/org/zeroturnaround/exec/StartedProcess.java000066400000000000000000000035111350762700300274530ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec; import java.util.concurrent.Future; /** * Represents a process that has started. It may or may not have finished. * * @author Rein Raudjärv */ public class StartedProcess { /** * The sub process started. */ private final Process process; /** * The asynchronous result of the started process. */ private final Future future; public StartedProcess(Process process, Future future) { this.process = process; this.future = future; } /** * @return the started process. */ public Process getProcess() { return process; } /** * @return asynchronous result of the started process. */ public Future getFuture() { return future; } /** * @return the started process. * @deprecated use {@link #getProcess()} instead. */ public Process process() { return getProcess(); } /** * @return asynchronous result of the started process. * @deprecated use {@link #getFuture()} instead. */ public Future future() { return getFuture(); } } zt-exec-zt-exec-1.11/src/main/java/org/zeroturnaround/exec/WaitForProcess.java000066400000000000000000000107241350762700300274240ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.concurrent.Callable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.zeroturnaround.exec.close.ProcessCloser; import org.zeroturnaround.exec.listener.ProcessListener; import org.zeroturnaround.exec.stop.ProcessStopper; /** * Handles the executed process. * * @author Rein Raudjärv */ class WaitForProcess implements Callable { private static final Logger log = LoggerFactory.getLogger(WaitForProcess.class); private final Process process; /** * Set of main attributes used to start the process. */ private final ProcessAttributes attributes; /** * Helper for stopping the process in case of interruption. */ private final ProcessStopper stopper; /** * Helper for closing the process' standard streams. */ private final ProcessCloser closer; /** * Buffer where the process output is redirected to or null if it's not used. */ private final ByteArrayOutputStream out; /** * Process event listener (not null). */ private final ProcessListener listener; /** * Helper for logging messages about starting and waiting for the processes. */ private final MessageLogger messageLogger; /** * Thread which executes this operation. */ private volatile Thread workerThread; public WaitForProcess(Process process, ProcessAttributes attributes, ProcessStopper stopper, ProcessCloser closer, ByteArrayOutputStream out, ProcessListener listener, MessageLogger messageLogger) { this.process = process; this.attributes = attributes; this.stopper = stopper; this.closer = closer; this.out = out; this.listener = listener; this.messageLogger = messageLogger; } /** * @return the sub process. */ public Process getProcess() { return process; } public ProcessResult call() throws IOException, InterruptedException { try { workerThread = Thread.currentThread(); int exit; boolean finished = false; try { exit = process.waitFor(); finished = true; messageLogger.message(log, "{} stopped with exit code {}", this, exit); } finally { if (!finished) { messageLogger.message(log, "Stopping {}...", this); stopper.stop(process); } closer.close(process); } ProcessOutput output = getCurrentOutput(); ProcessResult result = new ProcessResult(exit, output); InvalidExitUtil.checkExit(attributes, result); listener.afterFinish(process, result); return result; } finally { // Invoke listeners - regardless process finished or got cancelled listener.afterStop(process); workerThread = null; } } private ProcessOutput getCurrentOutput() { return out == null ? null : new ProcessOutput(out.toByteArray()); } /** * Adds a suffix for an error message including: *
    *
  • executed command
  • *
  • working directory (unless it's inherited from parent)
  • *
  • environment (unless it's the same with the parent)
  • *
  • output read so far (unless it's not read)
  • *
* @param sb where the suffix is appended to. */ public void addExceptionMessageSuffix(StringBuilder sb) { InvalidExitUtil.addExceptionMessageSuffix(attributes, sb, getCurrentOutput()); } /** * @return current stacktrace of the worker thread, null if this operation is currently not running. */ public StackTraceElement[] getStackTrace() { Thread t = workerThread; return t == null ? null : t.getStackTrace(); } @Override public String toString() { return process.toString(); } } zt-exec-zt-exec-1.11/src/main/java/org/zeroturnaround/exec/close/000077500000000000000000000000001350762700300247505ustar00rootroot00000000000000zt-exec-zt-exec-1.11/src/main/java/org/zeroturnaround/exec/close/ExceptionUtil.java000066400000000000000000000016201350762700300304060ustar00rootroot00000000000000package org.zeroturnaround.exec.close; import java.lang.reflect.Method; class ExceptionUtil { /** * Throwable.addSuppressed(Throwable) added in Java 7. */ private static final Method METHOD_ADD_SUPPRESSED = findAddSuppressed(); private static Method findAddSuppressed() { try { return Throwable.class.getDeclaredMethod("addSuppressed", Throwable.class); } catch (Exception e) { // ignore } return null; } /** * If supported. appends the specified exception to the exceptions that were suppressed in order to deliver this exception. */ public static void addSuppressed(Throwable t, Throwable suppressed) { if (METHOD_ADD_SUPPRESSED != null) { try { METHOD_ADD_SUPPRESSED.invoke(t, suppressed); } catch (Exception e) { throw new IllegalStateException("Could not add suppressed exception:", e); } } } } zt-exec-zt-exec-1.11/src/main/java/org/zeroturnaround/exec/close/ProcessCloser.java000066400000000000000000000023551350762700300304060ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec.close; import java.io.IOException; /** * Abstraction for closing sub process' streams. */ public interface ProcessCloser { /** * Closes standard streams of a given sub process. * * @param process sub process (not null). * @throws IOException if I/O errors occur while closing the underlying stream * @throws InterruptedException if underlying throws a InterruptedException */ void close(Process process) throws IOException, InterruptedException; } zt-exec-zt-exec-1.11/src/main/java/org/zeroturnaround/exec/close/StandardProcessCloser.java000066400000000000000000000064331350762700300320700ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec.close; import java.io.IOException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.zeroturnaround.exec.stream.ExecuteStreamHandler; /** * Stops {@link ExecuteStreamHandler} from pumping the streams and closes them. */ public class StandardProcessCloser implements ProcessCloser { private static final Logger log = LoggerFactory.getLogger(StandardProcessCloser.class); protected final ExecuteStreamHandler streams; public StandardProcessCloser(ExecuteStreamHandler streams) { this.streams = streams; } public void close(Process process) throws IOException, InterruptedException { if (streams != null) { streams.stop(); } closeStreams(process); } /** * Close the streams belonging to the given Process. */ private void closeStreams(final Process process) throws IOException { IOException caught = null; try { process.getOutputStream().close(); } catch (IOException e) { if (e.getMessage().equals("Stream closed")) { /** * OutputStream's contract for the close() method: If the stream is already closed then invoking this method has no effect. * * When a UNIXProcess exits ProcessPipeOutputStream automatically closes its target FileOutputStream and replaces it with NullOutputStream. * However the ProcessPipeOutputStream doesn't close itself at that moment. * As ProcessPipeOutputStream extends BufferedOutputStream extends FilterOutputStream closing it flushes the buffer first. * In Java 7 closing FilterOutputStream ignores any exception thrown by the target OutputStream. Since Java 8 these exceptions are now thrown. * * So since Java 8 after UNIXProcess detects the exit and there's something in the output buffer closing this stream throws IOException * with message "Stream closed" from NullOutputStream. */ log.trace("Failed to close process output stream:", e); } else { caught = add(caught, e); } } try { process.getInputStream().close(); } catch (IOException e) { caught = add(caught, e); } try { process.getErrorStream().close(); } catch (IOException e) { caught = add(caught, e); } if (caught != null) { throw caught; } } private static IOException add(IOException exception, IOException newException) { if (exception == null) { return newException; } ExceptionUtil.addSuppressed(exception, newException); return exception; } } zt-exec-zt-exec-1.11/src/main/java/org/zeroturnaround/exec/close/TimeoutProcessCloser.java000066400000000000000000000066011350762700300317530ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec.close; import java.io.IOException; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.zeroturnaround.exec.stream.ExecuteStreamHandler; import org.zeroturnaround.exec.stream.PumpStreamHandler; /** * Same as {@link StandardProcessCloser} but only waits fixed period for the closing. * On timeout a warning is logged but no error is thrown. *

* This is used on Windows where sometimes sub process' streams do not close properly. */ public class TimeoutProcessCloser extends StandardProcessCloser { private static final Logger log = LoggerFactory.getLogger(TimeoutProcessCloser.class); private final long timeout; private final TimeUnit unit; /** * Creates new instance of {@link TimeoutProcessCloser}. * * @param streams helper for pumping the streams. * @param timeout how long should we wait for the closing. * @param unit unit of the timeout value. */ public TimeoutProcessCloser(ExecuteStreamHandler streams, long timeout, TimeUnit unit) { super(streams); this.timeout = timeout; this.unit = unit; } public void close(final Process process) throws IOException, InterruptedException { ExecutorService service = Executors.newSingleThreadScheduledExecutor(); Future future = service.submit(new Callable() { public Void call() throws Exception { doClose(process); return null; } }); // Previously submitted tasks are executed but no new tasks will be accepted. service.shutdown(); try { future.get(timeout, unit); } catch (ExecutionException e) { throw new IllegalStateException("Could not close streams of " + process, e.getCause()); } catch (TimeoutException e) { log.warn("Could not close streams of {} in {} {}", process, timeout, getUnitsAsString(timeout, unit)); } finally { // Ensure that any data received so far is flushed from buffers if (streams instanceof PumpStreamHandler) { ((PumpStreamHandler) streams).flush(); } } } protected void doClose(final Process process) throws IOException, InterruptedException { super.close(process); } private static String getUnitsAsString(long d, TimeUnit unit) { String result = unit.toString().toLowerCase(); if (d == 1) { result = result.substring(0, result.length() - 1); } return result; } } zt-exec-zt-exec-1.11/src/main/java/org/zeroturnaround/exec/listener/000077500000000000000000000000001350762700300254705ustar00rootroot00000000000000zt-exec-zt-exec-1.11/src/main/java/org/zeroturnaround/exec/listener/CompositeProcessListener.java000066400000000000000000000055611350762700300333510ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec.listener; import java.util.Iterator; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import org.zeroturnaround.exec.ProcessExecutor; import org.zeroturnaround.exec.ProcessResult; /** * Composite process event handler. * * @author Rein Raudjärv */ public class CompositeProcessListener extends ProcessListener implements Cloneable { private final List children = new CopyOnWriteArrayList(); public CompositeProcessListener() { // no children } public CompositeProcessListener(List children) { this.children.addAll(children); } /** * Add new listener. * * @param listener listener to be added. */ public void add(ProcessListener listener) { children.add(listener); } /** * Remove existing listener. * * @param listener listener to be removed. */ public void remove(ProcessListener listener) { children.remove(listener); } /** * Remove existing listeners of given type or its sub-types. * * @param type listener type. */ public void removeAll(Class type) { for (Iterator it = children.iterator(); it.hasNext();) { if (type.isInstance(it.next())) it.remove(); } } /** * Remove all existing listeners. */ public void clear() { children.clear(); } public CompositeProcessListener clone() { return new CompositeProcessListener(children); } @Override public void beforeStart(ProcessExecutor executor) { for (ProcessListener child : children) { child.beforeStart(executor); } } @Override public void afterStart(Process process, ProcessExecutor executor) { for (ProcessListener child : children) { child.afterStart(process, executor); } } @Override public void afterFinish(Process process, ProcessResult result) { for (ProcessListener child : children) { child.afterFinish(process, result); } } @Override public void afterStop(Process process) { for (ProcessListener child : children) { child.afterStop(process); } } } zt-exec-zt-exec-1.11/src/main/java/org/zeroturnaround/exec/listener/DestroyerListenerAdapter.java000066400000000000000000000027111350762700300333230ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec.listener; import org.zeroturnaround.exec.ProcessExecutor; /** * Process event handler that wraps a process destroyer. * * @author Rein Raudjärv * * @see ProcessDestroyer */ public class DestroyerListenerAdapter extends ProcessListener { private final ProcessDestroyer destroyer; public DestroyerListenerAdapter(ProcessDestroyer destroyer) { if (destroyer == null) throw new IllegalArgumentException("Process destroyer must be provided."); this.destroyer = destroyer; } @Override public void afterStart(Process process, ProcessExecutor executor) { destroyer.add(process); } @Override public void afterStop(Process process) { destroyer.remove(process); } } zt-exec-zt-exec-1.11/src/main/java/org/zeroturnaround/exec/listener/ProcessDestroyer.java000066400000000000000000000054641350762700300316630ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * NOTICE: This file originates from the Apache Commons Exec package. * It has been modified to fit our needs. * * The following is the original header of the file in Apache Commons Exec: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec.listener; /** * Destroys all registered {@link java.lang.Process} after a certain event, * typically when the VM exits * @see ShutdownHookProcessDestroyer */ public interface ProcessDestroyer { /** * Returns true if the specified * {@link java.lang.Process} was * successfully added to the list of processes to be destroy. * * @param process * the process to add * @return true if the specified * {@link java.lang.Process} was * successfully added */ boolean add(Process process); /** * Returns true if the specified * {@link java.lang.Process} was * successfully removed from the list of processes to be destroy. * * @param process * the process to remove * @return true if the specified * {@link java.lang.Process} was * successfully removed */ boolean remove(Process process); /** * Returns the number of registered processes. * * @return the number of register process */ int size(); } zt-exec-zt-exec-1.11/src/main/java/org/zeroturnaround/exec/listener/ProcessListener.java000066400000000000000000000044641350762700300314670ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec.listener; import org.zeroturnaround.exec.ProcessExecutor; import org.zeroturnaround.exec.ProcessResult; /** * Event handler for process events. *

* This is a class instead of interface in order to add new methods without updating all implementations. * * @author Rein Raudjärv * @see ProcessExecutor#addListener(ProcessListener) */ public abstract class ProcessListener { /** * Invoked before a process is started. * * @param executor executor used for starting a process. * Any changes made here apply to the starting process. * Once the process has started it is not affected by the {@link ProcessExecutor} any more. */ public void beforeStart(ProcessExecutor executor) { // do nothing } /** * Invoked after a process has started. * * @param process the process started. * @param executor executor used for starting the process. * Modifying the {@link ProcessExecutor} only affects the following processes * not the one just started. */ public void afterStart(Process process, ProcessExecutor executor) { // do nothing } /** * Invoked after a process has finished successfully. * * @param process process just finished. * @param result result of the finished process. * @since 1.8 */ public void afterFinish(Process process, ProcessResult result) { // do nothing } /** * Invoked after a process has exited (whether finished or cancelled). * * @param process process just stopped. */ public void afterStop(Process process) { // do nothing } } ShutdownHookProcessDestroyer.java000066400000000000000000000176731350762700300341660ustar00rootroot00000000000000zt-exec-zt-exec-1.11/src/main/java/org/zeroturnaround/exec/listener/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * NOTICE: This file originates from the Apache Commons Exec package. * It has been modified to fit our needs. * * The following is the original header of the file in Apache Commons Exec: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec.listener; import java.util.Enumeration; import java.util.Vector; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Destroys all registered Processes when the VM exits. *

* This class is copied from Commons Exec. */ public class ShutdownHookProcessDestroyer implements ProcessDestroyer, Runnable { private static final Logger log = LoggerFactory.getLogger(ShutdownHookProcessDestroyer.class); /** * Singleton instance of the {@link ShutdownHookProcessDestroyer}. */ public static final ProcessDestroyer INSTANCE = new ShutdownHookProcessDestroyer(); /** the list of currently running processes */ private final Vector processes = new Vector(); /** The thread registered at the JVM to execute the shutdown handler */ private ProcessDestroyerImpl destroyProcessThread = null; /** Whether or not this ProcessDestroyer has been registered as a shutdown hook */ private boolean added = false; /** Whether the shut down hook routine was already run **/ private volatile boolean shutDownHookExecuted = false; /** * Whether or not this ProcessDestroyer is currently running as shutdown hook */ private volatile boolean running = false; private class ProcessDestroyerImpl extends Thread { private boolean shouldDestroy = true; public ProcessDestroyerImpl() { super("ProcessDestroyer Shutdown Hook"); } public void run() { if (shouldDestroy) { ShutdownHookProcessDestroyer.this.run(); } } public void setShouldDestroy(final boolean shouldDestroy) { this.shouldDestroy = shouldDestroy; } } /** * Constructs a ProcessDestroyer and obtains * Runtime.addShutdownHook() and * Runtime.removeShutdownHook() through reflection. The * ProcessDestroyer manages a list of processes to be destroyed when the VM * exits. If a process is added when the list is empty, this * ProcessDestroyer is registered as a shutdown hook. If * removing a process results in an empty list, the * ProcessDestroyer is removed as a shutdown hook. */ public ShutdownHookProcessDestroyer() { } /** * Registers this ProcessDestroyer as a shutdown hook, uses * reflection to ensure pre-JDK 1.3 compatibility. */ private void addShutdownHook() { if (!running) { destroyProcessThread = new ProcessDestroyerImpl(); Runtime.getRuntime().addShutdownHook(destroyProcessThread); added = true; } } /** * Removes this ProcessDestroyer as a shutdown hook, uses * reflection to ensure pre-JDK 1.3 compatibility */ private void removeShutdownHook() { if (added && !running) { boolean removed = Runtime.getRuntime().removeShutdownHook( destroyProcessThread); if (!removed) { log.error("Could not remove shutdown hook"); } /* * start the hook thread, a unstarted thread may not be eligible for * garbage collection Cf.: http://developer.java.sun.com/developer/ * bugParade/bugs/4533087.html */ destroyProcessThread.setShouldDestroy(false); destroyProcessThread.start(); // this should return quickly, since it basically is a NO-OP. try { destroyProcessThread.join(20000); } catch (InterruptedException ie) { // the thread didn't die in time // it should not kill any processes unexpectedly } destroyProcessThread = null; added = false; } } /** * Returns whether or not the ProcessDestroyer is registered as as shutdown * hook * * @return true if this is currently added as shutdown hook */ public boolean isAddedAsShutdownHook() { return added; } /** * Returns true if the specified Process was * successfully added to the list of processes to destroy upon VM exit. * * @param process * the process to add * @return true if the specified Process was * successfully added */ public boolean add(final Process process) { synchronized (processes) { // if this list is empty, register the shutdown hook if (processes.size() == 0) { try { if(shutDownHookExecuted) { throw new IllegalStateException(); } addShutdownHook(); } // kill the process now if the JVM is currently shutting down catch (IllegalStateException e) { destroy(process); } } processes.addElement(process); return processes.contains(process); } } /** * Returns true if the specified Process was * successfully removed from the list of processes to destroy upon VM exit. * * @param process * the process to remove * @return true if the specified Process was * successfully removed */ public boolean remove(final Process process) { synchronized (processes) { boolean processRemoved = processes.removeElement(process); if (processRemoved && processes.size() == 0) { try { removeShutdownHook(); } catch (IllegalStateException e) { /* if the JVM is shutting down, the hook cannot be removed */ shutDownHookExecuted = true; } } return processRemoved; } } /** * Returns the number of registered processes. * * @return the number of register process */ public int size() { return processes.size(); } /** * Invoked by the VM when it is exiting. */ public void run() { /* check if running the routine is still necessary */ if(shutDownHookExecuted) { return; } synchronized (processes) { running = true; Enumeration e = processes.elements(); while (e.hasMoreElements()) { destroy((Process) e.nextElement()); } processes.clear(); shutDownHookExecuted = true; } } private void destroy(Process process) { try { process.destroy(); } catch (Throwable t) { log.error("Unable to terminate process during process shutdown"); } } } zt-exec-zt-exec-1.11/src/main/java/org/zeroturnaround/exec/stop/000077500000000000000000000000001350762700300246305ustar00rootroot00000000000000zt-exec-zt-exec-1.11/src/main/java/org/zeroturnaround/exec/stop/DestroyProcessStopper.java000066400000000000000000000022151350762700300320400ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec.stop; /** * Default {@link ProcessStopper} implementation that just invokes {@link Process#destroy()}. */ public class DestroyProcessStopper implements ProcessStopper { /** * Singleton instance of the {@link DestroyProcessStopper}. */ public static final ProcessStopper INSTANCE = new DestroyProcessStopper(); public void stop(Process process) { process.destroy(); } } zt-exec-zt-exec-1.11/src/main/java/org/zeroturnaround/exec/stop/NopProcessStopper.java000066400000000000000000000022051350762700300311420ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec.stop; /** * {@link ProcessStopper} implementation that does nothing - it keeps the process running. */ public class NopProcessStopper implements ProcessStopper { /** * Singleton instance of the {@link NopProcessStopper}. */ public static final ProcessStopper INSTANCE = new NopProcessStopper(); public void stop(Process process) { // don't stop the process } } zt-exec-zt-exec-1.11/src/main/java/org/zeroturnaround/exec/stop/ProcessStopper.java000066400000000000000000000024151350762700300304700ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec.stop; import java.util.concurrent.Future; /** * Abstraction for stopping sub processes. *

* This is used in case a process runs too long (timeout is reached) or it's cancelled via {@link Future#cancel(boolean)}. */ public interface ProcessStopper { /** * Stops a given sub process. * It does not wait for the process to actually stop and it has no guarantee that the process terminates. * * @param process sub process being stopped (not null). */ void stop(Process process); } zt-exec-zt-exec-1.11/src/main/java/org/zeroturnaround/exec/stream/000077500000000000000000000000001350762700300251365ustar00rootroot00000000000000zt-exec-zt-exec-1.11/src/main/java/org/zeroturnaround/exec/stream/CallerLoggerUtil.java000066400000000000000000000045331350762700300312060ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec.stream; /** * Constructs name for the caller logger. * * @author Rein Raudjärv */ public abstract class CallerLoggerUtil { /** * Returns full name for the caller class' logger. * * @param name name of the logger. In case of full name (it contains dots) same value is just returned. * In case of short names (no dots) the given name is prefixed by caller's class name and a dot. * In case of null the caller's class name is just returned. * @return full name for the caller class' logger. */ public static String getName(String name) { return getName(name, 1); } /** * Returns full name for the caller class' logger. * * @param name name of the logger. In case of full name (it contains dots) same value is just returned. * In case of short names (no dots) the given name is prefixed by caller's class name and a dot. * In case of null the caller's class name is just returned. * @param level no of call stack levels to get the caller (0 means the caller of this method). * @return full name for the caller class' logger. */ public static String getName(String name, int level) { level++; String fullName; if (name == null) fullName = getCallerClassName(level); else if (name.contains(".")) fullName = name; else fullName = getCallerClassName(level) + "." + name; return fullName; } /** * @return caller class name of the given level. */ private static String getCallerClassName(int level) { return Thread.currentThread().getStackTrace()[level + 2].getClassName(); } } zt-exec-zt-exec-1.11/src/main/java/org/zeroturnaround/exec/stream/ExecuteStreamHandler.java000066400000000000000000000064421350762700300320630ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * NOTICE: This file originates from the Apache Commons Exec package. * It has been modified to fit our needs. * * The following is the original header of the file in Apache Commons Exec: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec.stream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; /** * Used by Execute to handle input and output stream of * subprocesses. */ public interface ExecuteStreamHandler { /** * Install a handler for the input stream of the subprocess. * * @param os * output stream to write to the standard input stream of the * subprocess * @throws IOException throws a IO exception in case of IO issues of the underlying stream */ void setProcessInputStream(OutputStream os) throws IOException; /** * Install a handler for the error stream of the subprocess. * * @param is * input stream to read from the error stream from the subprocess * @throws IOException throws a IO exception in case of IO issues of the underlying stream */ void setProcessErrorStream(InputStream is) throws IOException; /** * Install a handler for the output stream of the subprocess. * * @param is * input stream to read from the error stream from the subprocess * @throws IOException throws a IO exception in case of IO issues of the underlying stream */ void setProcessOutputStream(InputStream is) throws IOException; /** * Start handling of the streams. * * @throws IOException throws a IO exception in case of IO issues of the underlying stream */ void start() throws IOException; /** * Stop handling of the streams - will not be restarted. * Will wait for pump threads to complete. */ void stop(); } zt-exec-zt-exec-1.11/src/main/java/org/zeroturnaround/exec/stream/InputStreamPumper.java000066400000000000000000000062711350762700300314530ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * NOTICE: This file originates from the Apache Commons Exec package. * It has been modified to fit our needs. * * The following is the original header of the file in Apache Commons Exec: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec.stream; import java.io.InputStream; import java.io.OutputStream; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Copies all data from an System.input stream to an output stream of the executed process. * * @author mkleint */ public class InputStreamPumper implements Runnable { private static final Logger log = LoggerFactory.getLogger(InputStreamPumper.class); public static final int SLEEPING_TIME = 100; /** the input stream to pump from */ private final InputStream is; /** the output stream to pmp into */ private final OutputStream os; /** flag to stop the stream pumping */ private volatile boolean stop; /** * Create a new stream pumper. * * @param is input stream to read data from * @param os output stream to write data to. */ public InputStreamPumper(final InputStream is, final OutputStream os) { this.is = is; this.os = os; this.stop = false; } /** * Copies data from the input stream to the output stream. Terminates as * soon as the input stream is closed or an error occurs. */ public void run() { try { while (!stop) { while (is.available() > 0 && !stop) { os.write(is.read()); } os.flush(); Thread.sleep(SLEEPING_TIME); } } catch (Exception e) { log.error("Got exception while reading/writing the stream", e); } } public void stopProcessing() { stop = true; } } zt-exec-zt-exec-1.11/src/main/java/org/zeroturnaround/exec/stream/LogOutputStream.java000066400000000000000000000100031350762700300311110ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec.stream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; /** * Base class to connect a logging system to the output and/or * error stream of then external process. The implementation * parses the incoming data to construct a line and passes * the complete line to an user-defined implementation. */ public abstract class LogOutputStream extends OutputStream { /** Initial buffer size. */ private static final int INTIAL_SIZE = 132; /** Carriage return */ private static final int CR = 0x0d; /** Linefeed */ private static final int LF = 0x0a; /** the internal buffer */ private final ByteArrayOutputStream buffer = new ByteArrayOutputStream( INTIAL_SIZE); byte lastReceivedByte; /** * Write the data to the buffer and flush the buffer, if a line separator is * detected. * * @param cc data to log (byte). * @see java.io.OutputStream#write(int) */ public void write(final int cc) throws IOException { final byte c = (byte) cc; if ((c == '\n') || (c == '\r')) { // new line is started in case of // - CR (regardless of previous character) // - LF if previous character was not CR and not LF if (c == '\r' || (c == '\n' && (lastReceivedByte != '\r' && lastReceivedByte != '\n'))) { processBuffer(); } } else { buffer.write(cc); } lastReceivedByte = c; } /** * Flush this log stream. * * @see java.io.OutputStream#flush() */ public void flush() { if (buffer.size() > 0) { processBuffer(); } } /** * Writes all remaining data from the buffer. * * @see java.io.OutputStream#close() */ public void close() throws IOException { if (buffer.size() > 0) { processBuffer(); } super.close(); } /** * Write a block of characters to the output stream * * @param b the array containing the data * @param off the offset into the array where data starts * @param len the length of block * @throws java.io.IOException if the data cannot be written into the stream. * @see java.io.OutputStream#write(byte[], int, int) */ public void write(final byte[] b, final int off, final int len) throws IOException { // find the line breaks and pass other chars through in blocks int offset = off; int blockStartOffset = offset; int remaining = len; while (remaining > 0) { while (remaining > 0 && b[offset] != LF && b[offset] != CR) { offset++; remaining--; } // either end of buffer or a line separator char int blockLength = offset - blockStartOffset; if (blockLength > 0) { buffer.write(b, blockStartOffset, blockLength); lastReceivedByte = 0; } while (remaining > 0 && (b[offset] == LF || b[offset] == CR)) { write(b[offset]); offset++; remaining--; } blockStartOffset = offset; } } /** * Converts the buffer to a string and sends it to processLine. */ protected void processBuffer() { processLine(buffer.toString()); buffer.reset(); } /** * Logs a line to the log system of the user. * * @param line * the line to log. */ protected abstract void processLine(String line); } zt-exec-zt-exec-1.11/src/main/java/org/zeroturnaround/exec/stream/NullOutputStream.java000066400000000000000000000022541350762700300313130ustar00rootroot00000000000000/* * Copyright (C) 2019 Ketan Padegaonkar * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec.stream; import java.io.IOException; import java.io.OutputStream; /** * An OutputStream which ignores everything written to it. */ public class NullOutputStream extends OutputStream { /** * A singleton. */ public static final NullOutputStream NULL_OUTPUT_STREAM = new NullOutputStream(); public void write(byte[] b, int off, int len) { // discard! } public void write(int b) { // discard! } public void write(byte[] b) throws IOException { // discard! } } zt-exec-zt-exec-1.11/src/main/java/org/zeroturnaround/exec/stream/PumpStreamHandler.java000066400000000000000000000243311350762700300313770ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * NOTICE: This file originates from the Apache Commons Exec package. * It has been modified to fit our needs. * * The following is the original header of the file in Apache Commons Exec: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec.stream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.MDC; import org.zeroturnaround.exec.MDCRunnableAdapter; /** * Copies standard output and error of subprocesses to standard output and error * of the parent process. If output or error stream are set to null, any feedback * from that stream will be lost. */ public class PumpStreamHandler implements ExecuteStreamHandler { private static final Logger log = LoggerFactory.getLogger(PumpStreamHandler.class); protected Thread outputThread; protected Thread errorThread; protected Thread inputThread; protected final OutputStream out; protected final OutputStream err; protected final InputStream input; protected InputStreamPumper inputStreamPumper; /** * Construct a new PumpStreamHandler. */ public PumpStreamHandler() { this(System.out, System.err); } /** * Construct a new PumpStreamHandler. * * @param outAndErr * the output/error OutputStream. */ public PumpStreamHandler(OutputStream outAndErr) { this(outAndErr, outAndErr); } /** * Construct a new PumpStreamHandler. * * @param out * the output OutputStream. * @param err * the error OutputStream. */ public PumpStreamHandler(OutputStream out, OutputStream err) { this(out, err, null); } /** * Construct a new PumpStreamHandler. * * @param out * the output OutputStream. * @param err * the error OutputStream. * @param input * the input InputStream. */ public PumpStreamHandler(OutputStream out, OutputStream err, InputStream input) { this.out = out; this.err = err; this.input = input; } /** * Set the InputStream from which to read the standard output * of the process. * * @param is * the InputStream. */ public void setProcessOutputStream(InputStream is) { if (out != null) { createProcessOutputPump(is, out); } } /** * Set the InputStream from which to read the standard error * of the process. * * @param is * the InputStream. */ public void setProcessErrorStream(InputStream is) { if (err != null) { createProcessErrorPump(is, err); } } /** * Set the OutputStream by means of which input can be sent * to the process. * * @param os * the OutputStream. */ public void setProcessInputStream(OutputStream os) { if (input != null) { if (input == System.in) { inputThread = createSystemInPump(input, os); } else { inputThread = createPump(input, os, true, true); } } else { try { os.close(); } catch (IOException e) { log.info("Got exception while closing output stream", e); } } } /** * Start the Threads. */ public void start() { if (outputThread != null) { outputThread.start(); } if (errorThread != null) { errorThread.start(); } if (inputThread != null) { inputThread.start(); } } /** * Stop pumping the streams. */ public void stop() { if (inputThread != null) { if (inputStreamPumper != null) { inputStreamPumper.stopProcessing(); } // #33 Interrupt reading from a PipedInputStream to unblock the pumping thread inputThread.interrupt(); log.trace("Joining input thread {}...", inputThread); try { inputThread.join(); inputThread = null; } catch (InterruptedException e) { // ignore } } if (outputThread != null) { log.trace("Joining output thread {}...", outputThread); try { outputThread.join(); outputThread = null; } catch (InterruptedException e) { // ignore } } if (errorThread != null) { log.trace("Joining error thread {}...", errorThread); try { errorThread.join(); errorThread = null; } catch (InterruptedException e) { // ignore } } flush(); } public void flush() { if (out != null) { log.trace("Flushing output stream {}...", out); try { out.flush(); } catch (IOException e) { log.error("Got exception while flushing the output stream", e); } } if (err != null && err != out) { log.trace("Flushing error stream {}...", err); try { err.flush(); } catch (IOException e) { log.error("Got exception while flushing the error stream", e); } } } /** * Get the output stream. * * @return OutputStream. */ public OutputStream getOut() { return out; } /** * Get the error stream. * * @return OutputStream. */ public OutputStream getErr() { return err; } /** * Get the input stream. * * @return InputStream. */ public InputStream getInput() { return input; } /** * Create the pump to handle process output. * * @param is * the InputStream. * @param os * the OutputStream. */ protected void createProcessOutputPump(InputStream is, OutputStream os) { outputThread = createPump(is, os); } /** * Create the pump to handle error output. * * @param is * the InputStream. * @param os * the OutputStream. */ protected void createProcessErrorPump(InputStream is, OutputStream os) { errorThread = createPump(is, os); } /** * Creates a stream pumper to copy the given input stream to the given * output stream. * * @param is the input stream to copy from * @param os the output stream to copy into * @return the stream pumper thread */ protected Thread createPump(InputStream is, OutputStream os) { return createPump(is, os, false, false); } /** * Creates a stream pumper to copy the given input stream to the given * output stream. * * @param is the input stream to copy from * @param os the output stream to copy into * @param closeWhenExhausted close the output stream when the input stream is exhausted * @return the stream pumper thread */ protected Thread createPump(InputStream is, OutputStream os, boolean closeWhenExhausted) { return createPump(is, os, closeWhenExhausted, false); } /** * Creates a stream pumper to copy the given input stream to the given * output stream. * * @param is the input stream to copy from * @param os the output stream to copy into * @param closeWhenExhausted close the output stream when the input stream is exhausted * @param flushImmediately flush the output stream whenever data was written to it * @return the stream pumper thread */ protected Thread createPump(InputStream is, OutputStream os, boolean closeWhenExhausted, boolean flushImmediately) { return newThread(new StreamPumper(is, os, closeWhenExhausted, flushImmediately)); } /** * Creates a stream pumper to copy the given input stream to the given * output stream. * * @param is the System.in input stream to copy from * @param os the output stream to copy into * @return the stream pumper thread */ protected Thread createSystemInPump(InputStream is, OutputStream os) { inputStreamPumper = new InputStreamPumper(is, os); return newThread(inputStreamPumper); } /** * Override this to customize how the background task is created. * * @param task the task to be run in the background * @return the thread of the task */ protected Thread newThread(Runnable task) { Thread result = new Thread(wrapTask(task)); result.setDaemon(true); return result; } /** * Override this to customize how the background task is created. * * @param task the task to be run in the background * @return the runnable of the wrapped task */ protected Runnable wrapTask(Runnable task) { // Preserve the MDC context of the caller thread. Map contextMap = MDC.getCopyOfContextMap(); if (contextMap != null) { return new MDCRunnableAdapter(task, contextMap); } return task; } } zt-exec-zt-exec-1.11/src/main/java/org/zeroturnaround/exec/stream/StreamPumper.java000066400000000000000000000154751350762700300304410ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * NOTICE: This file originates from the Apache Commons Exec package. * It has been modified to fit our needs. * * The following is the original header of the file in Apache Commons Exec: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec.stream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Copies all data from an input stream to an output stream. */ public class StreamPumper implements Runnable { private static final Logger log = LoggerFactory.getLogger(StreamPumper.class); /** the default size of the internal buffer for copying the streams */ private static final int DEFAULT_SIZE = 1024; /** the input stream to pump from */ private final InputStream is; /** the output stream to pmp into */ private final OutputStream os; /** the size of the internal buffer for copying the streams */ private final int size; /** was the end of the stream reached */ private boolean finished; /** close the output stream when exhausted */ private final boolean closeWhenExhausted; /** flush the output stream after each write */ private final boolean flushImmediately; /** * Create a new stream pumper. * * @param is input stream to read data from * @param os output stream to write data to. * @param closeWhenExhausted if true, the output stream will be closed when the input is exhausted. * @param flushImmediately flush the output stream whenever data was written to it */ public StreamPumper(final InputStream is, final OutputStream os, final boolean closeWhenExhausted, boolean flushImmediately) { this.is = is; this.os = os; this.size = DEFAULT_SIZE; this.closeWhenExhausted = closeWhenExhausted; this.flushImmediately = flushImmediately; } /** * Create a new stream pumper. * * @param is input stream to read data from * @param os output stream to write data to. * @param closeWhenExhausted if true, the output stream will be closed when the input is exhausted. * @param size the size of the internal buffer for copying the streams * @param flushImmediately flush the output stream whenever data was written to it */ public StreamPumper(final InputStream is, final OutputStream os, final boolean closeWhenExhausted, final int size, boolean flushImmediately) { this.is = is; this.os = os; this.size = (size > 0 ? size : DEFAULT_SIZE); this.closeWhenExhausted = closeWhenExhausted; this.flushImmediately = flushImmediately; } /** * Create a new stream pumper. * * @param is input stream to read data from * @param os output stream to write data to. * @param closeWhenExhausted if true, the output stream will be closed when the input is exhausted. */ public StreamPumper(final InputStream is, final OutputStream os, final boolean closeWhenExhausted) { this.is = is; this.os = os; this.size = DEFAULT_SIZE; this.closeWhenExhausted = closeWhenExhausted; this.flushImmediately = false; } /** * Create a new stream pumper. * * @param is input stream to read data from * @param os output stream to write data to. * @param closeWhenExhausted if true, the output stream will be closed when the input is exhausted. * @param size the size of the internal buffer for copying the streams */ public StreamPumper(final InputStream is, final OutputStream os, final boolean closeWhenExhausted, final int size) { this.is = is; this.os = os; this.size = (size > 0 ? size : DEFAULT_SIZE); this.closeWhenExhausted = closeWhenExhausted; this.flushImmediately = false; } /** * Create a new stream pumper. * * @param is input stream to read data from * @param os output stream to write data to. */ public StreamPumper(final InputStream is, final OutputStream os) { this(is, os, false); } /** * Copies data from the input stream to the output stream. Terminates as * soon as the input stream is closed or an error occurs. */ public void run() { log.trace("{} started.", this); synchronized (this) { // Just in case this object is reused in the future finished = false; } final byte[] buf = new byte[this.size]; int length; try { while ((length = is.read(buf)) > 0) { os.write(buf, 0, length); if(flushImmediately) { os.flush(); } } } catch (Exception e) { // nothing to do - happens quite often with watchdog } finally { log.trace("{} finished.", this); if (closeWhenExhausted) { try { os.close(); } catch (IOException e) { log.error("Got exception while closing exhausted output stream", e); } } synchronized (this) { finished = true; notifyAll(); } } } /** * Tells whether the end of the stream has been reached. * * @return true is the stream has been exhausted. */ public synchronized boolean isFinished() { return finished; } /** * This method blocks until the stream pumper finishes. * * @see #isFinished() * @throws InterruptedException throws when the waiting is interrupted */ public synchronized void waitFor() throws InterruptedException { while (!isFinished()) { wait(); } } } zt-exec-zt-exec-1.11/src/main/java/org/zeroturnaround/exec/stream/TeeOutputStream.java000066400000000000000000000046641350762700300311250ustar00rootroot00000000000000/* * Copyright (C) 2019 Ketan Padegaonkar * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec.stream; import java.io.IOException; import java.io.OutputStream; /** * Splits an OutputStream into two. Named after the unix 'tee' * command. It allows a stream to be branched off so there * are now two streams. */ public class TeeOutputStream extends OutputStream { private final OutputStream left; private final OutputStream right; public TeeOutputStream(OutputStream left, OutputStream right) { this.left = left; this.right = right; } /** * Write a byte array to both output streams. * * @param b the data. * @param off the start offset in the data. * @param len the number of bytes to write. * @throws IOException on error. */ public void write(byte[] b, int off, int len) throws IOException { left.write(b, off, len); right.write(b, off, len); } /** * Write a byte to both output streams. * * @param b the byte to write. * @throws IOException on error. */ public void write(int b) throws IOException { left.write(b); right.write(b); } /** * Write a byte array to both output streams. * * @param b an array of bytes. * @throws IOException on error. */ public void write(byte[] b) throws IOException { left.write(b); right.write(b); } /** * Closes both output streams * * @throws IOException on error. */ @Override public void close() throws IOException { try { left.close(); } finally { right.close(); } } /** * Flush both output streams. * * @throws IOException on error */ @Override public void flush() throws IOException { left.flush(); right.flush(); } } zt-exec-zt-exec-1.11/src/main/java/org/zeroturnaround/exec/stream/slf4j/000077500000000000000000000000001350762700300261605ustar00rootroot00000000000000zt-exec-zt-exec-1.11/src/main/java/org/zeroturnaround/exec/stream/slf4j/Level.java000066400000000000000000000002211350762700300300650ustar00rootroot00000000000000package org.zeroturnaround.exec.stream.slf4j; /** * Slf4j logging level. */ public enum Level { TRACE, DEBUG, INFO, WARN, ERROR } zt-exec-zt-exec-1.11/src/main/java/org/zeroturnaround/exec/stream/slf4j/Slf4jDebugOutputStream.java000066400000000000000000000022121350762700300333460ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec.stream.slf4j; import org.slf4j.Logger; /** * Output stream that writes debug level messages to a given {@link Logger}. * * @author Rein Raudjärv */ public class Slf4jDebugOutputStream extends Slf4jOutputStream { public Slf4jDebugOutputStream(Logger logger) { super(logger); } @Override protected void processLine(String line) { log.debug(line); } } zt-exec-zt-exec-1.11/src/main/java/org/zeroturnaround/exec/stream/slf4j/Slf4jErrorOutputStream.java000066400000000000000000000022121350762700300334110ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec.stream.slf4j; import org.slf4j.Logger; /** * Output stream that writes error level messages to a given {@link Logger}. * * @author Rein Raudjärv */ public class Slf4jErrorOutputStream extends Slf4jOutputStream { public Slf4jErrorOutputStream(Logger logger) { super(logger); } @Override protected void processLine(String line) { log.error(line); } } zt-exec-zt-exec-1.11/src/main/java/org/zeroturnaround/exec/stream/slf4j/Slf4jInfoOutputStream.java000066400000000000000000000022061350762700300332160ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec.stream.slf4j; import org.slf4j.Logger; /** * Output stream that writes info level messages to a given {@link Logger}. * * @author Rein Raudjärv */ public class Slf4jInfoOutputStream extends Slf4jOutputStream { public Slf4jInfoOutputStream(Logger logger) { super(logger); } @Override protected void processLine(String line) { log.info(line); } } zt-exec-zt-exec-1.11/src/main/java/org/zeroturnaround/exec/stream/slf4j/Slf4jOutputStream.java000066400000000000000000000022401350762700300324000ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec.stream.slf4j; import org.slf4j.Logger; import org.zeroturnaround.exec.stream.LogOutputStream; /** * Output stream that writes to a given {@link Logger}. * * @author Rein Raudjärv */ public abstract class Slf4jOutputStream extends LogOutputStream { protected final Logger log; public Slf4jOutputStream(Logger logger) { this.log = logger; } public Logger getLogger() { return log; } } zt-exec-zt-exec-1.11/src/main/java/org/zeroturnaround/exec/stream/slf4j/Slf4jStream.java000066400000000000000000000076101350762700300311650ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec.stream.slf4j; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.zeroturnaround.exec.stream.CallerLoggerUtil; /** * Creates output streams that write to {@link Logger}s. * * @author Rein Raudjärv */ public class Slf4jStream { private final Logger log; private Slf4jStream(Logger log) { this.log = log; } /** * @param log logger which an output stream redirects to. * @return Slf4jStream with the given logger. */ public static Slf4jStream of(Logger log) { return new Slf4jStream(log); } /** * @param klass class which is used to get the logger's name. * @return Slf4jStream with a logger named after the given class. */ public static Slf4jStream of(Class klass) { return of(LoggerFactory.getLogger(klass)); } /** * Constructs a logger from a class name and an additional name, * appended to the end. So the final logger name will be: *

klass.getName() + "." + name
* * @param klass class which is used to get the logger's name. * @param name logger's name, appended to the class name. * @return Slf4jStream with a logger named after the given class. * * @since 1.8 */ public static Slf4jStream of(Class klass, String name) { if (name == null) { return of(klass); } else { return of(LoggerFactory.getLogger(klass.getName() + "." + name)); } } /** * @param name logger's name (full or short). * In case of short name (no dots) the given name is prefixed by caller's class name and a dot. * @return Slf4jStream with the given logger. */ public static Slf4jStream of(String name) { return of(LoggerFactory.getLogger(CallerLoggerUtil.getName(name, 1))); } /** * @return Slf4jStream with the logger of caller of this method. */ public static Slf4jStream ofCaller() { return of(LoggerFactory.getLogger(CallerLoggerUtil.getName(null, 1))); } /** * @param level the desired logging level * @return output stream that writes with a given level. */ public Slf4jOutputStream as(Level level) { switch (level) { case TRACE: return asTrace(); case DEBUG: return asDebug(); case INFO: return asInfo(); case WARN: return asWarn(); case ERROR: return asError(); } throw new IllegalArgumentException("Invalid level " + level); } /** * @return output stream that writes trace level. */ public Slf4jOutputStream asTrace() { return new Slf4jTraceOutputStream(log); } /** * @return output stream that writes debug level. */ public Slf4jOutputStream asDebug() { return new Slf4jDebugOutputStream(log); } /** * @return output stream that writes info level. */ public Slf4jOutputStream asInfo() { return new Slf4jInfoOutputStream(log); } /** * @return output stream that writes warn level. */ public Slf4jOutputStream asWarn() { return new Slf4jWarnOutputStream(log); } /** * @return output stream that writes error level. */ public Slf4jOutputStream asError() { return new Slf4jErrorOutputStream(log); } } zt-exec-zt-exec-1.11/src/main/java/org/zeroturnaround/exec/stream/slf4j/Slf4jTraceOutputStream.java000066400000000000000000000022121350762700300333560ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec.stream.slf4j; import org.slf4j.Logger; /** * Output stream that writes trace level messages to a given {@link Logger}. * * @author Rein Raudjärv */ public class Slf4jTraceOutputStream extends Slf4jOutputStream { public Slf4jTraceOutputStream(Logger logger) { super(logger); } @Override protected void processLine(String line) { log.trace(line); } } zt-exec-zt-exec-1.11/src/main/java/org/zeroturnaround/exec/stream/slf4j/Slf4jWarnOutputStream.java000066400000000000000000000022061350762700300332320ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec.stream.slf4j; import org.slf4j.Logger; /** * Output stream that writes warn level messages to a given {@link Logger}. * * @author Rein Raudjärv */ public class Slf4jWarnOutputStream extends Slf4jOutputStream { public Slf4jWarnOutputStream(Logger logger) { super(logger); } @Override protected void processLine(String line) { log.warn(line); } } zt-exec-zt-exec-1.11/src/test/000077500000000000000000000000001350762700300161415ustar00rootroot00000000000000zt-exec-zt-exec-1.11/src/test/java/000077500000000000000000000000001350762700300170625ustar00rootroot00000000000000zt-exec-zt-exec-1.11/src/test/java/org/000077500000000000000000000000001350762700300176515ustar00rootroot00000000000000zt-exec-zt-exec-1.11/src/test/java/org/zeroturnaround/000077500000000000000000000000001350762700300227525ustar00rootroot00000000000000zt-exec-zt-exec-1.11/src/test/java/org/zeroturnaround/exec/000077500000000000000000000000001350762700300236765ustar00rootroot00000000000000zt-exec-zt-exec-1.11/src/test/java/org/zeroturnaround/exec/ProcessOutputTest.java000066400000000000000000000031471350762700300302450ustar00rootroot00000000000000package org.zeroturnaround.exec; import java.util.Arrays; import org.junit.Assert; import org.junit.Test; public class ProcessOutputTest { @Test(expected = NullPointerException.class) public void testNull() { ProcessOutput.getLinesFrom(null); } @Test public void testSimple() { Assert.assertEquals(Arrays.asList("foo"), ProcessOutput.getLinesFrom("foo")); } @Test public void testNewLine() { Assert.assertEquals(Arrays.asList("foo", "bar"), ProcessOutput.getLinesFrom("foo\nbar")); } @Test public void testNewLineWithMultipleLines() { Assert.assertEquals(Arrays.asList("foo1", "bar1", "foo2", "bar2"), ProcessOutput.getLinesFrom("foo1\nbar1\nfoo2\nbar2")); } @Test public void testCarriageReturn() { Assert.assertEquals(Arrays.asList("foo", "bar"), ProcessOutput.getLinesFrom("foo\rbar")); } @Test public void testCarriageReturnWithMultipleLines() { Assert.assertEquals(Arrays.asList("foo1", "bar1", "foo2", "bar2"), ProcessOutput.getLinesFrom("foo1\rbar1\rfoo2\rbar2")); } @Test public void testCarriageReturnAndNewLine() { Assert.assertEquals(Arrays.asList("foo", "bar"), ProcessOutput.getLinesFrom("foo\r\nbar")); } @Test public void testCarriageReturnAndNewLineWithMultipleLines() { Assert.assertEquals(Arrays.asList("foo1", "bar1", "foo2", "bar2"), ProcessOutput.getLinesFrom("foo1\r\nbar1\r\nfoo2\r\nbar2")); } @Test public void testTwoNewLines() { Assert.assertEquals(Arrays.asList("foo", "bar"), ProcessOutput.getLinesFrom("foo\n\nbar")); } @Test public void testNewLineAtTheEnd() { Assert.assertEquals(Arrays.asList("foo"), ProcessOutput.getLinesFrom("foo\n")); } } zt-exec-zt-exec-1.11/src/test/java/org/zeroturnaround/exec/ReadmeExamples.java000066400000000000000000000106361350762700300274430ustar00rootroot00000000000000package org.zeroturnaround.exec; import java.io.OutputStream; import java.util.Map; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import org.slf4j.LoggerFactory; import org.zeroturnaround.exec.stream.LogOutputStream; import org.zeroturnaround.exec.stream.slf4j.Slf4jStream; /** * Examples of the readme. */ class ReadmeExamples { void justExecute() throws Exception { new ProcessExecutor().command("java", "-version").execute(); } int getExitCode() throws Exception { int exit = new ProcessExecutor().command("java", "-version") .execute().getExitValue(); return exit; } String getOutput() throws Exception { String output = new ProcessExecutor().command("java", "-version") .readOutput(true).execute() .outputUTF8(); return output; } void pumpOutputToLogger() throws Exception { new ProcessExecutor().command("java", "-version") .redirectOutput(Slf4jStream.of(LoggerFactory.getLogger(getClass().getName() + ".MyProcess")).asInfo()).execute(); } void pumpOutputToLoggerShorter() throws Exception { new ProcessExecutor().command("java", "-version") .redirectOutput(Slf4jStream.of("MyProcess").asInfo()).execute(); } void pumpOutputToLoggerOfCaller() throws Exception { new ProcessExecutor().command("java", "-version") .redirectOutput(Slf4jStream.ofCaller().asInfo()).execute(); } String pumpOutputToLoggerAndGetOutput() throws Exception { String output = new ProcessExecutor().command("java", "-version") .redirectOutput(Slf4jStream.of(getClass()).asInfo()) .readOutput(true).execute().outputUTF8(); return output; } String pumpErrorToLoggerAndGetOutput() throws Exception { String output = new ProcessExecutor().command("java", "-version") .redirectError(Slf4jStream.of(getClass()).asInfo()) .readOutput(true).execute() .outputUTF8(); return output; } void executeWithTimeout() throws Exception { try { new ProcessExecutor().command("java", "-version") .timeout(60, TimeUnit.SECONDS).execute(); } catch (TimeoutException e) { // process is automatically destroyed } } void pumpOutputToStream(OutputStream out) throws Exception { new ProcessExecutor().command("java", "-version") .redirectOutput(out).execute(); } void pumpOutputToLogStream(OutputStream out) throws Exception { new ProcessExecutor().command("java", "-version") .redirectOutput(new LogOutputStream() { @Override protected void processLine(String line) { // ... } }) .execute(); } void destroyProcessOnJvmExit() throws Exception { new ProcessExecutor().command("java", "-version").destroyOnExit().execute(); } void executeWithEnvironmentVariable() throws Exception { new ProcessExecutor().command("java", "-version") .environment("foo", "bar") .execute(); } void executeWithEnvironment(Map env) throws Exception { new ProcessExecutor().command("java", "-version") .environment(env) .execute(); } void checkExitCode() throws Exception { try { new ProcessExecutor().command("java", "-version") .exitValues(3).execute(); } catch (InvalidExitValueException e) { System.out.println("Process exited with " + e.getExitValue()); } } void checkExitCodeAndGetOutput() throws Exception { String output; boolean success = false; try { output = new ProcessExecutor().command("java", "-version") .readOutput(true).exitValues(3) .execute().outputUTF8(); success = true; } catch (InvalidExitValueException e) { System.out.println("Process exited with " + e.getExitValue()); output = e.getResult().outputUTF8(); } } void startInBackground() throws Exception { Future future = new ProcessExecutor() .command("java", "-version") .start().getFuture(); //do some stuff future.get(60, TimeUnit.SECONDS); } String startInBackgroundAndGetOutput() throws Exception { Future future = new ProcessExecutor() .command("java", "-version") .readOutput(true) .start().getFuture(); //do some stuff String output = future.get(60, TimeUnit.SECONDS).outputUTF8(); return output; } } zt-exec-zt-exec-1.11/src/test/java/org/zeroturnaround/exec/stream/000077500000000000000000000000001350762700300251715ustar00rootroot00000000000000zt-exec-zt-exec-1.11/src/test/java/org/zeroturnaround/exec/stream/TeeOutputStreamTest.java000066400000000000000000000060201350762700300320040ustar00rootroot00000000000000/* * Copyright (C) 2019 Ketan Padegaonkar * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec.stream; import org.junit.Assert; import org.junit.Test; import org.zeroturnaround.exec.test.RememberCloseOutputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; public class TeeOutputStreamTest { public static class ExceptionOnCloseByteArrayOutputStream extends RememberCloseOutputStream { public ExceptionOnCloseByteArrayOutputStream(OutputStream out) { super(out); } @Override public void close() throws IOException { super.close(); throw new IOException(); } } @Test public void shouldCopyContentsToBothStreams() throws IOException { ByteArrayOutputStream left = new ByteArrayOutputStream(); ByteArrayOutputStream right = new ByteArrayOutputStream(); TeeOutputStream teeOutputStream = new TeeOutputStream(left, right); teeOutputStream.write(10); teeOutputStream.write(new byte[]{1, 2, 3}); teeOutputStream.write(new byte[]{10, 11, 12, 13, 14, 15, 15, 16}, 2, 3); Assert.assertArrayEquals(new byte[]{10, 1, 2, 3, 12, 13, 14}, left.toByteArray()); Assert.assertArrayEquals(new byte[]{10, 1, 2, 3, 12, 13, 14}, right.toByteArray()); } @Test public void shouldCloseBothStreamsWhenClosingTee() throws IOException { RememberCloseOutputStream left = new RememberCloseOutputStream(NullOutputStream.NULL_OUTPUT_STREAM); RememberCloseOutputStream right = new RememberCloseOutputStream(NullOutputStream.NULL_OUTPUT_STREAM); TeeOutputStream teeOutputStream = new TeeOutputStream(left, right); teeOutputStream.close(); Assert.assertTrue(left.isClosed()); Assert.assertTrue(right.isClosed()); } @Test public void shouldCloseSecondStreamWhenClosingFirstFails() { ExceptionOnCloseByteArrayOutputStream left = new ExceptionOnCloseByteArrayOutputStream(NullOutputStream.NULL_OUTPUT_STREAM); RememberCloseOutputStream right = new RememberCloseOutputStream(NullOutputStream.NULL_OUTPUT_STREAM); TeeOutputStream teeOutputStream = new TeeOutputStream(left, right); try { teeOutputStream.close(); Assert.fail("Was expecting an exception!"); } catch (IOException expected) { } Assert.assertTrue(left.isClosed()); Assert.assertTrue(right.isClosed()); } } zt-exec-zt-exec-1.11/src/test/java/org/zeroturnaround/exec/test/000077500000000000000000000000001350762700300246555ustar00rootroot00000000000000zt-exec-zt-exec-1.11/src/test/java/org/zeroturnaround/exec/test/ArgumentsAsList.java000066400000000000000000000016421350762700300306100ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec.test; import java.util.Arrays; public class ArgumentsAsList { public static void main(String[] args) { System.out.print(Arrays.asList(args)); } } zt-exec-zt-exec-1.11/src/test/java/org/zeroturnaround/exec/test/BigOutput.java000066400000000000000000000017521350762700300274470ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec.test; public class BigOutput { public static final int LENGTH = 100000; public static void main(String[] args) { for (int i = 0; i < LENGTH; i++) { System.out.print("+"); System.err.print("-"); } } } zt-exec-zt-exec-1.11/src/test/java/org/zeroturnaround/exec/test/CallerLoggerUtilTest.java000066400000000000000000000027361350762700300315700ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec.test; import org.junit.Assert; import org.junit.Test; import org.zeroturnaround.exec.stream.CallerLoggerUtil; public class CallerLoggerUtilTest { @Test public void testFullName() throws Exception { String fullName = "my.full.Logger"; Assert.assertEquals(fullName, CallerLoggerUtil.getName(fullName)); } @Test public void testShortName() throws Exception { String shortName = "MyLogger"; String fullName = getClass().getName() + "." + shortName; Assert.assertEquals(fullName, CallerLoggerUtil.getName(shortName)); } @Test public void testMyClassName() throws Exception { String fullName = getClass().getName(); Assert.assertEquals(fullName, CallerLoggerUtil.getName(null)); } } zt-exec-zt-exec-1.11/src/test/java/org/zeroturnaround/exec/test/EmptyArgTest.java000066400000000000000000000031071350762700300301110ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec.test; import org.junit.Assert; import org.junit.Test; import org.zeroturnaround.exec.ProcessExecutor; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * Tests passing empty arguments. * * @see ProcessExecutor * @see ArgumentsAsList */ public class EmptyArgTest { @Test public void testReadOutputAndError() throws Exception { String output = argumentsAsList("arg1", "", "arg3", "").readOutput(true).execute().outputUTF8(); Assert.assertEquals("[arg1, , arg3, ]", output); } private ProcessExecutor argumentsAsList(String... args) { List command = new ArrayList(); command.addAll(Arrays.asList("java", "-cp", "target/test-classes", ArgumentsAsList.class.getName())); command.addAll(Arrays.asList(args)); return new ProcessExecutor(command); } } zt-exec-zt-exec-1.11/src/test/java/org/zeroturnaround/exec/test/ExitLikeABoss.java000066400000000000000000000021461350762700300301710ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec.test; public class ExitLikeABoss { public static void main(String[] args) { int exitCode = 0; if (args.length>0) { try { exitCode = Integer.parseInt(args[0]); } catch (NumberFormatException e) { System.out.println("Please provide valid exit code as parameter"); } } System.exit(exitCode); } } zt-exec-zt-exec-1.11/src/test/java/org/zeroturnaround/exec/test/HelloWorld.java000066400000000000000000000016301350762700300275730ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec.test; public class HelloWorld { public static void main(String[] args) { System.out.print("Hello "); System.err.print("world!"); } } zt-exec-zt-exec-1.11/src/test/java/org/zeroturnaround/exec/test/InputRedirectTest.java000066400000000000000000000036201350762700300311420ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec.test; import java.io.ByteArrayInputStream; import org.apache.commons.lang3.SystemUtils; import org.junit.Assume; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.zeroturnaround.exec.ProcessExecutor; /** * Reported in https://github.com/zeroturnaround/zt-exec/issues/30 */ public class InputRedirectTest { private static final Logger log = LoggerFactory.getLogger(InputRedirectTest.class); @Test public void testRedirectInput() throws Exception { String binTrue; if (SystemUtils.IS_OS_LINUX) { binTrue = "/bin/true"; } else if (SystemUtils.IS_OS_MAC_OSX) { binTrue = "/usr/bin/true"; } else { Assume.assumeTrue("Unsupported OS " + SystemUtils.OS_NAME, false); return; // Skip this test } // We need to put something in the buffer ByteArrayInputStream bais = new ByteArrayInputStream("foo".getBytes()); ProcessExecutor exec = new ProcessExecutor().command(binTrue); // Test that we don't get IOException: Stream closed int exit = exec.redirectInput(bais).readOutput(true).execute().getExitValue(); log.debug("Exit: {}", exit); } } zt-exec-zt-exec-1.11/src/test/java/org/zeroturnaround/exec/test/InputStreamPumperTest.java000066400000000000000000000042631350762700300320310ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec.test; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import org.junit.Assert; import org.junit.Test; import org.zeroturnaround.exec.ProcessExecutor; import org.zeroturnaround.exec.stream.PumpStreamHandler; /** * Tests that test redirected input for the process to be run. */ public class InputStreamPumperTest { @Test public void testPumpFromInputToOutput() throws Exception { String str = "Tere Minu Uus vihik"; ByteArrayInputStream bais = new ByteArrayInputStream(str.getBytes()); ByteArrayOutputStream baos = new ByteArrayOutputStream(); PumpStreamHandler handler = new PumpStreamHandler(baos, System.err, bais); ProcessExecutor exec = new ProcessExecutor("java", "-cp", "target/test-classes", PrintInputToOutput.class.getName()).readOutput(true); exec.streams(handler); String result = exec.execute().outputUTF8(); Assert.assertEquals(str, result); } @Test public void testPumpFromInputToOutputWithInput() throws Exception { String str = "Tere Minu Uus vihik"; ByteArrayInputStream bais = new ByteArrayInputStream(str.getBytes()); ByteArrayOutputStream baos = new ByteArrayOutputStream(); ProcessExecutor exec = new ProcessExecutor("java", "-cp", "target/test-classes", PrintInputToOutput.class.getName()).readOutput(true).redirectInput(bais); String result = exec.execute().outputUTF8(); Assert.assertEquals(str, result); } } zt-exec-zt-exec-1.11/src/test/java/org/zeroturnaround/exec/test/LogOutputStreamTest.java000066400000000000000000000044071350762700300315030ustar00rootroot00000000000000package org.zeroturnaround.exec.test; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.junit.Assert; import org.junit.Test; import org.zeroturnaround.exec.stream.LogOutputStream; public class LogOutputStreamTest { private void testLogOutputStream(String multiLineString, String... expectedLines) throws UnsupportedEncodingException, IOException { final List processedLines = new ArrayList(); LogOutputStream logOutputStream = new LogOutputStream() { @Override protected void processLine(String line) { processedLines.add(line); } }; try { logOutputStream.write(multiLineString.getBytes("UTF-8")); } finally { logOutputStream.close(); } Assert.assertEquals(Arrays.asList(expectedLines), processedLines); } @Test public void testSimple() throws UnsupportedEncodingException, IOException { testLogOutputStream("foo", "foo"); } @Test public void testNewLine() throws UnsupportedEncodingException, IOException { testLogOutputStream("foo\nbar", "foo", "bar"); } @Test public void testNewLineWithMultipleLines() throws UnsupportedEncodingException, IOException { testLogOutputStream("foo1\nbar1\nfoo2\nbar2", "foo1", "bar1", "foo2", "bar2"); } @Test public void testCarriageReturn() throws UnsupportedEncodingException, IOException { testLogOutputStream("foo\rbar", "foo", "bar"); } @Test public void testCarriageReturnWithMultipleLines() throws UnsupportedEncodingException, IOException { testLogOutputStream("foo1\rbar1\rfoo2\rbar2", "foo1", "bar1", "foo2", "bar2"); } @Test public void testCarriageReturnAndNewLine() throws UnsupportedEncodingException, IOException { testLogOutputStream("foo\r\nbar", "foo", "bar"); } @Test public void testCarriageReturnAndNewLineWithMultipleLines() throws UnsupportedEncodingException, IOException { testLogOutputStream("foo1\r\nbar1\r\nfoo2\r\nbar2", "foo1", "bar1", "foo2", "bar2"); } @Test public void testTwoNewLines() throws UnsupportedEncodingException, IOException { testLogOutputStream("foo\n\nbar", "foo", "bar"); } @Test public void testNewLineAtTheEnd() throws UnsupportedEncodingException, IOException { testLogOutputStream("foo\n", "foo"); } } zt-exec-zt-exec-1.11/src/test/java/org/zeroturnaround/exec/test/Loop.java000066400000000000000000000006461350762700300264370ustar00rootroot00000000000000package org.zeroturnaround.exec.test; import java.io.PrintStream; class Loop { private static final long INTERVAL = 1000; private static final long COUNT = 10; public static void main(String[] args) throws Exception { PrintStream out = System.out; out.println("Started"); for (int i = 0; i < COUNT; i++) { out.println(i); Thread.sleep(INTERVAL); } out.println("Finished"); } } zt-exec-zt-exec-1.11/src/test/java/org/zeroturnaround/exec/test/MockProcessDestroyer.java000066400000000000000000000022241350762700300316510ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec.test; import org.zeroturnaround.exec.listener.ProcessDestroyer; public class MockProcessDestroyer implements ProcessDestroyer { volatile Process added; volatile Process removed; public boolean add(Process process) { added = process; return true; } public boolean remove(Process process) { removed = process; return true; } public int size() { return 0; } } zt-exec-zt-exec-1.11/src/test/java/org/zeroturnaround/exec/test/PrintArguments.java000066400000000000000000000002731350762700300305040ustar00rootroot00000000000000package org.zeroturnaround.exec.test; public class PrintArguments { public static void main(String[] args) { for (String arg : args) { System.out.println(arg); } } } zt-exec-zt-exec-1.11/src/test/java/org/zeroturnaround/exec/test/PrintInputToOutput.java000066400000000000000000000007551350762700300313670ustar00rootroot00000000000000package org.zeroturnaround.exec.test; import java.io.BufferedReader; import java.io.InputStreamReader; public class PrintInputToOutput { public static void main(String[] args) throws Exception { InputStreamReader isr = new InputStreamReader(System.in); BufferedReader br = new BufferedReader(isr); String line = null; int count = 0; while ((line = br.readLine()) != null) { System.out.print(line); count++; if (count == 3) break; } } } ProcessExecutorArgsWithExtraSpaceTest.java000066400000000000000000000026301350762700300350700ustar00rootroot00000000000000zt-exec-zt-exec-1.11/src/test/java/org/zeroturnaround/exec/test/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec.test; import org.junit.Assert; import org.junit.Test; import org.zeroturnaround.exec.ProcessExecutor; /** * Tests argument splitting. * * @see ProcessExecutor * @see ArgumentsAsList */ public class ProcessExecutorArgsWithExtraSpaceTest { @Test public void testReadOutputAndError() throws Exception { String output = argumentsAsList("arg1 arg2 arg3").readOutput(true).execute().outputUTF8(); Assert.assertEquals("[arg1, arg2, arg3]", output); } private ProcessExecutor argumentsAsList(String args) { return new ProcessExecutor().commandSplit("java -cp target/test-classes " + ArgumentsAsList.class.getName() + " " + args); } } zt-exec-zt-exec-1.11/src/test/java/org/zeroturnaround/exec/test/ProcessExecutorBigOutputTest.java000066400000000000000000000053141350762700300333630ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec.test; import java.io.ByteArrayOutputStream; import java.util.concurrent.TimeUnit; import org.junit.Assert; import org.junit.Test; import org.zeroturnaround.exec.ProcessExecutor; /** * Tests reading large output that doesn't fit into a buffer between this process and sub process. * * @author Rein Raudjärv * * @see ProcessExecutor * @see BigOutput */ public class ProcessExecutorBigOutputTest { @Test public void testDevNull() throws Exception { bigOutput().execute(); } @Test public void testDevNullSeparate() throws Exception { bigOutput().redirectErrorStream(false).execute(); } @Test public void testReadOutputAndError() throws Exception { String output = bigOutput().readOutput(true).execute().outputUTF8(); Assert.assertEquals(repeat("+-"), output); } @Test public void testReadOutputOnly() throws Exception { String output = bigOutput().readOutput(true).redirectErrorStream(false).execute().outputUTF8(); Assert.assertEquals(repeat("+"), output); } @Test public void testRedirectOutputOnly() throws Exception { ByteArrayOutputStream out = new ByteArrayOutputStream(); bigOutput().redirectOutput(out).redirectErrorStream(false).execute(); Assert.assertEquals(repeat("+"), new String(out.toByteArray())); } @Test public void testRedirectErrorOnly() throws Exception { ByteArrayOutputStream err = new ByteArrayOutputStream(); bigOutput().redirectError(err).redirectErrorStream(false).execute(); Assert.assertEquals(repeat("-"), new String(err.toByteArray())); } private ProcessExecutor bigOutput() { // Use timeout in case we get stuck return new ProcessExecutor("java", "-cp", "target/test-classes", BigOutput.class.getName()).timeout(10, TimeUnit.SECONDS); } private static String repeat(String s) { StringBuffer sb = new StringBuffer(BigOutput.LENGTH * 2); for (int i = 0; i < BigOutput.LENGTH; i++) sb.append(s); return sb.toString(); } } zt-exec-zt-exec-1.11/src/test/java/org/zeroturnaround/exec/test/ProcessExecutorCommandLineTest.java000066400000000000000000000056061350762700300336330ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec.test; import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.concurrent.TimeoutException; import org.apache.commons.io.IOUtils; import org.junit.Assert; import org.junit.Test; import org.zeroturnaround.exec.ProcessExecutor; /** * Tests passing command line arguments to a Java process. */ public class ProcessExecutorCommandLineTest { @Test public void testOneArg() throws Exception { testArguments("foo"); } @Test public void testTwoArgs() throws Exception { testArguments("foo", "bar"); } @Test public void testSpaces() throws Exception { testArguments("foo foo", "bar bar"); } @Test public void testQuotes() throws Exception { String[] args = new String[]{"\"a\"", "b \"c\" d", "f \"e\"", "\"g\" h"}; List expected = Arrays.asList("\"a\"", "b \"c\" d", "f \"e\"", "\"g\" h"); if (System.getProperty("os.name").startsWith("Windows")) expected = Arrays.asList("a", "b c d", "f e", "g h"); testArguments(expected, args); } @Test public void testSlashes() throws Exception { testArguments("/o\\", "\\/.*"); } private void testArguments(String... args) throws IOException, InterruptedException, TimeoutException { byte[] bytes = printArguments(args).execute().output(); List expected = Arrays.asList(args); List actual = IOUtils.readLines(new ByteArrayInputStream(bytes)); Assert.assertEquals(expected, actual); } private void testArguments(List expected, String... args) throws IOException, InterruptedException, TimeoutException { byte[] bytes = printArguments(args).execute().output(); List actual = IOUtils.readLines(new ByteArrayInputStream(bytes)); Assert.assertEquals(expected, actual); } private ProcessExecutor printArguments(String... args) { List command = new ArrayList(); command.addAll(Arrays.asList("java", "-cp", "target/test-classes", PrintArguments.class.getName())); command.addAll(Arrays.asList(args)); return new ProcessExecutor(command).readOutput(true); } } zt-exec-zt-exec-1.11/src/test/java/org/zeroturnaround/exec/test/ProcessExecutorExitValueTest.java000066400000000000000000000043051350762700300333460ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec.test; import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; import org.junit.Test; import org.zeroturnaround.exec.InvalidExitValueException; import org.zeroturnaround.exec.ProcessExecutor; public class ProcessExecutorExitValueTest { @Test(expected=InvalidExitValueException.class) public void testJavaVersionExitValueCheck() throws Exception { new ProcessExecutor().command("java", "-version").exitValues(3).execute(); } @Test(expected=InvalidExitValueException.class) public void testJavaVersionExitValueCheckTimeout() throws Exception { new ProcessExecutor().command("java", "-version").exitValues(3).timeout(60, TimeUnit.SECONDS).execute(); } public void testNonZeroExitValueByDefault() throws Exception { new ProcessExecutor(exitLikeABoss(17)).execute(); } @Test public void testCustomExitValueValid() throws Exception { new ProcessExecutor(exitLikeABoss(17)).exitValues(17).execute(); } @Test(expected=InvalidExitValueException.class) public void testCustomExitValueInvalid() throws Exception { new ProcessExecutor(exitLikeABoss(17)).exitValues(15).execute(); } private static List exitLikeABoss(int exitValue) { List result = new ArrayList(); result.add("java"); result.add("-cp"); result.add("target/test-classes"); result.add(ExitLikeABoss.class.getName()); result.add(String.valueOf(exitValue)); return result; } } zt-exec-zt-exec-1.11/src/test/java/org/zeroturnaround/exec/test/ProcessExecutorHelloWorldTest.java000066400000000000000000000114471350762700300335200ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec.test; import java.io.ByteArrayOutputStream; import org.junit.Assert; import org.junit.Test; import org.zeroturnaround.exec.ProcessExecutor; /** * Tests redirecting stream. * * @author Rein Raudjärv * * @see ProcessExecutor * @see HelloWorld */ public class ProcessExecutorHelloWorldTest { @Test public void testReadOutputAndError() throws Exception { String output = helloWorld().readOutput(true).execute().outputUTF8(); Assert.assertEquals("Hello world!", output); } @Test public void testReadOutputOnly() throws Exception { String output = helloWorld().readOutput(true).redirectErrorStream(false).execute().outputUTF8(); Assert.assertEquals("Hello ", output); } @Test public void testRedirectOutputAndError() throws Exception { ByteArrayOutputStream out = new ByteArrayOutputStream(); helloWorld().redirectOutput(out).execute(); Assert.assertEquals("Hello world!", new String(out.toByteArray())); } @Test public void testRedirectOutputAndErrorMerged() throws Exception { ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayOutputStream err = new ByteArrayOutputStream(); helloWorld().redirectOutput(out).redirectError(err).execute(); Assert.assertEquals("Hello ", new String(out.toByteArray())); Assert.assertEquals("world!", new String(err.toByteArray())); } @Test public void testRedirectOutputAndErrorAndReadOutput() throws Exception { ByteArrayOutputStream out = new ByteArrayOutputStream(); String output = helloWorld().redirectOutput(out).readOutput(true).execute().outputUTF8(); Assert.assertEquals("Hello world!", output); Assert.assertEquals("Hello world!", new String(out.toByteArray())); } @Test public void testRedirectOutputOnly() throws Exception { ByteArrayOutputStream out = new ByteArrayOutputStream(); helloWorld().redirectOutput(out).redirectErrorStream(false).execute(); Assert.assertEquals("Hello ", new String(out.toByteArray())); } @Test public void testRedirectOutputOnlyAndReadOutput() throws Exception { ByteArrayOutputStream out = new ByteArrayOutputStream(); String output = helloWorld().redirectOutput(out).redirectErrorStream(false).readOutput(true).execute().outputUTF8(); Assert.assertEquals("Hello ", output); Assert.assertEquals("Hello ", new String(out.toByteArray())); } @Test public void testRedirectErrorOnly() throws Exception { ByteArrayOutputStream err = new ByteArrayOutputStream(); helloWorld().redirectError(err).redirectErrorStream(false).execute(); Assert.assertEquals("world!", new String(err.toByteArray())); } @Test public void testRedirectErrorOnlyAndReadOutput() throws Exception { ByteArrayOutputStream err = new ByteArrayOutputStream(); String output = helloWorld().redirectError(err).redirectErrorStream(false).readOutput(true).execute().outputUTF8(); Assert.assertEquals("Hello ", output); Assert.assertEquals("world!", new String(err.toByteArray())); } @Test public void testRedirectOutputAndErrorSeparate() throws Exception { ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayOutputStream err = new ByteArrayOutputStream(); helloWorld().redirectOutput(out).redirectError(err).redirectErrorStream(false).execute(); Assert.assertEquals("Hello ", new String(out.toByteArray())); Assert.assertEquals("world!", new String(err.toByteArray())); } @Test public void testRedirectOutputAndErrorSeparateAndReadOutput() throws Exception { ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayOutputStream err = new ByteArrayOutputStream(); String output = helloWorld().redirectOutput(out).redirectError(err).redirectErrorStream(false).readOutput(true).execute().outputUTF8(); Assert.assertEquals("Hello ", output); Assert.assertEquals("Hello ", new String(out.toByteArray())); Assert.assertEquals("world!", new String(err.toByteArray())); } private ProcessExecutor helloWorld() { return new ProcessExecutor("java", "-cp", "target/test-classes", HelloWorld.class.getName()); } } zt-exec-zt-exec-1.11/src/test/java/org/zeroturnaround/exec/test/ProcessExecutorInputStreamTest.java000066400000000000000000000045411350762700300337150ustar00rootroot00000000000000package org.zeroturnaround.exec.test; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.PipedInputStream; import java.io.PipedOutputStream; import java.util.concurrent.TimeUnit; import org.junit.Assert; import org.junit.Test; import org.zeroturnaround.exec.ProcessExecutor; import org.zeroturnaround.exec.StartedProcess; /** * */ public class ProcessExecutorInputStreamTest { @Test public void testWithInputAndRedirectOutput() throws Exception { String str = "Tere Minu Uus vihik"; ByteArrayInputStream bais = new ByteArrayInputStream(str.getBytes()); ByteArrayOutputStream baos = new ByteArrayOutputStream(); ProcessExecutor exec = new ProcessExecutor("java", "-cp", "target/test-classes", PrintInputToOutput.class.getName()); exec.redirectInput(bais).redirectOutput(baos); exec.execute(); Assert.assertEquals(str, baos.toString()); } @Test public void testRedirectPipedInputStream() throws Exception { // Setup InputStream that will block on a read() PipedOutputStream pos = new PipedOutputStream(); PipedInputStream pis = new PipedInputStream(pos); ByteArrayOutputStream baos = new ByteArrayOutputStream(); ProcessExecutor exec = new ProcessExecutor("java", "-cp", "target/test-classes", PrintArguments.class.getName()); exec.redirectInput(pis); StartedProcess startedProcess = exec.start(); // Assert that we don't get a TimeoutException startedProcess.getFuture().get(5, TimeUnit.SECONDS); } @Test public void testDataIsFlushedToProcessWithANonEndingInputStream() throws Exception { String str = "Tere Minu Uus vihik " + System.nanoTime(); // Setup InputStream that will block on a read() PipedOutputStream pos = new PipedOutputStream(); PipedInputStream pis = new PipedInputStream(pos); ByteArrayOutputStream baos = new ByteArrayOutputStream(); ProcessExecutor exec = new ProcessExecutor("java", "-cp", "target/test-classes", PrintInputToOutput.class.getName()); exec.redirectInput(pis).redirectOutput(baos); StartedProcess startedProcess = exec.start(); pos.write(str.getBytes()); pos.write("\n\n\n".getBytes()); // PrintInputToOutput processes at most 3 lines // Assert that we don't get a TimeoutException startedProcess.getFuture().get(5, TimeUnit.SECONDS); Assert.assertEquals(str, baos.toString()); } } zt-exec-zt-exec-1.11/src/test/java/org/zeroturnaround/exec/test/ProcessExecutorLoggerTest.java000066400000000000000000000045111350762700300326560ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec.test; import java.io.OutputStream; import org.junit.Assert; import org.junit.Test; import org.zeroturnaround.exec.ProcessExecutor; import org.zeroturnaround.exec.stream.PumpStreamHandler; import org.zeroturnaround.exec.stream.slf4j.Slf4jInfoOutputStream; import org.zeroturnaround.exec.stream.slf4j.Slf4jStream; public class ProcessExecutorLoggerTest { @Test public void testFullName() throws Exception { String fullName = "my.full.Logger"; testSlf4jLoggerName(fullName, Slf4jStream.of(fullName)); } @Test public void testShortName() throws Exception { String shortName = "MyLogger"; String fullName = getClass().getName() + "." + shortName; testSlf4jLoggerName(fullName, Slf4jStream.of(shortName)); } @Test public void testClassNameWithShortName() throws Exception { String shortName = "MyLogger"; String fullName = getClass().getName() + "." + shortName; testSlf4jLoggerName(fullName, Slf4jStream.of(getClass(), shortName)); } @Test public void testMyClassName() throws Exception { String fullName = getClass().getName(); testSlf4jLoggerName(fullName, Slf4jStream.ofCaller()); } private void testSlf4jLoggerName(String fullName, Slf4jStream stream) { ProcessExecutor executor = new ProcessExecutor(); executor.redirectOutput(stream.asInfo()); PumpStreamHandler pumps = executor.pumps(); OutputStream out = pumps.getOut(); Assert.assertTrue("Slf4jInfoOutputStream expected", out instanceof Slf4jInfoOutputStream); Assert.assertEquals(fullName, ((Slf4jInfoOutputStream) out).getLogger().getName()); } } zt-exec-zt-exec-1.11/src/test/java/org/zeroturnaround/exec/test/ProcessExecutorMainTest.java000066400000000000000000000154261350762700300323320ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec.test; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.apache.commons.lang3.StringUtils; import org.junit.Assert; import org.junit.Test; import org.zeroturnaround.exec.ProcessExecutor; import org.zeroturnaround.exec.ProcessResult; import org.zeroturnaround.exec.stream.ExecuteStreamHandler; import org.zeroturnaround.exec.stream.slf4j.Slf4jStream; public class ProcessExecutorMainTest { @Test(expected=IllegalStateException.class) public void testNoCommand() throws Exception { new ProcessExecutor().execute(); } @Test(expected=IOException.class) public void testNoSuchFile() throws Exception { new ProcessExecutor().command("unknown command").execute(); } @Test public void testJavaVersion() throws Exception { int exit = new ProcessExecutor().command("java", "-version").execute().getExitValue(); Assert.assertEquals(0, exit); } @Test public void testJavaVersionCommandSplit() throws Exception { int exit = new ProcessExecutor().commandSplit("java -version").execute().getExitValue(); Assert.assertEquals(0, exit); } @Test public void testJavaVersionIterable() throws Exception { Iterable iterable = Arrays.asList("java", "-version"); int exit = new ProcessExecutor().command(iterable).execute().getExitValue(); Assert.assertEquals(0, exit); } @Test public void testJavaVersionFuture() throws Exception { int exit = new ProcessExecutor().command("java", "-version").start().getFuture().get().getExitValue(); Assert.assertEquals(0, exit); } @Test public void testJavaVersionOutput() throws Exception { ProcessResult result = new ProcessExecutor().command("java", "-version").readOutput(true).execute(); String str = result.outputUTF8(); Assert.assertFalse(StringUtils.isEmpty(str)); } @Test public void testJavaVersionOutputTwice() throws Exception { ProcessExecutor executor = new ProcessExecutor().command("java", "-version").readOutput(true); ProcessResult result = executor.execute(); String str = result.outputUTF8(); Assert.assertFalse(StringUtils.isEmpty(str)); Assert.assertEquals(str, executor.execute().outputUTF8()); } @Test public void testJavaVersionOutputFuture() throws Exception { ProcessResult result = new ProcessExecutor().command("java", "-version").readOutput(true).start().getFuture().get(); String str = result.outputUTF8(); Assert.assertFalse(StringUtils.isEmpty(str)); } @Test public void testJavaVersionLogInfo() throws Exception { // Just expect no errors - don't check the log file itself new ProcessExecutor().command("java", "-version").redirectOutput(Slf4jStream.of("testJavaVersionLogInfo").asInfo()).execute(); } @Test public void testJavaVersionLogInfoAndOutput() throws Exception { // Just expect no errors - don't check the log file itself ProcessResult result = new ProcessExecutor().command("java", "-version").redirectOutput(Slf4jStream.of("testJavaVersionLogInfoAndOutput").asInfo()).readOutput(true).execute(); String str = result.outputUTF8(); Assert.assertFalse(StringUtils.isEmpty(str)); } @Test public void testJavaVersionLogInfoAndOutputFuture() throws Exception { // Just expect no errors - don't check the log file itself ProcessResult result = new ProcessExecutor().command("java", "-version").redirectOutput(Slf4jStream.of("testJavaVersionLogInfoAndOutputFuture").asInfo()).readOutput(true).start().getFuture().get(); String str = result.outputUTF8(); Assert.assertFalse(StringUtils.isEmpty(str)); } @Test public void testJavaVersionNoStreams() throws Exception { // Just expect no errors new ProcessExecutor().command("java", "-version").streams(null).execute(); } @Test public void testProcessDestroyerEvents() throws Exception { MockProcessDestroyer mock = new MockProcessDestroyer(); new ProcessExecutor().command("java", "-version").destroyer(mock).execute(); Assert.assertNotNull(mock.added); Assert.assertEquals(mock.added, mock.removed); } @Test public void testProcessDestroyerEventsOnStreamsFail() throws Exception { MockProcessDestroyer mock = new MockProcessDestroyer(); ExecuteStreamHandler streams = new SetFailExecuteStreamHandler(); try { new ProcessExecutor().command("java", "-version").streams(streams).destroyer(mock).execute(); Assert.fail("IOException expected"); } catch (IOException e) { // Good } Assert.assertNull(mock.added); Assert.assertNull(mock.removed); } @Test public void testProcessExecutorListInit() throws Exception { // Use timeout in case we get stuck List args = new ArrayList() { { add("java"); add("-cp"); add("target/test-classes"); add(HelloWorld.class.getName()); } }; ProcessExecutor exec = new ProcessExecutor(args); ProcessResult result = exec.readOutput(true).execute(); Assert.assertEquals("Hello world!", result.outputUTF8()); } @Test public void testProcessExecutorCommand() throws Exception { // Use timeout in case we get stuck List args = new ArrayList() { { add("java"); add("-cp"); add("target/test-classes"); add(HelloWorld.class.getName()); } }; ProcessExecutor exec = new ProcessExecutor(); exec.command(args); ProcessResult result = exec.readOutput(true).execute(); Assert.assertEquals("Hello world!", result.outputUTF8()); } @Test public void testProcessExecutorSetDirectory() throws Exception { // Use timeout in case we get stuck List args = new ArrayList() { { add("java"); add("-cp"); add("test-classes"); add(HelloWorld.class.getName()); } }; ProcessExecutor exec = new ProcessExecutor().directory(new File("target")); exec.command(args); ProcessResult result = exec.readOutput(true).execute(); Assert.assertEquals("Hello world!", result.outputUTF8()); } } zt-exec-zt-exec-1.11/src/test/java/org/zeroturnaround/exec/test/ProcessExecutorStreamCloseTest.java000066400000000000000000000037301350762700300336620ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec.test; import java.io.ByteArrayOutputStream; import org.junit.Assert; import org.junit.Test; import org.zeroturnaround.exec.ProcessExecutor; /** * Tests that redirect target stream are not closed. * * @author Rein Raudjärv * * @see ProcessExecutor * @see HelloWorld */ public class ProcessExecutorStreamCloseTest { @Test public void testRedirectOutputNotClosed() throws Exception { ByteArrayOutputStream out = new ByteArrayOutputStream(); RememberCloseOutputStream close = new RememberCloseOutputStream(out); helloWorld().redirectOutput(close).redirectErrorStream(false).execute(); Assert.assertEquals("Hello ", new String(out.toByteArray())); Assert.assertFalse(close.isClosed()); } @Test public void testRedirectErrorNotClosed() throws Exception { ByteArrayOutputStream out = new ByteArrayOutputStream(); RememberCloseOutputStream close = new RememberCloseOutputStream(out); helloWorld().redirectError(close).execute(); Assert.assertEquals("world!", new String(out.toByteArray())); Assert.assertFalse(close.isClosed()); } private ProcessExecutor helloWorld() { return new ProcessExecutor("java", "-cp", "target/test-classes", HelloWorld.class.getName()); } } zt-exec-zt-exec-1.11/src/test/java/org/zeroturnaround/exec/test/ProcessExecutorTimeoutTest.java000066400000000000000000000100161350762700300330620ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec.test; import org.apache.commons.lang3.SystemUtils; import org.hamcrest.CoreMatchers; import org.junit.Assert; import org.junit.Test; import org.zeroturnaround.exec.ProcessExecutor; import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; public class ProcessExecutorTimeoutTest { @Test public void testExecuteTimeout() throws Exception { try { // Use timeout in case we get stuck List args = getWriterLoopCommand(); new ProcessExecutor().command(args).timeout(1, TimeUnit.SECONDS).execute(); Assert.fail("TimeoutException expected."); } catch (TimeoutException e) { Assert.assertThat(e.getMessage(), CoreMatchers.containsString("1 second")); Assert.assertThat(e.getMessage(), CoreMatchers.containsString(Loop.class.getName())); } } @Test public void testStartTimeout() throws Exception { try { // Use timeout in case we get stuck List args = getWriterLoopCommand(); new ProcessExecutor().command(args).start().getFuture().get(1, TimeUnit.SECONDS); Assert.fail("TimeoutException expected."); } catch (TimeoutException e) { Assert.assertNull(e.getMessage()); } } private List getWriterLoopCommand() { List args = new ArrayList() { { add("java"); add("-cp"); add("target/test-classes"); add(Loop.class.getName()); } }; return args; } /* * This is a test copied from https://github.com/zeroturnaround/zt-exec/issues/56 */ @Test public void testExecuteTimeoutIssue56_1() throws Exception { try { List commands = new ArrayList(); if (SystemUtils.IS_OS_WINDOWS) { // native sleep command is not available on Windows platform // mock using standard ping to localhost instead // (Windows ping does 4 requests which takes about 3 seconds) commands.add("ping"); commands.add("127.0.0.1"); } else { commands.add("sleep"); commands.add("3"); } new ProcessExecutor() .command(commands) .timeout(1, TimeUnit.SECONDS) .execute(); Assert.fail("TimeoutException expected."); } catch (TimeoutException e) { Assert.assertThat(e.getMessage(), CoreMatchers.containsString("1 second")); } } /* * This is a test copied from https://github.com/zeroturnaround/zt-exec/issues/56 */ @Test public void testStartTimeoutIssue56_2() throws Exception { try { List commands = new ArrayList(); if (SystemUtils.IS_OS_WINDOWS) { // native sleep command is not available on Windows platform // mock using standard ping to localhost instead // (Windows ping does 4 requests which takes about 3 seconds) commands.add("ping"); commands.add("127.0.0.1"); } else { commands.add("sleep"); commands.add("3"); } new ProcessExecutor() .command(commands) .start() .getFuture() .get(1, TimeUnit.SECONDS); Assert.fail("TimeoutException expected."); } catch (TimeoutException e) { Assert.assertNull(e.getMessage()); } } } zt-exec-zt-exec-1.11/src/test/java/org/zeroturnaround/exec/test/ProcessInitExceptionTest.java000066400000000000000000000042141350762700300325020ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec.test; import java.io.IOException; import org.junit.Assert; import org.junit.Test; import org.zeroturnaround.exec.ProcessInitException; public class ProcessInitExceptionTest { @Test public void testNull() throws Exception { Assert.assertNull(ProcessInitException.newInstance(null, new IOException())); } @Test public void testEmpty() throws Exception { Assert.assertNull(ProcessInitException.newInstance(null, new IOException(""))); } @Test public void testSimple() throws Exception { ProcessInitException e = ProcessInitException.newInstance( "Could not run test.", new IOException("java.io.IOException: Cannot run program \"ls\": java.io.IOException: error=12, Cannot allocate memory")); Assert.assertNotNull(e); Assert.assertEquals("Could not run test. Error=12, Cannot allocate memory", e.getMessage()); Assert.assertEquals(12, e.getErrorCode()); } @Test public void testBeforeCode() throws Exception { ProcessInitException e = ProcessInitException.newInstance( "Could not run test.", new IOException("java.io.IOException: Cannot run program \"sleep\": java.io.IOException: CreateProcess error=2, The system cannot find the file specified")); Assert.assertNotNull(e); Assert.assertEquals("Could not run test. Error=2, The system cannot find the file specified", e.getMessage()); Assert.assertEquals(2, e.getErrorCode()); } } zt-exec-zt-exec-1.11/src/test/java/org/zeroturnaround/exec/test/ProcessListenerSuccessTest.java000066400000000000000000000042251350762700300330400ustar00rootroot00000000000000package org.zeroturnaround.exec.test; import org.junit.Assert; import org.junit.Test; import org.zeroturnaround.exec.ProcessExecutor; import org.zeroturnaround.exec.ProcessResult; import org.zeroturnaround.exec.listener.ProcessListener; public class ProcessListenerSuccessTest { @Test public void testJavaVersion() throws Exception { ProcessListenerImpl listener = new ProcessListenerImpl(); ProcessResult result = new ProcessExecutor("java", "-version").addListener(listener).execute(); int exit = result.getExitValue(); Assert.assertEquals(0, exit); Assert.assertNotNull(listener.executor); Assert.assertNotNull(listener.process); Assert.assertNotNull(listener.result); Assert.assertEquals(result, listener.result); } static class ProcessListenerImpl extends ProcessListener { ProcessExecutor executor; Process process; ProcessResult result; @Override public void beforeStart(ProcessExecutor executor) { Assert.assertNotNull(executor); Assert.assertNull(this.executor); Assert.assertNull(this.process); Assert.assertNull(this.result); this.executor = executor; } @Override public void afterStart(Process process, ProcessExecutor executor) { Assert.assertNotNull(process); Assert.assertNotNull(executor); Assert.assertNotNull(this.executor); Assert.assertNull(this.process); Assert.assertNull(this.result); Assert.assertEquals(this.executor, executor); this.process = process; } @Override public void afterFinish(Process process, ProcessResult result) { Assert.assertNotNull(process); Assert.assertNotNull(result); Assert.assertNotNull(this.executor); Assert.assertNotNull(this.process); Assert.assertNull(this.result); Assert.assertEquals(this.process, process); this.result = result; } @Override public void afterStop(Process process) { Assert.assertNotNull(process); Assert.assertNotNull(this.executor); Assert.assertNotNull(this.process); Assert.assertNotNull(this.result); Assert.assertEquals(this.process, process); } } } zt-exec-zt-exec-1.11/src/test/java/org/zeroturnaround/exec/test/ProcessListenerThrowTest.java000066400000000000000000000022671350762700300325370ustar00rootroot00000000000000package org.zeroturnaround.exec.test; import java.util.concurrent.TimeUnit; import org.junit.Test; import org.zeroturnaround.exec.InvalidOutputException; import org.zeroturnaround.exec.ProcessExecutor; import org.zeroturnaround.exec.ProcessResult; import org.zeroturnaround.exec.test.ProcessListenerSuccessTest.ProcessListenerImpl; public class ProcessListenerThrowTest { @Test(expected=InvalidOutputException.class) public void testJavaVersion() throws Exception { new ProcessExecutor("java", "-version").readOutput(true).addListener(new ProcessListenerThrowImpl()).execute(); } @Test(expected=InvalidOutputException.class) public void testJavaVersionWithTimeout() throws Exception { new ProcessExecutor("java", "-version").readOutput(true).addListener(new ProcessListenerThrowImpl()).timeout(1, TimeUnit.MINUTES).execute(); } private static class ProcessListenerThrowImpl extends ProcessListenerImpl { @Override public void afterFinish(Process process, ProcessResult result) { super.afterFinish(process, result); if (result.getOutput().getString().contains("java version")) { throw new InvalidOutputException("Test", result); } } } } zt-exec-zt-exec-1.11/src/test/java/org/zeroturnaround/exec/test/RememberCloseOutputStream.java000066400000000000000000000007231350762700300326430ustar00rootroot00000000000000package org.zeroturnaround.exec.test; import java.io.FilterOutputStream; import java.io.IOException; import java.io.OutputStream; public class RememberCloseOutputStream extends FilterOutputStream { private volatile boolean closed; public RememberCloseOutputStream(OutputStream out) { super(out); } @Override public void close() throws IOException { closed = true; super.close(); } public boolean isClosed() { return closed; } } zt-exec-zt-exec-1.11/src/test/java/org/zeroturnaround/exec/test/SetFailExecuteStreamHandler.java000066400000000000000000000026401350762700300330460ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec.test; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.zeroturnaround.exec.stream.ExecuteStreamHandler; public class SetFailExecuteStreamHandler implements ExecuteStreamHandler { public void setProcessInputStream(OutputStream os) throws IOException { throw new IOException(); } public void setProcessErrorStream(InputStream is) throws IOException { throw new IOException(); } public void setProcessOutputStream(InputStream is) throws IOException { throw new IOException(); } public void start() throws IOException { // do nothing } public void stop() { // do nothing } } zt-exec-zt-exec-1.11/src/test/java/org/zeroturnaround/exec/test/shutdown/000077500000000000000000000000001350762700300265305ustar00rootroot00000000000000ProcessExecutorShutdownHookTest.java000066400000000000000000000043611350762700300356720ustar00rootroot00000000000000zt-exec-zt-exec-1.11/src/test/java/org/zeroturnaround/exec/test/shutdown/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec.test.shutdown; import java.io.File; import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.SystemUtils; import org.junit.Assert; import org.junit.Test; import org.zeroturnaround.exec.ProcessExecutor; /** * Tests destroying processes on JVM exit. */ public class ProcessExecutorShutdownHookTest { private static final long SLEEP_FOR_RECHECKING_FILE = 2000; @Test public void testDestroyOnExit() throws Exception { testDestroyOnExit(WriterLoopStarterBeforeExit.class, true); } @Test public void testDestroyOnExitInShutdownHook() throws Exception { testDestroyOnExit(WriterLoopStarterAfterExit.class, false); } private void testDestroyOnExit(Class starter, boolean fileIsAlwaysCreated) throws Exception { File file = WriterLoop.getFile(); if (file.exists()) FileUtils.forceDelete(file); new ProcessExecutor("java", "-cp", SystemUtils.JAVA_CLASS_PATH, starter.getName()).redirectOutputAsInfo().execute(); // After WriterLoopStarter has finished we expect that WriterLoop is also finished - no-one is updating the file if (fileIsAlwaysCreated || file.exists()) { checkFileStaysTheSame(file); FileUtils.forceDelete(file); } } private static void checkFileStaysTheSame(File file) throws InterruptedException { Assert.assertTrue(file.exists()); long length = file.length(); Thread.sleep(SLEEP_FOR_RECHECKING_FILE); Assert.assertEquals("File '" + file + "' was still updated.", length, file.length()); } } zt-exec-zt-exec-1.11/src/test/java/org/zeroturnaround/exec/test/shutdown/WriterLoop.java000066400000000000000000000031101350762700300314740ustar00rootroot00000000000000/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec.test.shutdown; import java.io.File; import java.io.FileWriter; import java.io.PrintWriter; /** * Program which regularly writes into a file. * By checking whether the file gets updates we know whether this program is still running or it's finished. */ class WriterLoop { private static final File FILE = new File("writeLoop.data"); private static final long INTERVAL = 1000; private static final long COUNT = 10; public static File getFile() { return FILE; } public static void main(String[] args) throws Exception { PrintWriter out = new PrintWriter(new FileWriter(FILE), true); try { out.println("Started"); for (int i = 0; i < COUNT; i++) { out.println(i); Thread.sleep(INTERVAL); } out.println("Finished"); } finally { out.close(); } } } WriterLoopStarterAfterExit.java000066400000000000000000000027451350762700300346130ustar00rootroot00000000000000zt-exec-zt-exec-1.11/src/test/java/org/zeroturnaround/exec/test/shutdown/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec.test.shutdown; import org.zeroturnaround.exec.ProcessExecutor; /** * Starts {@link WriterLoop} inside shutdown hook and destroys it. */ public class WriterLoopStarterAfterExit implements Runnable { private static final long SLEEP_AFTER_START = 2000; public static void main(String[] args) throws Exception { Runtime.getRuntime().addShutdownHook(new Thread(new WriterLoopStarterAfterExit())); // Launch the process and also destroy it System.exit(0); } public void run() { try { new ProcessExecutor("java", "-cp", "target/test-classes", WriterLoop.class.getName()).destroyOnExit().start(); Thread.sleep(SLEEP_AFTER_START); } catch (Exception e) { e.printStackTrace(); } } } WriterLoopStarterBeforeExit.java000066400000000000000000000024131350762700300347440ustar00rootroot00000000000000zt-exec-zt-exec-1.11/src/test/java/org/zeroturnaround/exec/test/shutdown/* * Copyright (C) 2014 ZeroTurnaround * Contains fragments of code from Apache Commons Exec, rights owned * by Apache Software Foundation (ASF). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zeroturnaround.exec.test.shutdown; import org.zeroturnaround.exec.ProcessExecutor; /** * Starts {@link WriterLoop} and destroys it on JVM exit. */ public class WriterLoopStarterBeforeExit { private static final long SLEEP_AFTER_START = 2000; public static void main(String[] args) throws Exception { new ProcessExecutor("java", "-cp", "target/test-classes", WriterLoop.class.getName()).destroyOnExit().start(); Thread.sleep(SLEEP_AFTER_START); // Cause the launched process to be destroyed System.exit(0); } } zt-exec-zt-exec-1.11/src/test/resources/000077500000000000000000000000001350762700300201535ustar00rootroot00000000000000zt-exec-zt-exec-1.11/src/test/resources/logback.xml000066400000000000000000000006201350762700300222750ustar00rootroot00000000000000 target/test.log true %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%logger{0}] %msg%n