From dad31f992d92117074b4f9faf61ae0794f59fed7 Mon Sep 17 00:00:00 2001 From: "Christian P. MOMON" Date: Thu, 4 May 2017 23:01:53 +0200 Subject: [PATCH] Split from devinsy-utils to devinsy-cmdexec, devinsy-rss, devinsy-strings, devinsy-unix, devinsy-xml. --- .classpath | 14 +- .settings/org.eclipse.jdt.ui.prefs | 2 + README.md | 1 - build.properties | 2 +- lib/{ => Logs}/log4j-1.2.17-source.zip | Bin lib/{ => Logs}/log4j-1.2.17.jar | Bin lib/{ => Logs}/slf4j-api-1.7.5-sources.jar | Bin lib/{ => Logs}/slf4j-api-1.7.5.jar | Bin .../slf4j-log4j12-1.7.5-sources.jar | Bin lib/{ => Logs}/slf4j-log4j12-1.7.5.jar | Bin .../hamcrest-core-1.3-sources.jar | Bin lib/{ => UnitTesting}/hamcrest-core-1.3.jar | Bin lib/{ => UnitTesting}/junit-4.11-sources.jar | Bin lib/{ => UnitTesting}/junit-4.11.jar | Bin lib/devinsy-cmdexec-0.4.0-sources.zip | Bin 0 -> 8656 bytes lib/devinsy-cmdexec-0.4.0.jar | Bin 0 -> 8560 bytes lib/devinsy-rss-0.4.0-sources.zip | Bin 0 -> 6885 bytes lib/devinsy-rss-0.4.0.jar | Bin 0 -> 5085 bytes lib/devinsy-strings-0.4.0-sources.zip | Bin 0 -> 17905 bytes lib/devinsy-strings-0.4.0.jar | Bin 0 -> 19983 bytes lib/devinsy-unix-0.4.0-sources.zip | Bin 0 -> 26486 bytes lib/devinsy-unix-0.4.0.jar | Bin 0 -> 28855 bytes lib/devinsy-xml-0.4.0-sources.zip | Bin 0 -> 17771 bytes lib/devinsy-xml-0.4.0.jar | Bin 0 -> 20537 bytes src/fr/devinsy/util/DataFile.java | 22 +- src/fr/devinsy/util/DataFiles.java | 16 +- src/fr/devinsy/util/DateHelper.java | 38 +- src/fr/devinsy/util/DateTimeHelper.java | 16 +- src/fr/devinsy/util/Digester.java | 12 +- src/fr/devinsy/util/FileCopier.java | 8 +- src/fr/devinsy/util/FileIterator.java | 32 +- src/fr/devinsy/util/FileIteratorState.java | 18 +- src/fr/devinsy/util/FileTools.java | 8 +- src/fr/devinsy/util/Fraction.java | 26 +- .../util/InternetProxyConfiguration.java | 20 +- src/fr/devinsy/util/SimpleAveragemeter.java | 16 +- src/fr/devinsy/util/SimpleChronometer.java | 14 +- src/fr/devinsy/util/StacktraceWriter.java | 10 +- src/fr/devinsy/util/ToolBox.java | 8 +- src/fr/devinsy/util/cmdexec/CmdExec.java | 500 ------ .../util/cmdexec/CmdExecException.java | 65 - .../devinsy/util/cmdexec/StreamGobbler.java | 196 -- src/fr/devinsy/util/rss/RSSCache.java | 214 --- src/fr/devinsy/util/rss/RSSElement.java | 154 -- src/fr/devinsy/util/rss/RSSWriter.java | 172 -- .../util/strings/StringLengthComparator.java | 146 -- src/fr/devinsy/util/strings/StringList.java | 1584 ----------------- .../util/strings/StringListCharIterator.java | 133 -- .../util/strings/StringListCharPosition.java | 111 -- .../util/strings/StringListInputStream.java | 130 -- .../util/strings/StringListReader.java | 122 -- .../devinsy/util/strings/StringListUtils.java | 1038 ----------- .../util/strings/StringListWriter.java | 148 -- src/fr/devinsy/util/strings/StringSet.java | 411 ----- src/fr/devinsy/util/unix/CachedFile.java | 134 -- src/fr/devinsy/util/unix/EtcGroupFile.java | 200 --- .../devinsy/util/unix/EtcGroupFileReader.java | 102 -- src/fr/devinsy/util/unix/EtcPasswdFile.java | 186 -- .../util/unix/EtcPasswdFileReader.java | 105 -- src/fr/devinsy/util/unix/Group.java | 223 --- src/fr/devinsy/util/unix/Groups.java | 233 --- src/fr/devinsy/util/unix/Unix.java | 597 ------- src/fr/devinsy/util/unix/User.java | 355 ---- src/fr/devinsy/util/unix/Users.java | 179 -- src/fr/devinsy/util/unix/acl/Acl.java | 216 --- src/fr/devinsy/util/unix/acl/AclEntries.java | 216 --- src/fr/devinsy/util/unix/acl/AclEntry.java | 113 -- src/fr/devinsy/util/unix/acl/AclManager.java | 424 ----- src/fr/devinsy/util/xml/XMLAttributes.java | 160 -- .../util/xml/XMLBadFormatException.java | 81 - src/fr/devinsy/util/xml/XMLReader.java | 617 ------- src/fr/devinsy/util/xml/XMLTag.java | 148 -- src/fr/devinsy/util/xml/XMLTools.java | 389 ---- src/fr/devinsy/util/xml/XMLWriter.java | 315 ---- src/fr/devinsy/util/xml/XMLZipReader.java | 68 - src/fr/devinsy/util/xml/XMLZipWriter.java | 149 -- test/FileIteratorSandbox.java | 8 +- test/fr/devinsy/util/FileToolsTest.java | 8 +- .../devinsy/util/cmdexec/CmdExecSandbox.java | 108 -- .../devinsy/util/strings/StringListTest.java | 402 ----- .../util/strings/StringListUtilsTest.java | 174 -- .../devinsy/util/util/rss/RSSCacheTest.java | 67 - test/fr/devinsy/util/xml/XMLReaderTest.java | 131 -- 83 files changed, 152 insertions(+), 11363 deletions(-) rename lib/{ => Logs}/log4j-1.2.17-source.zip (100%) rename lib/{ => Logs}/log4j-1.2.17.jar (100%) rename lib/{ => Logs}/slf4j-api-1.7.5-sources.jar (100%) rename lib/{ => Logs}/slf4j-api-1.7.5.jar (100%) rename lib/{ => Logs}/slf4j-log4j12-1.7.5-sources.jar (100%) rename lib/{ => Logs}/slf4j-log4j12-1.7.5.jar (100%) rename lib/{ => UnitTesting}/hamcrest-core-1.3-sources.jar (100%) rename lib/{ => UnitTesting}/hamcrest-core-1.3.jar (100%) rename lib/{ => UnitTesting}/junit-4.11-sources.jar (100%) rename lib/{ => UnitTesting}/junit-4.11.jar (100%) create mode 100644 lib/devinsy-cmdexec-0.4.0-sources.zip create mode 100644 lib/devinsy-cmdexec-0.4.0.jar create mode 100644 lib/devinsy-rss-0.4.0-sources.zip create mode 100644 lib/devinsy-rss-0.4.0.jar create mode 100644 lib/devinsy-strings-0.4.0-sources.zip create mode 100644 lib/devinsy-strings-0.4.0.jar create mode 100644 lib/devinsy-unix-0.4.0-sources.zip create mode 100644 lib/devinsy-unix-0.4.0.jar create mode 100644 lib/devinsy-xml-0.4.0-sources.zip create mode 100644 lib/devinsy-xml-0.4.0.jar delete mode 100644 src/fr/devinsy/util/cmdexec/CmdExec.java delete mode 100644 src/fr/devinsy/util/cmdexec/CmdExecException.java delete mode 100644 src/fr/devinsy/util/cmdexec/StreamGobbler.java delete mode 100644 src/fr/devinsy/util/rss/RSSCache.java delete mode 100644 src/fr/devinsy/util/rss/RSSElement.java delete mode 100644 src/fr/devinsy/util/rss/RSSWriter.java delete mode 100644 src/fr/devinsy/util/strings/StringLengthComparator.java delete mode 100644 src/fr/devinsy/util/strings/StringList.java delete mode 100644 src/fr/devinsy/util/strings/StringListCharIterator.java delete mode 100644 src/fr/devinsy/util/strings/StringListCharPosition.java delete mode 100644 src/fr/devinsy/util/strings/StringListInputStream.java delete mode 100644 src/fr/devinsy/util/strings/StringListReader.java delete mode 100644 src/fr/devinsy/util/strings/StringListUtils.java delete mode 100644 src/fr/devinsy/util/strings/StringListWriter.java delete mode 100644 src/fr/devinsy/util/strings/StringSet.java delete mode 100644 src/fr/devinsy/util/unix/CachedFile.java delete mode 100644 src/fr/devinsy/util/unix/EtcGroupFile.java delete mode 100644 src/fr/devinsy/util/unix/EtcGroupFileReader.java delete mode 100644 src/fr/devinsy/util/unix/EtcPasswdFile.java delete mode 100644 src/fr/devinsy/util/unix/EtcPasswdFileReader.java delete mode 100644 src/fr/devinsy/util/unix/Group.java delete mode 100644 src/fr/devinsy/util/unix/Groups.java delete mode 100644 src/fr/devinsy/util/unix/Unix.java delete mode 100644 src/fr/devinsy/util/unix/User.java delete mode 100644 src/fr/devinsy/util/unix/Users.java delete mode 100644 src/fr/devinsy/util/unix/acl/Acl.java delete mode 100644 src/fr/devinsy/util/unix/acl/AclEntries.java delete mode 100644 src/fr/devinsy/util/unix/acl/AclEntry.java delete mode 100644 src/fr/devinsy/util/unix/acl/AclManager.java delete mode 100644 src/fr/devinsy/util/xml/XMLAttributes.java delete mode 100644 src/fr/devinsy/util/xml/XMLBadFormatException.java delete mode 100644 src/fr/devinsy/util/xml/XMLReader.java delete mode 100644 src/fr/devinsy/util/xml/XMLTag.java delete mode 100644 src/fr/devinsy/util/xml/XMLTools.java delete mode 100644 src/fr/devinsy/util/xml/XMLWriter.java delete mode 100644 src/fr/devinsy/util/xml/XMLZipReader.java delete mode 100644 src/fr/devinsy/util/xml/XMLZipWriter.java delete mode 100644 test/fr/devinsy/util/cmdexec/CmdExecSandbox.java delete mode 100644 test/fr/devinsy/util/strings/StringListTest.java delete mode 100644 test/fr/devinsy/util/strings/StringListUtilsTest.java delete mode 100644 test/fr/devinsy/util/util/rss/RSSCacheTest.java delete mode 100644 test/fr/devinsy/util/xml/XMLReaderTest.java diff --git a/.classpath b/.classpath index 5a93c3d..2e2dbf5 100644 --- a/.classpath +++ b/.classpath @@ -3,11 +3,6 @@ - - - - - @@ -16,5 +11,14 @@ + + + + + + + + + diff --git a/.settings/org.eclipse.jdt.ui.prefs b/.settings/org.eclipse.jdt.ui.prefs index 5cbede0..4f91e57 100644 --- a/.settings/org.eclipse.jdt.ui.prefs +++ b/.settings/org.eclipse.jdt.ui.prefs @@ -55,6 +55,8 @@ eclipse.preferences.version=1 editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true formatter_profile=_Devinsy-utils formatter_settings_version=12 +jautodoc.cleanup.add_header=false +jautodoc.cleanup.replace_header=false sp_cleanup.add_default_serial_version_id=true sp_cleanup.add_generated_serial_version_id=false sp_cleanup.add_missing_annotations=true diff --git a/README.md b/README.md index 589a9d6..1bd5a04 100644 --- a/README.md +++ b/README.md @@ -20,4 +20,3 @@ Several useful Java classes. ## Conclusion Enjoy and use DEVINSY Utils. For questions, improvement, issues: christian.momon@devinsy.fr - \ No newline at end of file diff --git a/build.properties b/build.properties index 72570db..d5f00be 100644 --- a/build.properties +++ b/build.properties @@ -1,3 +1,3 @@ -product.name=devinsy-utils +product.name=Devinsy-unix product.revision.major=0 product.revision.minor=3 diff --git a/lib/log4j-1.2.17-source.zip b/lib/Logs/log4j-1.2.17-source.zip similarity index 100% rename from lib/log4j-1.2.17-source.zip rename to lib/Logs/log4j-1.2.17-source.zip diff --git a/lib/log4j-1.2.17.jar b/lib/Logs/log4j-1.2.17.jar similarity index 100% rename from lib/log4j-1.2.17.jar rename to lib/Logs/log4j-1.2.17.jar diff --git a/lib/slf4j-api-1.7.5-sources.jar b/lib/Logs/slf4j-api-1.7.5-sources.jar similarity index 100% rename from lib/slf4j-api-1.7.5-sources.jar rename to lib/Logs/slf4j-api-1.7.5-sources.jar diff --git a/lib/slf4j-api-1.7.5.jar b/lib/Logs/slf4j-api-1.7.5.jar similarity index 100% rename from lib/slf4j-api-1.7.5.jar rename to lib/Logs/slf4j-api-1.7.5.jar diff --git a/lib/slf4j-log4j12-1.7.5-sources.jar b/lib/Logs/slf4j-log4j12-1.7.5-sources.jar similarity index 100% rename from lib/slf4j-log4j12-1.7.5-sources.jar rename to lib/Logs/slf4j-log4j12-1.7.5-sources.jar diff --git a/lib/slf4j-log4j12-1.7.5.jar b/lib/Logs/slf4j-log4j12-1.7.5.jar similarity index 100% rename from lib/slf4j-log4j12-1.7.5.jar rename to lib/Logs/slf4j-log4j12-1.7.5.jar diff --git a/lib/hamcrest-core-1.3-sources.jar b/lib/UnitTesting/hamcrest-core-1.3-sources.jar similarity index 100% rename from lib/hamcrest-core-1.3-sources.jar rename to lib/UnitTesting/hamcrest-core-1.3-sources.jar diff --git a/lib/hamcrest-core-1.3.jar b/lib/UnitTesting/hamcrest-core-1.3.jar similarity index 100% rename from lib/hamcrest-core-1.3.jar rename to lib/UnitTesting/hamcrest-core-1.3.jar diff --git a/lib/junit-4.11-sources.jar b/lib/UnitTesting/junit-4.11-sources.jar similarity index 100% rename from lib/junit-4.11-sources.jar rename to lib/UnitTesting/junit-4.11-sources.jar diff --git a/lib/junit-4.11.jar b/lib/UnitTesting/junit-4.11.jar similarity index 100% rename from lib/junit-4.11.jar rename to lib/UnitTesting/junit-4.11.jar diff --git a/lib/devinsy-cmdexec-0.4.0-sources.zip b/lib/devinsy-cmdexec-0.4.0-sources.zip new file mode 100644 index 0000000000000000000000000000000000000000..1f65023f64a52b1940a2f720f15715004afc836c GIT binary patch literal 8656 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 literal 0 HcmV?d00001 diff --git a/lib/devinsy-cmdexec-0.4.0.jar b/lib/devinsy-cmdexec-0.4.0.jar new file mode 100644 index 0000000000000000000000000000000000000000..a76fa4c166596f028927629e2fee7749a5a7c4bf GIT binary patch literal 8560 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 Ym!b^pefceoRstqMv8~4=#K!`~Uy| literal 0 HcmV?d00001 diff --git a/lib/devinsy-rss-0.4.0-sources.zip b/lib/devinsy-rss-0.4.0-sources.zip new file mode 100644 index 0000000000000000000000000000000000000000..ffa5ba799dd1caf09a6ecab561ccd4f651d0bfff GIT binary patch literal 6885 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 literal 0 HcmV?d00001 diff --git a/lib/devinsy-rss-0.4.0.jar b/lib/devinsy-rss-0.4.0.jar new file mode 100644 index 0000000000000000000000000000000000000000..7e781968b91ed8c28367cefe333f19a47ae976d8 GIT binary patch literal 5085 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 IP=5dQf9-Oqc>n+a literal 0 HcmV?d00001 diff --git a/lib/devinsy-strings-0.4.0-sources.zip b/lib/devinsy-strings-0.4.0-sources.zip new file mode 100644 index 0000000000000000000000000000000000000000..0ec9078e26e9d453f0c73d3c5fcf1d223b04d485 GIT binary patch literal 17905 zcmb8X19W9u);1j5wyla)v2EM7E4FRhwko!5+fD@)e(CPF``+&V{@>f*Ipd78&&Zt5 z+G}OZwf1}_1JUiX{n|rrW+LK z7npV&ro?IJmSDwbMr##z_J9EXxe5>ff4iH4uHf~)uj!9`trXM$?mGv-FrMyxsnMk$NEL)C0N1Mrm++Rx!=zU#BGqS zvA);iBK%DM>{^xq@=JD!1sZtD-go3Jh=_pG>XAeJKH0D#;JOm9T~p1gGq;RSKf%J5 z%mm34twGEsgI|IiVmHlr45mPbaMGf;<}a};yJ2VUl2UZo7Z`OuTjnUsLWGgDMmzru z=~5n;T0NUO6O>*fAz6u*Dn(SJUxk!?g@c%t#K;fJDq35*JfwZ5(!OW{qA^p9a)lNhNCl#(w-Lo_n1AZVuC`H;^^)=Ea$#dP;<^`cQMWk)4@WlqE1 zNWUO*jDiU(Z@%Zg9jqc2JNC}1%xlh1XMcfvSZ4$b$xe)%qBx@zhIs!Tafr;|o-l|m zsj??#+1OSpek~1&x_$$;!+1uGIt8qV%!l0*tD;qr2Tnk7NF2EW${^<_5X3rgVsnOq zJ+}*8sl-A*E=4RbSD+l;0Gc2IFj;v&{{S{67un|oJQSt5`>qdC6rK;8>!ARdBDYad zg||^mO7QEaBAnkZDNG9GG;xXv$ASp&$z5C0(E5_JPp1!B(xmU++QgGia|l?qnumw= zNp_pN5l!}m%m&iGA;Vbwu{E?T$;#TI@M-c4%IozQskQq({HO~TtIR8!DQuvlTt9S? zBYrmN79sf>bhr;{G{N>g}9n31R zApcm{wv8-2e@-|JfXA09*)f87#Px7q_`KO7xwcPP{^n;pxrz6@{(z0#^5ou$DpPXx z2Gex@Xo0x3TDi%&Yr3JqV&}(Jie85gvw*kGl+xTh%JcCU%!_?FJ@xtTTLP-4e~2DD z0Kl|5008;_z9pDDI{kec*wi|ATxUi4wE9FX<^5HtR$SGZbR=?kvE^ifsKWXfc z21m<}gdM&Rmx!yI{`u~L4iDs+)_5Sgp2o=vN#o-4Q|*Edz=qeOc`Cauz|I@_M}m2u z2DtU3r|EG?)$#YuEV#F|%|TrsBk=i=2;^zlm9XK0&<5Ax>*$zTrVk&U2Lske g5 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 K0094e|N1{%?te}I literal 0 HcmV?d00001 diff --git a/lib/devinsy-strings-0.4.0.jar b/lib/devinsy-strings-0.4.0.jar new file mode 100644 index 0000000000000000000000000000000000000000..96018e152b2c84a1ca73a4f402337afe54b9d937 GIT binary patch literal 19983 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 HyLI<}JV*Ec literal 0 HcmV?d00001 diff --git a/lib/devinsy-unix-0.4.0-sources.zip b/lib/devinsy-unix-0.4.0-sources.zip new file mode 100644 index 0000000000000000000000000000000000000000..e041cb7c2383397d3a96ef1c672c7860517d0a14 GIT binary patch literal 26486 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 literal 0 HcmV?d00001 diff --git a/lib/devinsy-unix-0.4.0.jar b/lib/devinsy-unix-0.4.0.jar new file mode 100644 index 0000000000000000000000000000000000000000..5278dce11210abf90bee8614f555133445bc4714 GIT binary patch literal 28855 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 ga^rn8RSr4y>Fm+ltc7E*nR;@z)PdWO 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 z + * along with Devinsy-unix. If not, see */ package fr.devinsy.util; @@ -89,7 +89,7 @@ public class DataFile result = this.contentId; // - return (result); + return result; } /** @@ -102,7 +102,7 @@ public class DataFile result = this.creationDate; // - return (result); + return result; } /** @@ -115,7 +115,7 @@ public class DataFile result = this.creationUser; // - return (result); + return result; } /** @@ -128,7 +128,7 @@ public class DataFile result = this.data; // - return (result); + return result; } /** @@ -141,7 +141,7 @@ public class DataFile result = this.id; // - return (result); + return result; } /** @@ -154,7 +154,7 @@ public class DataFile result = this.name; // - return (result); + return result; } /** @@ -251,6 +251,6 @@ public class DataFile result = this.size; // - return (result); + return result; } } diff --git a/src/fr/devinsy/util/DataFiles.java b/src/fr/devinsy/util/DataFiles.java index e204708..82d0119 100755 --- a/src/fr/devinsy/util/DataFiles.java +++ b/src/fr/devinsy/util/DataFiles.java @@ -1,20 +1,20 @@ /** * Copyright (C) 2008-2010, 2013-2014 Christian Pierre MOMON * - * This file is part of Devinsy-utils. + * This file is part of Devinsy-unix. * - * Devinsy-utils is free software: you can redistribute it and/or modify + * Devinsy-unix is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * - * Devinsy-utils is distributed in the hope that it will be useful, + * Devinsy-unix is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see + * along with Devinsy-unix. If not, see */ package fr.devinsy.util; @@ -65,7 +65,7 @@ public class DataFiles extends ArrayList } // - return (result); + return result; } /** @@ -101,7 +101,7 @@ public class DataFiles extends ArrayList } // - return (result); + return result; } /** @@ -114,7 +114,7 @@ public class DataFiles extends ArrayList result = super.get(index); // - return (result); + return result; } /** @@ -157,7 +157,7 @@ public class DataFiles extends ArrayList } // - return (result); + return result; } /** diff --git a/src/fr/devinsy/util/DateHelper.java b/src/fr/devinsy/util/DateHelper.java index 3caea96..8b6e88f 100755 --- a/src/fr/devinsy/util/DateHelper.java +++ b/src/fr/devinsy/util/DateHelper.java @@ -1,20 +1,20 @@ /** * Copyright (C) 2010, 2013-2014 Christian Pierre MOMON * - * This file is part of Devinsy-utils. + * This file is part of Devinsy-unix. * - * Devinsy-utils is free software: you can redistribute it and/or modify + * Devinsy-unix is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * - * Devinsy-utils is distributed in the hope that it will be useful, + * Devinsy-unix is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see + * along with Devinsy-unix. If not, see */ package fr.devinsy.util; @@ -61,7 +61,7 @@ public class DateHelper } // - return (result); + return result; } /** @@ -81,7 +81,7 @@ public class DateHelper } // - return (result); + return result; } /** @@ -101,7 +101,7 @@ public class DateHelper } // - return (result); + return result; } /** @@ -121,7 +121,7 @@ public class DateHelper } // - return (result); + return result; } /** @@ -141,7 +141,7 @@ public class DateHelper } // - return (result); + return result; } /** @@ -161,7 +161,7 @@ public class DateHelper } // - return (result); + return result; } /** @@ -181,7 +181,7 @@ public class DateHelper } // - return (result); + return result; } /** @@ -201,7 +201,7 @@ public class DateHelper } // - return (result); + return result; } /** @@ -224,7 +224,7 @@ public class DateHelper } // - return (result); + return result; } /** @@ -256,7 +256,7 @@ public class DateHelper } // - return (result); + return result; } /** @@ -279,7 +279,7 @@ public class DateHelper } // - return (result); + return result; } /** @@ -302,7 +302,7 @@ public class DateHelper } // - return (result); + return result; } /** @@ -325,7 +325,7 @@ public class DateHelper } // - return (result); + return result; } /** @@ -345,7 +345,7 @@ public class DateHelper } // - return (result); + return result; } /** @@ -365,6 +365,6 @@ public class DateHelper } // - return (result); + return result; } } diff --git a/src/fr/devinsy/util/DateTimeHelper.java b/src/fr/devinsy/util/DateTimeHelper.java index bcd4aca..2652497 100755 --- a/src/fr/devinsy/util/DateTimeHelper.java +++ b/src/fr/devinsy/util/DateTimeHelper.java @@ -1,20 +1,20 @@ /** * Copyright (C) 2010, 2013-2014 Christian Pierre MOMON * - * This file is part of Devinsy-utils. + * This file is part of Devinsy-unix. * - * Devinsy-utils is free software: you can redistribute it and/or modify + * Devinsy-unix is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * - * Devinsy-utils is distributed in the hope that it will be useful, + * Devinsy-unix is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see + * along with Devinsy-unix. If not, see */ package fr.devinsy.util; @@ -56,7 +56,7 @@ public class DateTimeHelper } // - return (result); + return result; } /** @@ -77,7 +77,7 @@ public class DateTimeHelper } // - return (result); + return result; } /** @@ -98,7 +98,7 @@ public class DateTimeHelper } // - return (result); + return result; } /** @@ -119,6 +119,6 @@ public class DateTimeHelper } // - return (result); + return result; } } diff --git a/src/fr/devinsy/util/Digester.java b/src/fr/devinsy/util/Digester.java index 731f9db..3858940 100644 --- a/src/fr/devinsy/util/Digester.java +++ b/src/fr/devinsy/util/Digester.java @@ -1,20 +1,20 @@ /** * Copyright (C) 2006, 2010, 2013-2014 Christian Pierre MOMON * - * This file is part of Devinsy-utils. + * This file is part of Devinsy-unix. * - * Devinsy-utils is free software: you can redistribute it and/or modify + * Devinsy-unix is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * - * Devinsy-utils is distributed in the hope that it will be useful, + * Devinsy-unix is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see + * along with Devinsy-unix. If not, see */ package fr.devinsy.util; @@ -94,7 +94,7 @@ public class Digester } // - return (result); + return result; } /** @@ -123,6 +123,6 @@ public class Digester result = hashString.toString(); // - return (result); + return result; } } diff --git a/src/fr/devinsy/util/FileCopier.java b/src/fr/devinsy/util/FileCopier.java index 3c99aaf..61e877b 100644 --- a/src/fr/devinsy/util/FileCopier.java +++ b/src/fr/devinsy/util/FileCopier.java @@ -1,20 +1,20 @@ /** * Copyright (C) 2010, 2013-2014 Christian Pierre MOMON * - * This file is part of Devinsy-utils. + * This file is part of Devinsy-unix. * - * Devinsy-utils is free software: you can redistribute it and/or modify + * Devinsy-unix is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * - * Devinsy-utils is distributed in the hope that it will be useful, + * Devinsy-unix is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see + * along with Devinsy-unix. If not, see */ package fr.devinsy.util; diff --git a/src/fr/devinsy/util/FileIterator.java b/src/fr/devinsy/util/FileIterator.java index e5e7170..0a1beba 100644 --- a/src/fr/devinsy/util/FileIterator.java +++ b/src/fr/devinsy/util/FileIterator.java @@ -1,20 +1,20 @@ /** * Copyright (C) 2010, 2013-2014 Christian Pierre MOMON * - * This file is part of Devinsy-utils. + * This file is part of Devinsy-unix. * - * Devinsy-utils is free software: you can redistribute it and/or modify + * Devinsy-unix is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * - * Devinsy-utils is distributed in the hope that it will be useful, + * Devinsy-unix is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see + * along with Devinsy-unix. If not, see */ package fr.devinsy.util; @@ -118,7 +118,7 @@ public class FileIterator extends Vector implements Iterator< result = this.currentState().currentFile(); // - return (result); + return result; } /** @@ -131,7 +131,7 @@ public class FileIterator extends Vector implements Iterator< result = this.get(this.currentDepth); // - return (result); + return result; } /** @@ -151,7 +151,7 @@ public class FileIterator extends Vector implements Iterator< } // - return (result); + return result; } /** @@ -171,7 +171,7 @@ public class FileIterator extends Vector implements Iterator< } // - return (result); + return result; } /** @@ -191,7 +191,7 @@ public class FileIterator extends Vector implements Iterator< } // - return (result); + return result; } /** @@ -208,7 +208,7 @@ public class FileIterator extends Vector implements Iterator< } // - return (result); + return result; } /** @@ -240,7 +240,7 @@ public class FileIterator extends Vector implements Iterator< } // - return (result); + return result; } /** @@ -254,7 +254,7 @@ public class FileIterator extends Vector implements Iterator< result = this.currentState().hasNext(); // - return (result); + return result; } /** @@ -293,7 +293,7 @@ public class FileIterator extends Vector implements Iterator< shift(); // - return (result); + return result; } /** @@ -306,7 +306,7 @@ public class FileIterator extends Vector implements Iterator< result = this.pattern; // - return (result); + return result; } /** @@ -427,7 +427,7 @@ public class FileIterator extends Vector implements Iterator< result = "[depth=" + this.currentDepth + "][index=" + this.get(this.currentDepth).currentIndex() + "/" + this.get(this.currentDepth).files.length + "]"; // - return (result); + return result; } /** @@ -447,6 +447,6 @@ public class FileIterator extends Vector implements Iterator< } // - return (result); + return result; } } diff --git a/src/fr/devinsy/util/FileIteratorState.java b/src/fr/devinsy/util/FileIteratorState.java index 7a48705..3315be4 100644 --- a/src/fr/devinsy/util/FileIteratorState.java +++ b/src/fr/devinsy/util/FileIteratorState.java @@ -1,20 +1,20 @@ /** * Copyright (C) 2010, 2013-2014 Christian Pierre MOMON * - * This file is part of Devinsy-utils. + * This file is part of Devinsy-unix. * - * Devinsy-utils is free software: you can redistribute it and/or modify + * Devinsy-unix is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * - * Devinsy-utils is distributed in the hope that it will be useful, + * Devinsy-unix is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see + * along with Devinsy-unix. If not, see */ package fr.devinsy.util; @@ -79,7 +79,7 @@ public class FileIteratorState implements Iterator } // - return (result); + return result; } /** @@ -92,7 +92,7 @@ public class FileIteratorState implements Iterator result = this.currentIndex; // - return (result); + return result; } /** @@ -105,7 +105,7 @@ public class FileIteratorState implements Iterator result = this.files; // - return (result); + return result; } /** @@ -126,7 +126,7 @@ public class FileIteratorState implements Iterator } // - return (result); + return result; } /** @@ -141,7 +141,7 @@ public class FileIteratorState implements Iterator this.currentIndex += 1; // - return (result); + return result; } /** diff --git a/src/fr/devinsy/util/FileTools.java b/src/fr/devinsy/util/FileTools.java index 6c9eb3b..be76415 100644 --- a/src/fr/devinsy/util/FileTools.java +++ b/src/fr/devinsy/util/FileTools.java @@ -1,20 +1,20 @@ /** * Copyright (C) 2008-2015 Christian Pierre MOMON * - * This file is part of Devinsy-utils. + * This file is part of Devinsy-unix. * - * Devinsy-utils is free software: you can redistribute it and/or modify + * Devinsy-unix is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * - * Devinsy-utils is distributed in the hope that it will be useful, + * Devinsy-unix is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see + * along with Devinsy-unix. If not, see */ package fr.devinsy.util; diff --git a/src/fr/devinsy/util/Fraction.java b/src/fr/devinsy/util/Fraction.java index 1746795..3a41f63 100644 --- a/src/fr/devinsy/util/Fraction.java +++ b/src/fr/devinsy/util/Fraction.java @@ -1,20 +1,20 @@ /** * Copyright (C) 2009-2010, 2013-2014 Christian Pierre MOMON * - * This file is part of Devinsy-utils. + * This file is part of Devinsy-unix. * - * Devinsy-utils is free software: you can redistribute it and/or modify + * Devinsy-unix is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * - * Devinsy-utils is distributed in the hope that it will be useful, + * Devinsy-unix is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see + * along with Devinsy-unix. If not, see */ package fr.devinsy.util; @@ -47,7 +47,7 @@ public class Fraction result = this.denominator; // - return (result); + return result; } /** @@ -60,7 +60,7 @@ public class Fraction result = this.numerator; // - return (result); + return result; } /** @@ -73,7 +73,7 @@ public class Fraction result = percentage(this.numerator, this.denominator); // - return (result); + return result; } /** @@ -86,7 +86,7 @@ public class Fraction result = percentageFullString(this.numerator, this.denominator); // - return (result); + return result; } /** @@ -99,7 +99,7 @@ public class Fraction result = percentageString(this.numerator, this.denominator); // - return (result); + return result; } /** @@ -113,7 +113,7 @@ public class Fraction result = this.numerator + "/" + this.denominator; // - return (result); + return result; } /** @@ -133,7 +133,7 @@ public class Fraction } // - return (result); + return result; } /** @@ -146,7 +146,7 @@ public class Fraction result = percentageString(numerator, denominator); // - return (result); + return result; } /** @@ -183,6 +183,6 @@ public class Fraction } // - return (result); + return result; } } diff --git a/src/fr/devinsy/util/InternetProxyConfiguration.java b/src/fr/devinsy/util/InternetProxyConfiguration.java index ba0b859..58c7500 100755 --- a/src/fr/devinsy/util/InternetProxyConfiguration.java +++ b/src/fr/devinsy/util/InternetProxyConfiguration.java @@ -1,20 +1,20 @@ /** * Copyright (C) 2009-2010, 2013-2014 Christian Pierre MOMON * - * This file is part of Devinsy-utils. + * This file is part of Devinsy-unix. * - * Devinsy-utils is free software: you can redistribute it and/or modify + * Devinsy-unix is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * - * Devinsy-utils is distributed in the hope that it will be useful, + * Devinsy-unix is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see + * along with Devinsy-unix. If not, see */ package fr.devinsy.util; @@ -143,7 +143,7 @@ public class InternetProxyConfiguration result = this.host; // - return (result); + return result; } /** @@ -163,7 +163,7 @@ public class InternetProxyConfiguration } // - return (result); + return result; } /** @@ -176,7 +176,7 @@ public class InternetProxyConfiguration result = this.login; // - return (result); + return result; } /** @@ -189,7 +189,7 @@ public class InternetProxyConfiguration result = this.password; // - return (result); + return result; } /** @@ -202,7 +202,7 @@ public class InternetProxyConfiguration result = this.port; // - return (result); + return result; } /** @@ -236,6 +236,6 @@ public class InternetProxyConfiguration result = "(" + this.host + "," + this.port + "," + login + "," + password + ")"; // - return (result); + return result; } } diff --git a/src/fr/devinsy/util/SimpleAveragemeter.java b/src/fr/devinsy/util/SimpleAveragemeter.java index 4f5a418..073c0a2 100755 --- a/src/fr/devinsy/util/SimpleAveragemeter.java +++ b/src/fr/devinsy/util/SimpleAveragemeter.java @@ -1,20 +1,20 @@ /** * Copyright (C) 2009-2010, 2013-2014 Christian Pierre MOMON * - * This file is part of Devinsy-utils. + * This file is part of Devinsy-unix. * - * Devinsy-utils is free software: you can redistribute it and/or modify + * Devinsy-unix is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * - * Devinsy-utils is distributed in the hope that it will be useful, + * Devinsy-unix is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see + * along with Devinsy-unix. If not, see */ package fr.devinsy.util; @@ -79,7 +79,7 @@ public class SimpleAveragemeter } // - return (result); + return result; } /** @@ -92,7 +92,7 @@ public class SimpleAveragemeter result = this.cardinal; // - return (result); + return result; } /** @@ -115,7 +115,7 @@ public class SimpleAveragemeter result = Long.toString(this.average()); // - return (result); + return result; } /** @@ -128,6 +128,6 @@ public class SimpleAveragemeter result = this.average(); // - return (result); + return result; } } diff --git a/src/fr/devinsy/util/SimpleChronometer.java b/src/fr/devinsy/util/SimpleChronometer.java index 4ae2e98..84843a0 100755 --- a/src/fr/devinsy/util/SimpleChronometer.java +++ b/src/fr/devinsy/util/SimpleChronometer.java @@ -1,20 +1,20 @@ /** * Copyright (C) 2008-2010, 2013-2014 Christian Pierre MOMON * - * This file is part of Devinsy-utils. + * This file is part of Devinsy-unix. * - * Devinsy-utils is free software: you can redistribute it and/or modify + * Devinsy-unix is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * - * Devinsy-utils is distributed in the hope that it will be useful, + * Devinsy-unix is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see + * along with Devinsy-unix. If not, see */ package fr.devinsy.util; @@ -46,7 +46,7 @@ public class SimpleChronometer result = new Date().getTime() - this.firstTime; // - return (result); + return result; } /** @@ -91,7 +91,7 @@ public class SimpleChronometer } // - return (result); + return result; } /** @@ -159,6 +159,6 @@ public class SimpleChronometer } // - return (result); + return result; } } diff --git a/src/fr/devinsy/util/StacktraceWriter.java b/src/fr/devinsy/util/StacktraceWriter.java index 2cec674..c2cdb2a 100644 --- a/src/fr/devinsy/util/StacktraceWriter.java +++ b/src/fr/devinsy/util/StacktraceWriter.java @@ -1,20 +1,20 @@ /** * Copyright (C) 2010, 2013-2016 Christian Pierre MOMON * - * This file is part of Devinsy-utils. + * This file is part of Devinsy-unix. * - * Devinsy-utils is free software: you can redistribute it and/or modify + * Devinsy-unix is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * - * Devinsy-utils is distributed in the hope that it will be useful, + * Devinsy-unix is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see + * along with Devinsy-unix. If not, see */ package fr.devinsy.util; @@ -42,6 +42,6 @@ public class StacktraceWriter result = out.toString(); // - return (result); + return result; } } diff --git a/src/fr/devinsy/util/ToolBox.java b/src/fr/devinsy/util/ToolBox.java index adc4b49..b148522 100644 --- a/src/fr/devinsy/util/ToolBox.java +++ b/src/fr/devinsy/util/ToolBox.java @@ -1,20 +1,20 @@ /** * Copyright (C) 2008-2010, 2013-2014 Christian Pierre MOMON * - * This file is part of Devinsy-utils. + * This file is part of Devinsy-unix. * - * Devinsy-utils is free software: you can redistribute it and/or modify + * Devinsy-unix is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * - * Devinsy-utils is distributed in the hope that it will be useful, + * Devinsy-unix is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see + * along with Devinsy-unix. If not, see */ package fr.devinsy.util; diff --git a/src/fr/devinsy/util/cmdexec/CmdExec.java b/src/fr/devinsy/util/cmdexec/CmdExec.java deleted file mode 100644 index 8465567..0000000 --- a/src/fr/devinsy/util/cmdexec/CmdExec.java +++ /dev/null @@ -1,500 +0,0 @@ -/** - * Copyright (C) 2005-2010, 2013, 2015-2016 Christian Pierre MOMON - * - * This file is part of Devinsy-utils. - * - * Devinsy-utils is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Devinsy-utils is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see - */ -package fr.devinsy.util.cmdexec; - -import java.util.ArrayList; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import fr.devinsy.util.cmdexec.StreamGobbler.StreamWay; -import fr.devinsy.util.strings.StringListUtils; - -/** - * We must use the isOver method on Gobblers because with short tasks the - * waitFor ends before the Gobbler read. - * - * @author Christian Pierre MOMON (christian.momon@devinsy.fr) - */ -public class CmdExec -{ - private static Logger logger = LoggerFactory.getLogger(CmdExec.class); - - private int exitValue; - private String out; - private String err; - - // //////////////////////////////////////////////////////////////////// - // - // //////////////////////////////////////////////////////////////////// - - /** - * - */ - public CmdExec(final String command) - { - run(command, StreamGobbler.StreamWay.BUFFER, StreamGobbler.StreamWay.BUFFER); - } - - /** - * - */ - public CmdExec(final String... command) - { - run(command, StreamGobbler.StreamWay.BUFFER, StreamGobbler.StreamWay.BUFFER); - } - - /** - * - */ - public CmdExec(final String command, final StreamGobbler outputGobbler, final StreamGobbler errorGobbler) - { - run(command, outputGobbler, errorGobbler); - } - - /** - * - */ - public CmdExec(final String command, final StreamGobbler.StreamWay stdout, final StreamGobbler.StreamWay stderr) - { - run(command, stdout, stderr); - } - - /** - * - */ - public CmdExec(final String[] command, final StreamGobbler outputGobbler, final StreamGobbler errorGobbler) - { - run(command, outputGobbler, errorGobbler); - } - - /** - * - */ - public CmdExec(final String[] command, final StreamGobbler.StreamWay stdout, final StreamGobbler.StreamWay stderr) - { - run(command, stdout, stderr); - } - - // //////////////////////////////////////////////////////////////////// - // - // //////////////////////////////////////////////////////////////////// - - /** - * - * @return - */ - public String getErrStream() - { - String result; - - result = this.err; - - // - return (result); - } - - /** - * - * @return - */ - public int getExitValue() - { - int result; - - result = this.exitValue; - - // - return (result); - } - - /** - * - * @return - */ - public String getOutStream() - { - String result; - - result = this.out; - - // - return (result); - } - - /** - * - * @param command - * : not a shell command, it must be a executable program. - * @param outputGobbler - * @param errorGobbler - * @return - */ - public int run(final String command, final StreamGobbler outputGobbler, final StreamGobbler errorGobbler) - { - int result; - - logger.info("CmdExec(command) = [" + command + "]"); - - String[] commands = command.split("[ \t\n\r\f]"); - - result = run(commands, outputGobbler, errorGobbler); - - // - return (result); - } - - /** - * - */ - public int run(final String command, final StreamWay stdout, final StreamWay stderr) - { - int result; - - result = run(command, new StreamGobbler("OUTPUT", stdout), new StreamGobbler("ERROR", stderr)); - - // - return (result); - } - - /** - * Note: this code is inspired by an article of Michael C. Daconta published - * in JavaWorld Dec 29, 2000 (http://www.javaworld.com/article/2071275 - * /core-java/when-runtime-exec---won-t.html?page=2). - * - * @param command - * not a shell command, it must be a executable program. - * @param outputGobbler - * @param errorGobbler - * @return - */ - public int run(final String[] command, final StreamGobbler outputGobbler, final StreamGobbler errorGobbler) - { - int result; - - logger.info("CmdExec(command[]) = [" + StringListUtils.toStringSeparatedBy(command, " ") + "]"); - logger.info("CmdExec(command[]) = [" + StringListUtils.toStringWithBrackets(command) + "]"); - - try - { - Runtime rt = Runtime.getRuntime(); - - Process process = rt.exec(command); - - // Set a collector for error message. - errorGobbler.setInputStream(process.getErrorStream()); - - // Set a collector for output message. - outputGobbler.setInputStream(process.getInputStream()); - - // Collect messages. - errorGobbler.start(); - outputGobbler.start(); - - // Wait and manage the exit value. - this.exitValue = process.waitFor(); - logger.info("ExitValue: {}", this.exitValue); - - // Sometimes, process ends before Gobblers read its outpout, so we - // must wait them. - while ((!outputGobbler.isOver()) || (!errorGobbler.isOver())) - { - Thread.sleep(1); - } - - // Store messages. - this.out = outputGobbler.getStream(); - this.err = errorGobbler.getStream(); - - result = this.exitValue; - } - catch (Exception exception) - { - this.err = exception.getMessage(); - this.exitValue = -77; - result = this.exitValue; - logger.error(exception.getMessage(), exception); - } - - // - return (result); - } - - /** - * - * @param command - * @param stdout - * @param stderr - * @return - */ - public int run(final String[] command, final StreamGobbler.StreamWay stdout, final StreamGobbler.StreamWay stderr) - { - int result; - - result = run(command, new StreamGobbler("OUTPUT", stdout), new StreamGobbler("ERROR", stderr)); - - // - return (result); - } - - /** - * - * @param commands - * @return - * @throws CmdExecException - */ - public static String multirun(final String... commands) throws CmdExecException - { - String result; - - ArrayList stdouts = new ArrayList(commands.length); - - boolean ended = false; - int commandCounter = 0; - while (!ended) - { - if (commandCounter < commands.length) - { - String command = commands[commandCounter]; - - if ((command == null) || (command.length() == 0)) - { - result = null; - commandCounter += 1; - } - else - { - stdouts.add(CmdExec.run(command)); - commandCounter += 1; - } - } - else - { - ended = true; - result = null; - } - } - - // - int resultLength = 0; - for (String stdout : stdouts) - { - resultLength += stdout.length(); - } - StringBuffer buffer = new StringBuffer(resultLength); - for (String stdout : stdouts) - { - buffer.append(stdout); - } - result = buffer.toString(); - - // - return (result); - } - - // //////////////////////////////////////////////////////////////////// - // - // //////////////////////////////////////////////////////////////////// - /** - * @throws CmdExecException - */ - public static String run(final String command) throws CmdExecException - { - String result; - - result = CmdExec.run(command.split("[ \t\n\r\f]")); - - // - return (result); - } - - /** - * @throws CmdExecException - * @throws Exception - */ - public static String run(final String... command) throws CmdExecException - { - String result; - - if ((command == null) || (command.length == 0)) - { - throw new IllegalArgumentException("Empty command"); - } - else - { - CmdExec cmd = new CmdExec(command, StreamGobbler.StreamWay.BUFFER, StreamGobbler.StreamWay.BUFFER); - - if (cmd.getExitValue() == 0) - { - result = cmd.getOutStream(); - } - else - { - logger.error("Command=\"" + StringListUtils.toStringWithBrackets(command)); - logger.error("Command=\"[" + StringListUtils.toString(command) + "]\n out => [" + cmd.getOutStream() + "]\n " + "err => (" + cmd.getErrStream().length() + ")[" + cmd.getErrStream() - + "]"); - throw new CmdExecException(cmd.getErrStream()); - } - } - - // - return (result); - } - - /** - * Examples: - * - * run("sudo", "setfacl", "-m", "g:cpm:rwX", "/tmp/toto"); - * - * run("sudo", "setfacl", "-R", "-m", "g:cpm:rwX", "/tmp/toto"); - * - * @throws CmdExecException - */ - public static String run(final String program1, final String program2, final String[] args, final int min, final int max) throws CmdExecException - { - String result; - - // - boolean nullArg = false; - boolean ended = false; - int argumentIndex = 0; - while (!ended) - { - if (argumentIndex >= args.length) - { - ended = true; - nullArg = false; - } - else - { - if (args[argumentIndex] == null) - { - ended = true; - nullArg = true; - } - else - { - argumentIndex += 1; - } - } - } - - // - if (program1 == null) - { - throw new IllegalArgumentException("Null program parameter 1 detected: [" + program1 + "]."); - } - else if (program2 == null) - { - throw new IllegalArgumentException("Null program parameter 2 detected: [" + program2 + "]."); - } - else if (nullArg) - { - throw new IllegalArgumentException("Null parameter detected in position " + argumentIndex + " for " + StringListUtils.toStringWithBrackets(args) + "."); - } - else if ((args.length < min) || (args.length > max)) - { - throw new IllegalArgumentException("Bad number of parameters: " + args.length + " for " + StringListUtils.toStringWithBrackets(args) + "."); - } - else - { - // - String[] command = new String[args.length + 2]; - command[0] = program1; - command[1] = program2; - for (argumentIndex = 0; argumentIndex < args.length; argumentIndex++) - { - command[argumentIndex + 2] = args[argumentIndex]; - } - - result = CmdExec.run(command); - } - - // - return (result); - } - - /** - * Examples: - * - * run("setfacl", "-m", "g:cpm:rwX", "/tmp/toto"); - * - * run("setfacl", "-R", "-m", "g:cpm:rwX", "/tmp/toto"); - * - * @throws CmdExecException - */ - public static String run(final String program, final String[] args, final int min, final int max) throws CmdExecException - { - String result; - - // - boolean nullArg = false; - boolean ended = false; - int argumentCounter = 0; - while (!ended) - { - if (argumentCounter >= args.length) - { - ended = true; - nullArg = false; - } - else - { - if (args[argumentCounter] == null) - { - ended = true; - nullArg = true; - } - else - { - argumentCounter += 1; - } - } - } - - // - if (program == null) - { - throw new IllegalArgumentException("Null program parameter detected: [" + program + "]."); - } - else if (nullArg) - { - throw new IllegalArgumentException("Null parameter detected in position " + argumentCounter + " for " + StringListUtils.toStringWithBrackets(args) + "."); - } - else if ((args.length < min) || (args.length > max)) - { - throw new IllegalArgumentException("Bad number of parameters: " + args.length + " for " + StringListUtils.toStringWithBrackets(args) + "."); - } - else - { - // - String[] command = new String[args.length + 1]; - command[0] = program; - for (argumentCounter = 0; argumentCounter < args.length; argumentCounter++) - { - command[argumentCounter + 1] = args[argumentCounter]; - } - - result = CmdExec.run(command); - } - - // - return (result); - } -} diff --git a/src/fr/devinsy/util/cmdexec/CmdExecException.java b/src/fr/devinsy/util/cmdexec/CmdExecException.java deleted file mode 100644 index e50dee6..0000000 --- a/src/fr/devinsy/util/cmdexec/CmdExecException.java +++ /dev/null @@ -1,65 +0,0 @@ -/** - * Copyright (C) 2016 Christian Pierre MOMON - * - * This file is part of Devinsy-utils. - * - * Devinsy-utils is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Devinsy-utils is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see - */ -package fr.devinsy.util.cmdexec; - -/** - * - * @author Christian Pierre MOMON (christian.momon@devinsy.fr) - * - */ -public class CmdExecException extends Exception -{ - private static final long serialVersionUID = 3264886426311529668L; - - /** - * - */ - public CmdExecException() - { - super(); - } - - /** - * - * @param message - */ - public CmdExecException(final String message) - { - super(message); - } - - /** - * - * @param message - * @param cause - */ - public CmdExecException(final String message, final Throwable cause) - { - super(message, cause); - } - - /** - * - * @param cause - */ - public CmdExecException(final Throwable cause) - { - super(cause); - } -} diff --git a/src/fr/devinsy/util/cmdexec/StreamGobbler.java b/src/fr/devinsy/util/cmdexec/StreamGobbler.java deleted file mode 100644 index a4739ae..0000000 --- a/src/fr/devinsy/util/cmdexec/StreamGobbler.java +++ /dev/null @@ -1,196 +0,0 @@ -/** - * Copyright (C) 2005-2008, 2010, 2013, 2016 Christian Pierre MOMON - * - * This file is part of Devinsy-utils. - * - * Devinsy-utils is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Devinsy-utils is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see - */ -package fr.devinsy.util.cmdexec; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * @author Christian Pierre MOMON (christian.momon@devinsy.fr) - */ -public class StreamGobbler extends Thread -{ - public enum StreamWay - { - NONE, - PRINT, - BUFFER - } - - private static final Logger logger = LoggerFactory.getLogger(CmdExec.class); - - private InputStream is; - private String name; - private StreamWay streamWay; - private StringBuffer stream; - - // Important if the caller wants have complete stream in case of very short - // command. - private boolean isOverStatus; - - /** - * - */ - StreamGobbler() - { - this.is = null; - this.name = ""; - this.streamWay = StreamWay.NONE; - this.stream = new StringBuffer(); - this.isOverStatus = false; - } - - /** - * - * @param is - * @param name - */ - StreamGobbler(final InputStream is, final String name) - { - this.is = is; - this.name = name; - this.streamWay = StreamWay.NONE; - this.stream = new StringBuffer(); - this.isOverStatus = false; - } - - /** - * - * @param is - * @param name - * @param streamWay - */ - StreamGobbler(final InputStream is, final String name, final StreamWay streamWay) - { - this.is = is; - this.name = name; - this.streamWay = streamWay; - this.stream = new StringBuffer(); - this.isOverStatus = false; - } - - /** - * - * @param type - * @param streamWay - */ - StreamGobbler(final String type, final StreamWay streamWay) - { - this.name = type; - this.streamWay = streamWay; - this.stream = new StringBuffer(); - this.isOverStatus = false; - } - - /** - * - * @return - */ - public String getStream() - { - String result; - - if (this.stream != null) - { - result = this.stream.toString(); - } - else - { - result = null; - } - - // - return (result); - } - - /** - * - * @return - */ - public boolean isOver() - { - boolean result; - - result = this.isOverStatus; - - // - return (result); - } - - /** - * - */ - @Override - public void run() - { - try - { - InputStreamReader isr = new InputStreamReader(this.is); - BufferedReader buffer = new BufferedReader(isr); - String line = null; - switch (this.streamWay) - { - case NONE: - while ((line = buffer.readLine()) != null) - { - ; - } - break; - - case PRINT: - while ((line = buffer.readLine()) != null) - { - System.out.println(this.name + ">" + line); - } - break; - - case BUFFER: - while ((line = buffer.readLine()) != null) - { - this.stream.append(line + "\n"); - } - break; - - default: - logger.warn("unknow way for stream"); - } - } - catch (IOException exception) - { - logger.error(exception.getMessage(), exception); - } - - this.isOverStatus = true; - } - - /** - * - * @param is - */ - public void setInputStream(final InputStream is) - { - this.is = is; - } -} diff --git a/src/fr/devinsy/util/rss/RSSCache.java b/src/fr/devinsy/util/rss/RSSCache.java deleted file mode 100644 index 939398e..0000000 --- a/src/fr/devinsy/util/rss/RSSCache.java +++ /dev/null @@ -1,214 +0,0 @@ -/** - * Copyright (C) 2013-2014 Christian Pierre MOMON - * - * This file is part of Devinsy-utils. - * - * Devinsy-utils is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Devinsy-utils is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see - */ -package fr.devinsy.util.rss; - -import java.util.HashMap; -import java.util.Locale; - -import fr.devinsy.util.strings.StringList; - -/** - * - * @author Christian Pierre MOMON (christian.momon@devinsy.fr) - */ -public class RSSCache -{ - private static RSSCache instance = new RSSCache(); - private HashMap cache; - - /** - * - */ - private RSSCache() - { - this.cache = new HashMap(); - } - - /** - * - * @param key - * @param locale - * @return - */ - public String get(final String name) - { - return get(name, Locale.ROOT); - } - - /** - * - * @param name - * @param locale - * @return - */ - public String get(final String name, final Locale locale) - { - String result; - - if (name == null) - { - throw new NullPointerException("name is null."); - } - else if (locale == null) - { - result = get(name, Locale.ROOT); - } - else - { - result = this.cache.get(key(name, locale)); - - if (result == null) - { - result = this.cache.get(name); - } - } - - return result; - } - - /** - * - * @param name - * @param locale - * @return - */ - private String key(final String name, final Locale locale) - { - String result; - - if (locale.getLanguage().length() == 0) - { - result = name; - } - else - { - result = name + "_" + locale.getLanguage(); - } - - // - return result; - } - - /** - * - * @param key - * @param locale - * @param rss - */ - public void put(final String name, final Locale locale, final String rss) - { - if (name == null) - { - throw new NullPointerException("name is null."); - } - else if (locale == null) - { - put(name, Locale.ROOT, rss); - } - else - { - this.cache.put(key(name, locale), rss); - } - } - - /** - * - * @param name - * @param locale - * @param rss - */ - public void put(final String name, final String rss) - { - put(name, Locale.ROOT, rss); - } - - /** - * - * @param name - */ - public void remove(final String name) - { - remove(name, Locale.ROOT); - } - - /** - * - * @param name - */ - public void remove(final String name, final Locale locale) - { - if (name == null) - { - throw new NullPointerException("key is null."); - } - else - { - this.cache.remove(name + "-" + locale.getLanguage()); - } - } - - /** - * - * @param key - */ - public void setOudated(final String name) - { - for (String subkey : subkeys(name)) - { - if (subkey.startsWith(name)) - { - this.cache.remove(subkey); - } - } - } - - /** - * - * @param key - */ - public StringList subkeys(final String name) - { - StringList result; - - // - result = new StringList(); - - // - for (String key : this.cache.keySet()) - { - if (key.startsWith(name)) - { - result.add(key); - } - } - - // - return result; - } - - /** - * - * @return - */ - public static RSSCache instance() - { - return instance; - } - -} diff --git a/src/fr/devinsy/util/rss/RSSElement.java b/src/fr/devinsy/util/rss/RSSElement.java deleted file mode 100644 index 52e07d8..0000000 --- a/src/fr/devinsy/util/rss/RSSElement.java +++ /dev/null @@ -1,154 +0,0 @@ -/** - * Copyright (C) 2013-2014 Christian Pierre MOMON - * - * This file is part of Devinsy-utils. - * - * Devinsy-utils is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Devinsy-utils is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see - */ -package fr.devinsy.util.rss; - -import org.joda.time.DateTime; - -/** - * - * @author Christian Pierre MOMON (christian.momon@devinsy.fr) - */ -public class RSSElement -{ - public static final String DATE_PATTERN = "dd MMM YYYY hh:mm:ss Z"; - private String name; - private String value; - private String[] attributes; - - /** - * - * @param name - * @param value - */ - public RSSElement(final String name, final DateTime value) - { - setName(name); - if (value == null) - { - this.value = null; - } - else - { - this.value = value.toString(DATE_PATTERN); - } - this.attributes = null; - } - - /** - * - * @param name - * @param value - */ - public RSSElement(final String name, final long value) - { - setName(name); - this.value = String.valueOf(value); - this.attributes = null; - } - - /** - * - * @param name - * @param value - */ - public RSSElement(final String name, final long value, final String... attributes) - { - setName(name); - this.value = String.valueOf(value); - this.attributes = attributes; - } - - /** - * - * @param name - * @param value - */ - public RSSElement(final String name, final String value) - { - setName(name); - this.value = value; - this.attributes = null; - } - - /** - * - * @param name - * @param value - */ - public RSSElement(final String name, final String value, final String... attributes) - { - setName(name); - this.value = value; - this.attributes = attributes; - } - - public String[] getAttributes() - { - return this.attributes; - } - - /** - * - * @return - */ - public String getName() - { - return this.name; - } - - /** - * - * @return - */ - public String getValue() - { - return this.value; - } - - public void setAttributes(final String[] attributes) - { - this.attributes = attributes; - } - - /** - * - * @param name - */ - public void setName(final String name) - { - if (name == null) - { - throw new NullPointerException("name is null"); - } - else - { - this.name = name; - } - } - - /** - * - * @param value - */ - public void setValue(final String value) - { - this.value = value; - } - -} diff --git a/src/fr/devinsy/util/rss/RSSWriter.java b/src/fr/devinsy/util/rss/RSSWriter.java deleted file mode 100644 index 31610c7..0000000 --- a/src/fr/devinsy/util/rss/RSSWriter.java +++ /dev/null @@ -1,172 +0,0 @@ -/** - * Copyright (C) 2013-2014 Christian Pierre MOMON - * - * This file is part of Devinsy-utils. - * - * Devinsy-utils is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Devinsy-utils is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see - */ -package fr.devinsy.util.rss; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.OutputStream; -import java.io.UnsupportedEncodingException; -import java.io.Writer; - -import fr.devinsy.util.xml.XMLWriter; - -/** - * - * @author Christian Pierre MOMON (christian.momon@devinsy.fr) - */ -public class RSSWriter -{ - private XMLWriter out; - - /** - * - * @param file - * @throws FileNotFoundException - * @throws UnsupportedEncodingException - */ - public RSSWriter(final File file) throws UnsupportedEncodingException, FileNotFoundException - { - this.out = new XMLWriter(file); - writeRSSHeader(); - } - - /** - * - * @param target - * @throws UnsupportedEncodingException - */ - public RSSWriter(final OutputStream target) throws UnsupportedEncodingException - { - this.out = new XMLWriter(target); - writeRSSHeader(); - } - - /** - * - * @param target - * @throws UnsupportedEncodingException - */ - public RSSWriter(final Writer target) throws UnsupportedEncodingException - { - this.out = new XMLWriter(target); - writeRSSHeader(); - } - - /** - * - */ - public void close() throws IOException - { - if (this.out != null) - { - this.out.writeEndTag("channel"); - this.out.writeEndTag("rss"); - this.out.close(); - } - } - - /** - * - */ - public void flush() throws IOException - { - if (this.out != null) - { - this.out.flush(); - } - } - - /** - * - */ - public void writeChannel(final String title, final String link, final String description, final RSSElement... elements) - { - // - this.out.writeStartTag("channel"); - - // - this.out.writeTag("title", title); - this.out.writeTag("link", link); - this.out.writeTag("description", description); - - // - if ((elements != null) && (elements.length > 0)) - { - for (RSSElement element : elements) - { - this.out.writeTag(element.getName(), element.getValue(), element.getAttributes()); - } - } - } - - /** - * - * @param comment - */ - public void writeComment(final String comment) - { - this.out.writeComment(comment); - } - - /** - * - */ - public void writeItem(final String title, final String link, final String description, final RSSElement... elements) - { - // - this.out.writeStartTag("item"); - - // - this.out.writeTag("title", title); - if (link != null) - { - this.out.writeTag("link", link); - } - if (description == null) - { - this.out.writeTag("description", "n/a"); - } - else - { - this.out.writeTag("description", description); - } - - // - if ((elements != null) && (elements.length > 0)) - { - for (RSSElement element : elements) - { - this.out.writeTag(element.getName(), element.getValue(), element.getAttributes()); - } - } - - // - this.out.writeEndTag("item"); - } - - /** - * - */ - private void writeRSSHeader() - { - this.out.writeXMLHeader(); - this.out.writeStartTag("rss", "version", "2.0"); - } -} diff --git a/src/fr/devinsy/util/strings/StringLengthComparator.java b/src/fr/devinsy/util/strings/StringLengthComparator.java deleted file mode 100644 index adac2f1..0000000 --- a/src/fr/devinsy/util/strings/StringLengthComparator.java +++ /dev/null @@ -1,146 +0,0 @@ -/** - * Copyright (C) 2013-2017 Christian Pierre MOMON - * - * This file is part of Devinsy-utils. - * - * Devinsy-utils is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Devinsy-utils is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see - */ -package fr.devinsy.util.strings; - -import java.util.Comparator; - -/** - * - */ -public class StringLengthComparator implements Comparator -{ - private static StringLengthComparator instance; - - /** - * - */ - @Override - public int compare(final String alpha, final String bravo) - { - int result; - - // - Integer alphaValue; - if (alpha == null) - { - // - alphaValue = null; - - } - else - { - // - alphaValue = alpha.length(); - } - - // - Integer bravoValue; - if (bravo == null) - { - // - bravoValue = null; - - } - else - { - // - bravoValue = bravo.length(); - } - - // - result = compare(alphaValue, bravoValue); - - // - return result; - } - - /** - * This method compares two nullable string values. - * - * The comparison manages the local language alphabet order. - * - *

-	 * compare(null, null)   = 0
-	 * compare(null, bravo)  < 0
-	 * compare(alpha, null)  > 0
-	 * compare(alpha, bravo) = alpha.compareTo(bravo)
-	 * 
- * - * @param alpha - * one of the value. - * - * @param bravo - * the other value. - * - * @return zero or a positive value or a negative value. - * - */ - public static int compare(final Integer alpha, final Integer bravo) - { - int result; - - // - if ((alpha == null) && (bravo == null)) - { - // - result = 0; - - } - else if (alpha == null) - { - // - result = -1; - - } - else if (bravo == null) - { - // - result = +1; - - } - else - { - // - result = alpha.compareTo(bravo); - } - - // - return result; - } - - /** - * - * @return - */ - public static StringLengthComparator instance() - { - StringLengthComparator result; - - if (instance == null) - { - instance = new StringLengthComparator(); - } - - result = instance; - - // - return result; - } - -} diff --git a/src/fr/devinsy/util/strings/StringList.java b/src/fr/devinsy/util/strings/StringList.java deleted file mode 100644 index 873f541..0000000 --- a/src/fr/devinsy/util/strings/StringList.java +++ /dev/null @@ -1,1584 +0,0 @@ -/** - * Copyright (C) 2008-2010, 2013-2015 Christian Pierre MOMON - * - * This file is part of Devinsy-utils. - * - * Devinsy-utils is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Devinsy-utils is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see - */ -package fr.devinsy.util.strings; - -import java.io.IOException; -import java.text.Collator; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.Iterator; - -import org.apache.commons.lang3.StringUtils; - -/** - * This class is a collection of String objects with specific methods. It makes - * possible to build a string without any copy. The goal is to optimize the - * building of strings where they are lot of concatenation action. - * - */ -public class StringList extends ArrayList implements CharSequence -{ - private static final long serialVersionUID = -1154185934830213732L; - - public static final String LINE_SEPARATOR = "\n"; - - /** - * Constructs an empty list with an initial capacity of ten (see ArrayList - * constructor). - */ - public StringList() - { - super(); - } - - /** - * Constructs a list of string of the specified collection, in the order - * they are returned by the collection's iterator. - * - * @param source - */ - public StringList(final Collection source) - { - super(); - - if (source != null) - { - // - ensureCapacity(source.size()); - - // - for (String string : source) - { - this.add(string); - } - } - } - - /** - * Constructs an empty list with the specified initial capacity. - * - * @param initialCapacity - */ - public StringList(final int initialCapacity) - { - super(initialCapacity); - } - - /** - * Constructs a list of string from a string array. - * - * @param source - */ - public StringList(final String... source) - { - super(); - - if (source != null) - { - // - ensureCapacity(source.length); - - // - for (String string : source) - { - this.add(string); - } - } - } - - /** - * Appends the string representation of the char argument to this string - * list. - * - * @param character - * @return - */ - public StringList append(final char character) - { - StringList result; - - this.add(String.valueOf(character)); - - result = this; - - // - return (result); - } - - /** - * Appends the string of the specified collection, in the order they are - * returned by the collection's iterator. - * - * @param strings - * @return - */ - public StringList append(final Collection strings) - { - StringList result; - - if (strings != null) - { - for (String string : strings) - { - this.append(string); - } - } - - result = this; - - // - return (result); - } - - /** - * Appends the string representation of the double argument to this string - * list. - * - * @param value - * @return - */ - public StringList append(final double value) - { - StringList result; - - result = this.append(String.valueOf(value)); - - // - return (result); - } - - /** - * Appends the string representation of the int argument to this string - * list. - * - * @param value - * @return - */ - public StringList append(final int value) - { - StringList result; - - result = this.append(String.valueOf(value)); - - // - return (result); - } - - /** - * Appends the string representation of the long argument to this string - * list. - * - * @param value - * @return - */ - public StringList append(final long value) - { - StringList result; - - result = this.append(String.valueOf(value)); - - // - return (result); - } - - /** - * Appends the string representation of the int argument to this string - * list. - * - * @param value - * @return - */ - public StringList append(final Object value) - { - StringList result; - - if (value != null) - { - this.append(value.toString()); - } - - result = this; - - // - return (result); - } - - /** - * Appends the string representation of the long argument to this string - * list. - * - * @param value - * @return - */ - public StringList append(final short value) - { - StringList result; - - result = this.append(String.valueOf(value)); - - // - return (result); - } - - /** - * Appends the string argument to this string list. - * - * Check null parameter before add. - * - * @param string - * @return - */ - public StringList append(final String string) - { - StringList result; - - if (string != null) - { - this.add(string); - } - - result = this; - - // - return (result); - } - - /** - * Appends the string of the array argument to this string list. - * - * @param strings - * @return - */ - public StringList append(final String... strings) - { - StringList result; - - if (strings != null) - { - for (String string : strings) - { - this.add(string); - } - } - - result = this; - - // - return (result); - } - - /** - * Appends a break line to this string list. - * - * @return - */ - public StringList appendln() - { - StringList result; - - this.add(LINE_SEPARATOR); - - result = this; - - // - return (result); - } - - /** - * Appends the string representation of the char argument to this string - * list, then append a break line too. - * - * @param character - * @return - */ - public StringList appendln(final char character) - { - StringList result; - - result = this.append(character).appendln(); - - // - return (result); - } - - /** - * - * @param string - * @return - */ - public StringList appendln(final Collection string) - { - StringList result; - - result = this.append(string).appendln(); - - // - return (result); - } - - /** - * - * @param value - * @return - */ - public StringList appendln(final double value) - { - StringList result; - - result = this.append(value).appendln(); - - // - return (result); - } - - /** - * - * @param value - * @return - */ - public StringList appendln(final int value) - { - StringList result; - - result = this.append(value).appendln(); - - // - return (result); - } - - /** - * - * @param value - * @return - */ - public StringList appendln(final long value) - { - StringList result; - - result = this.append(value).appendln(); - - // - return (result); - } - - /** - * - * @param value - * @return - */ - public StringList appendln(final Object value) - { - StringList result; - - result = this.append(value).appendln(); - - // - return (result); - } - - /** - * - * @param value - * @return - */ - public StringList appendln(final short value) - { - StringList result; - - result = this.append(value).appendln(); - - // - return (result); - } - - /** - * - * @param string - * @return - */ - public StringList appendln(final String string) - { - StringList result; - - result = this.append(string).appendln(); - - // - return (result); - } - - /** - * - * @param strings - * @return - */ - public StringList appendln(final String... strings) - { - StringList result; - - result = this.append(strings).appendln(); - - // - return (result); - } - - /** - * - */ - @Override - public char charAt(final int index) - { - char result; - - // - StringListCharPosition position = indexOf(index); - - // - result = get(position.getStringIndex()).charAt(position.getLocalCharIndex()); - - // - return result; - } - - /** - * - * @param position - * @return - */ - public char charAt(final StringListCharPosition position) - { - char result; - - // - result = get(position.getStringIndex()).charAt(position.getLocalCharIndex()); - - // - return result; - } - - /** - * Deep copy and shallow copy have no sense about a list of immutable - * objects. - * - * @return - */ - @Override - public StringList clone() - { - StringList result; - - result = new StringList(size()); - - for (String string : this) - { - result.add(string); - } - - // - return result; - } - - /** - * - * @param source - * @return - */ - public boolean containsAny(final Collection target) - { - boolean result; - - if (target == null) - { - result = false; - } - else - { - boolean ended = false; - Iterator iterator = target.iterator(); - result = false; - while (!ended) - { - if (iterator.hasNext()) - { - String current = iterator.next(); - - if (this.contains(current)) - { - ended = true; - result = true; - } - } - else - { - ended = true; - result = false; - } - } - } - - // - return result; - } - - /** - * - * @param source - * @return - */ - public boolean containsAny(final String... target) - { - boolean result; - - if (target == null) - { - result = false; - } - else - { - boolean ended = false; - int index = 0; - result = false; - while (!ended) - { - if (index < target.length) - { - String current = target[index]; - - if (this.contains(current)) - { - ended = true; - result = true; - } - else - { - index += 1; - } - } - else - { - ended = true; - result = false; - } - } - } - - // - return result; - } - - /** - * - * @return - */ - public boolean containsBlank() - { - boolean result; - - boolean ended = false; - Iterator iterator = iterator(); - result = false; - while (!ended) - { - if (iterator.hasNext()) - { - String line = iterator.next(); - - if (StringUtils.isBlank(line)) - { - ended = true; - result = true; - } - } - else - { - ended = true; - result = false; - } - } - - // - return result; - } - - /** - * - * @return - */ - public boolean containsEmpty() - { - boolean result; - - boolean ended = false; - Iterator iterator = iterator(); - result = false; - while (!ended) - { - if (iterator.hasNext()) - { - String line = iterator.next(); - - if (StringUtils.isEmpty(line)) - { - ended = true; - result = true; - } - } - else - { - ended = true; - result = false; - } - } - - // - return result; - } - - /** - * - * @return - */ - public boolean containsNull() - { - boolean result; - - boolean ended = false; - Iterator iterator = iterator(); - result = false; - while (!ended) - { - if (iterator.hasNext()) - { - String line = iterator.next(); - - if (line == null) - { - ended = true; - result = true; - } - } - else - { - ended = true; - result = false; - } - } - - // - return result; - } - - /** - * - * @param id - * @return - */ - public String getByIndex(final int id) - { - String result; - - result = this.get(id); - - // - return (result); - } - - /** - * - * @return - */ - public String getFirst() - { - String result; - - if (this.size() == 0) - { - result = null; - } - else - { - result = get(0); - } - - // - return (result); - } - - /** - * - * @return - */ - public String getLast() - { - String result; - - if (this.size() == 0) - { - result = null; - } - else - { - result = get(this.size() - 1); - } - - // - return (result); - } - - /** - * - * @return - */ - public String getLongestBytesLine() - { - String result; - - if (isEmpty()) - { - result = null; - } - else - { - int max = 0; - result = ""; - for (String line : this) - { - if (line.getBytes().length > max) - { - max = line.length(); - result = line; - } - } - } - - // - return result; - } - - /** - * - * @return - */ - public String getLongestLine() - { - String result; - - if (isEmpty()) - { - result = null; - } - else - { - int max = 0; - result = ""; - for (String line : this) - { - if (line.length() > max) - { - max = line.length(); - result = line; - } - } - } - - // - return result; - } - - /** - * - * @return - */ - public StringList getNotBlank() - { - StringList result; - - result = new StringList(); - - for (String line : this) - { - if (StringUtils.isNotBlank(line)) - { - result.add(line); - } - } - - // - return (result); - } - - /** - * - * @return - */ - public StringList getNotEmpty() - { - StringList result; - - result = new StringList(); - - for (String line : this) - { - if (StringUtils.isNotEmpty(line)) - { - result.add(line); - } - } - - // - return (result); - } - - /** - * - * @return - */ - public StringList getNotNull() - { - StringList result; - - result = new StringList(); - - for (String line : this) - { - if (line != null) - { - result.add(line); - } - } - - // - return (result); - } - - /** - * - * @return - */ - public String getShortestBytesLine() - { - String result; - - if (isEmpty()) - { - result = null; - } - else - { - int min = Integer.MAX_VALUE; - result = null; - for (String line : this) - { - if (line.getBytes().length < min) - { - min = line.length(); - result = line; - } - } - } - - // - return result; - } - - /** - * - * @return - */ - public String getShortestLine() - { - String result; - - if (isEmpty()) - { - result = null; - } - else - { - int min = Integer.MAX_VALUE; - result = null; - for (String line : this) - { - if (line.length() < min) - { - min = line.length(); - result = line; - } - } - } - - // - return result; - } - - /** - * - * @param index - * @return - */ - public StringListCharPosition indexOf(final int index) - { - StringListCharPosition result; - - if ((index < 0) || (index >= length())) - { - throw new StringIndexOutOfBoundsException(index); - } - else - { - boolean ended = false; - int stringIndex = 0; - int currentLength = 0; - result = null; - while (!ended) - { - if (index < currentLength + get(stringIndex).length()) - { - ended = true; - result = new StringListCharPosition(index, stringIndex, index - currentLength); - } - else - { - stringIndex += 1; - currentLength += get(stringIndex).length(); - } - } - - } - - // - return result; - } - - /** - * - * @param startIndex - * @return the index of the next line not null, -1 otherwise. - */ - public int indexOfNextLineNotNull(final int startIndex) - { - int result; - - boolean ended = false; - int currentIndex = startIndex; - result = -1; - while (!ended) - { - if (currentIndex >= this.size()) - { - ended = true; - result = -1; - } - else - { - if (this.get(currentIndex) == null) - { - ended = true; - result = currentIndex; - } - else - { - currentIndex += 1; - } - } - } - - // - return result; - } - - /** - * - * @param position - * @return - */ - public boolean isOutOfBounds(final StringListCharPosition position) - { - boolean result; - - if (position == null) - { - result = true; - } - else - { - if (isOutOfList(position)) - { - result = true; - } - else if (isOutOfLine(position)) - { - result = true; - } - else - { - result = false; - } - } - - // - return result; - } - - /** - * - * @param position - * @return - */ - public boolean isOutOfLine(final StringListCharPosition position) - { - boolean result; - - if (position == null) - { - result = true; - } - else - { - if (position.getLocalCharIndex() >= this.get(position.getStringIndex()).length()) - { - result = true; - } - else - { - result = false; - } - } - - // - return result; - } - - /** - * - * @param position - * @return - */ - public boolean isOutOfList(final StringListCharPosition position) - { - boolean result; - - if (position == null) - { - result = true; - } - else - { - if (position.getStringIndex() >= this.size()) - { - result = true; - } - else - { - result = false; - } - } - - // - return result; - } - - /** - * - */ - public Iterator iteratorOfChar() - { - Iterator result; - - result = new StringListCharIterator(this); - - // - return result; - } - - /** - * Returns the length of the string list concatenation. Null strings are - * ignored. - */ - @Override - public int length() - { - int result = 0; - - for (String string : this) - { - if (string != null) - { - result += string.length(); - } - } - - // - return (result); - } - - /** - * Merge all strings of the list into in single string. At the end of - * operation, the new string is the first of the list and the size list is - * 1. - * - * @return - */ - public StringList merge() - { - StringList result; - - String merge = this.toString(); - - clear(); - add(merge); - - result = this; - - // - return result; - } - - /** - * Removes the last element of the list. - * - * @return This list. - */ - public StringList removeLast() - { - StringList result; - - if (this.size() > 0) - { - this.remove(this.size() - 1); - } - - result = this; - - // - return (result); - } - - /** - * Extends the list copying the last element a number of time. - * - * @param count - * The number of time to copy the last element. - * - * @return This list. - */ - public StringList repeatLast(final int count) - { - StringList result; - - // - if ((this.size() != 0) && (count > 0)) - { - // - this.ensureCapacity(this.size() + count); - - // - String last = getLast(); - - // - for (int index = 0; index < count; index++) - { - this.append(last); - } - } - - // - result = this; - - // - return (result); - } - - /** - * Sorts this list. - * - * @return This List. - */ - public StringList reverse() - { - StringList result; - - Collections.reverse(this); - - // - result = this; - - // - return result; - } - - /** - * Sorts this list. - * - * @return This List. - */ - public StringList sort() - { - StringList result; - - Collections.sort(this, Collator.getInstance()); - - // - result = this; - - // - return result; - } - - /** - * Sorts this list. - * - * @return This List. - */ - public StringList sort(final Comparator comparator) - { - StringList result; - - Collections.sort(this, comparator); - - // - result = this; - - // - return result; - } - - /** - * Sorts this list. - * - * @return This List. - */ - public StringList sortByLength() - { - StringList result; - - Collections.sort(this, StringLengthComparator.instance()); - - // - result = this; - - // - return result; - } - - /** - * {@inheritDoc} - */ - @Override - public CharSequence subSequence(final int start, final int end) - { - StringList result; - - result = substring(start, end); - - // - return result; - } - - /** - * Extracts a substring from this list. - * - * @param start - * The first character of the substring. - * @param end - * The last character of the substring. - * - * @return The sublist targeted. - */ - public StringList substring(final int beginIndex, final int endIndex) - { - StringList result; - - if (beginIndex < 0) - { - throw new StringIndexOutOfBoundsException(beginIndex); - } - else if (endIndex > length()) - { - throw new StringIndexOutOfBoundsException(endIndex); - } - else if (beginIndex > endIndex) - { - throw new StringIndexOutOfBoundsException(endIndex - beginIndex); - } - else if (beginIndex == endIndex) - { - result = new StringList(); - } - else - { - // - result = new StringList(); - - // - StringListCharPosition startPosition = indexOf(beginIndex); - StringListCharPosition endPosition = indexOf(endIndex); - - // - if (startPosition.getStringIndex() == endPosition.getStringIndex()) - { - String source = get(startPosition.getStringIndex()); - String target = source.substring(startPosition.getLocalCharIndex(), endPosition.getLocalCharIndex()); - result.append(target); - } - else - { - // - { - String source = get(startPosition.getStringIndex()); - String target = source.substring(startPosition.getLocalCharIndex()); - result.append(target); - } - - // - for (int stringIndex = startPosition.getStringIndex() + 1; stringIndex < endPosition.getStringIndex(); stringIndex++) - { - String target = get(stringIndex); - result.append(target); - } - - // - { - String source = get(endPosition.getStringIndex()); - String target = source.substring(0, endPosition.getLocalCharIndex()); - result.append(target); - } - } - } - - // - return result; - } - - /** - * {@inheritDoc} - */ - @Override - public String toString() - { - String result; - - if (size() == 1) - { - // - result = get(0); - - } - else - { - // - StringBuffer buffer = new StringBuffer(length()); - - for (String string : this) - { - buffer.append(string); - } - - result = buffer.toString(); - } - - // - return (result); - } - - /** - * - * @param prefix - * @param separator - * @param postifx - * @return - */ - public String toString(final String prefix, final String separator, final String postfix) - { - String result; - - StringList buffer = new StringList(1 + size() * 2 + 1); - - buffer.append(prefix); - - for (String string : this) - { - buffer.append(string); - buffer.append(separator); - } - - if (separator != null) - { - buffer.removeLast(); - } - - buffer.append(postfix); - - result = buffer.toString(); - - // - return result; - } - - /** - * Returns an array containing all of the strings in this list in proper - * sequence (from first to last element). - * - * @return - */ - public String[] toStringArray() - { - String[] result; - - result = new String[this.size()]; - - for (int index = 0; index < size(); index++) - { - result[index] = get(index); - } - - // - return result; - } - - /** - * Returns a string containing the concatenation of the strings of this - * list. Between each string of this list, a separator argument string is - * concatenated too. - * - * @param separator - * - * @return - */ - public String toStringSeparatedBy(final String separator) - { - String result; - - StringList buffer = new StringList(this.size() * 2); - - for (String string : this) - { - buffer.append(string); - buffer.append(separator); - } - - if (separator != null) - { - buffer.removeLast(); - } - - result = buffer.toString(); - - // - return (result); - } - - /** - * - * @param strings - * @return - */ - public String toStringWithBracket() - { - String result; - - result = toString("[", ",", "]"); - - // - return result; - } - - /** - * - * @param source - * @return - */ - public String toStringWithBrackets() - { - String result; - - StringList buffer = new StringList(); - - for (String string : this) - { - buffer.append("[").append(string).append("]"); - } - - result = buffer.toString(); - - // - return result; - } - - /** - * - * @return - */ - public String toStringWithCommas() - { - String result; - - result = this.toStringSeparatedBy(","); - - // - return (result); - } - - /** - * - * @return - */ - public String toStringWithFrenchCommas() - { - String result; - - result = this.toStringSeparatedBy(", "); - - // - return (result); - } - - /** - * Writes the strings of this list into a {@code PrintWriter}. - * - * @param out - * The {@code PrintWriter} where to write. - * - * @throws IOException - */ - public void writeInto(final java.io.PrintWriter out) throws IOException - { - for (String string : this) - { - out.write(string); - } - } - - /** - * Writes the strings of this list into a {@code Writer}. - * - * @param out - * The {@code Writer} where to write. - * - * @throws IOException - */ - public void writeInto(final java.io.Writer out) throws IOException - { - for (String string : this) - { - out.write(string); - } - } -} diff --git a/src/fr/devinsy/util/strings/StringListCharIterator.java b/src/fr/devinsy/util/strings/StringListCharIterator.java deleted file mode 100644 index 4f84c1b..0000000 --- a/src/fr/devinsy/util/strings/StringListCharIterator.java +++ /dev/null @@ -1,133 +0,0 @@ -/** - * Copyright (C) 2014-2015 Christian Pierre MOMON - * - * This file is part of Devinsy-utils. - * - * Devinsy-utils is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Devinsy-utils is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see - */ -package fr.devinsy.util.strings; - -import java.util.Iterator; - -/** - * - */ -public class StringListCharIterator implements Iterator -{ - private StringList source; - private StringListCharPosition currentPosition; - private StringListCharPosition nextPosition; - - /** - * - */ - public StringListCharIterator(final StringList source) - { - super(); - - this.source = source; - this.nextPosition = new StringListCharPosition(); - } - - /** - * - */ - @Override - public boolean hasNext() - { - boolean result; - - if (this.source == null) - { - result = false; - } - else - { - if (this.source.isOutOfBounds(this.nextPosition)) - { - result = false; - } - else - { - result = true; - } - } - - // - return result; - } - - /** - * - */ - @Override - public Character next() - { - Character result; - - if (this.source == null) - { - result = null; - } - else - { - if (hasNext()) - { - result = this.source.charAt(this.nextPosition); - - this.nextPosition.next(); - - if (this.source.isOutOfLine(this.nextPosition)) - { - this.nextPosition.nextEndOfLine(); - - while ((!this.source.isOutOfList(this.nextPosition)) && (this.source.get(this.nextPosition.getStringIndex()) == null)) - { - this.nextPosition.nextEndOfLine(); - } - } - } - else - { - result = null; - } - } - - // - return result; - } - - /** - * - * @return - */ - public StringListCharPosition nextPosition() - { - StringListCharPosition result; - - result = new StringListCharPosition(this.nextPosition); - - // - return result; - } - - /** - * Do nothing. - */ - @Override - public void remove() - { - // TODO or not TODO? - } -} diff --git a/src/fr/devinsy/util/strings/StringListCharPosition.java b/src/fr/devinsy/util/strings/StringListCharPosition.java deleted file mode 100644 index 5940e53..0000000 --- a/src/fr/devinsy/util/strings/StringListCharPosition.java +++ /dev/null @@ -1,111 +0,0 @@ -/** - * Copyright (C) 2013-2015 Christian Pierre MOMON - * - * This file is part of Devinsy-utils. - * - * Devinsy-utils is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Devinsy-utils is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see - */ -package fr.devinsy.util.strings; - -/** - * This class manages a char position in a StringList object. - * - * @author Christian P. Momon - */ -public class StringListCharPosition -{ - private int charIndex; - private int stringIndex; - private int localCharIndex; - - /** - * - * @param index - * @param stringIndex - * @param localIndex - */ - public StringListCharPosition() - { - this.charIndex = 0; - this.stringIndex = 0; - this.localCharIndex = 0; - } - - /** - * - * @param index - * @param stringIndex - * @param localIndex - */ - public StringListCharPosition(final int index, final int stringIndex, final int localIndex) - { - this.charIndex = index; - this.stringIndex = stringIndex; - this.localCharIndex = localIndex; - } - - /** - * - * @param source - */ - public StringListCharPosition(final StringListCharPosition source) - { - this.charIndex = source.getCharIndex(); - this.stringIndex = source.getStringIndex(); - this.localCharIndex = source.getLocalCharIndex(); - } - - public int getCharIndex() - { - return this.charIndex; - } - - public int getLocalCharIndex() - { - return this.localCharIndex; - } - - public int getStringIndex() - { - return this.stringIndex; - } - - public void next() - { - this.charIndex += 1; - this.localCharIndex += 1; - } - - public void nextEndOfLine() - { - this.localCharIndex = 0; - this.stringIndex += 1; - } - - public void setCharIndex(final int charIndex) - { - this.charIndex = charIndex; - } - - public void setLocalCharIndex(final int localCharIndex) - { - this.localCharIndex = localCharIndex; - } - - public void setStringIndex(final int stringIndex) - { - this.stringIndex = stringIndex; - } - -} diff --git a/src/fr/devinsy/util/strings/StringListInputStream.java b/src/fr/devinsy/util/strings/StringListInputStream.java deleted file mode 100644 index 95ab552..0000000 --- a/src/fr/devinsy/util/strings/StringListInputStream.java +++ /dev/null @@ -1,130 +0,0 @@ -/** - * Copyright (C) 2013-2015 Christian Pierre MOMON - * - * This file is part of Devinsy-utils. - * - * Devinsy-utils is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Devinsy-utils is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see - */ -package fr.devinsy.util.strings; - -import java.io.IOException; -import java.io.InputStream; - -/** - * TODO CREATION STEP. - */ -public class StringListInputStream extends InputStream -{ - private StringList in; - - /** - * - */ - public StringListInputStream() - { - this.in = new StringList(); - } - - /** - * - */ - public StringListInputStream(final int size) - { - this.in = new StringList(size); - } - - /** - * - */ - public StringListInputStream(final StringList source) - { - if (source == null) - { - throw new NullPointerException("source is null."); - } - else - { - this.in = source; - } - } - - /** - * {@inheritDoc} - */ - @Override - public int available() throws IOException - { - return 0; - } - - /** - * {@inheritDoc} - */ - @Override - public void close() throws IOException - { - } - - /** - * {@inheritDoc} - */ - @Override - public synchronized void mark(final int readlimit) - { - // TODO - } - - /** - * {@inheritDoc} - */ - @Override - public boolean markSupported() - { - boolean result; - - result = true; - - return result; - } - - /** - * {@inheritDoc} - */ - @Override - public int read() throws IOException - { - // TODO Auto-generated method stub - return 0; - } - - /** - * {@inheritDoc} - */ - @Override - public synchronized void reset() throws IOException - { - // TODO - throw new IOException("mark/reset not supported"); - } - - /** - * {@inheritDoc} - */ - @Override - public long skip(final long n) throws IOException - { - // TODO - return 0; - } -} diff --git a/src/fr/devinsy/util/strings/StringListReader.java b/src/fr/devinsy/util/strings/StringListReader.java deleted file mode 100644 index 465739a..0000000 --- a/src/fr/devinsy/util/strings/StringListReader.java +++ /dev/null @@ -1,122 +0,0 @@ -/** - * Copyright (C) 2013-2017 Christian Pierre MOMON - * - * This file is part of Devinsy-utils. - * - * Devinsy-utils is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Devinsy-utils is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see - */ -package fr.devinsy.util.strings; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.Reader; - -/** - * - * @author Christian Pierre MOMON (christian.momon@devinsy.fr) - */ -public class StringListReader extends Reader -{ - private StringList in; - private StringListCharIterator iterator; - - /** - * - * @param in - */ - public StringListReader(final StringList in) - { - this.in = in; - this.iterator = new StringListCharIterator(in); - } - - /** - * - */ - @Override - public void close() - { - } - - /** - * - */ - @Override - public synchronized int read(final char[] cbuf, final int off, final int len) throws IOException - { - int result; - - BufferedReader a; - - if ((off < 0) || (off > cbuf.length) || (len < 0) || ((off + len) > cbuf.length) || ((off + len) < 0)) - { - throw new IndexOutOfBoundsException(); - } - else if (len == 0) - { - result = 0; - } - else if (this.iterator.hasNext()) - { - // - result = 0; - - // Read off characters. - { - boolean ended = false; - int offCount = 0; - while (!ended) - { - if ((offCount < off) && (this.iterator.hasNext())) - { - this.iterator.next(); - offCount += 1; - result += 1; - } - else - { - ended = true; - } - } - } - - // Read len characters. - { - boolean ended = false; - int lenCount = 0; - while (!ended) - { - if ((lenCount < len) && (this.iterator.hasNext())) - { - char letter = this.iterator.next(); - cbuf[lenCount] = letter; - lenCount += 1; - result += 1; - } - else - { - ended = true; - } - } - } - } - else - { - result = -1; - } - - // - return result; - } -} diff --git a/src/fr/devinsy/util/strings/StringListUtils.java b/src/fr/devinsy/util/strings/StringListUtils.java deleted file mode 100644 index 9ad0a7a..0000000 --- a/src/fr/devinsy/util/strings/StringListUtils.java +++ /dev/null @@ -1,1038 +0,0 @@ -/** - * Copyright (C) 2008-2010, 2013-2016 Christian Pierre MOMON - * - * This file is part of Devinsy-utils. - * - * Devinsy-utils is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Devinsy-utils is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see - */ -package fr.devinsy.util.strings; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; -import java.io.UnsupportedEncodingException; -import java.net.URL; -import java.util.Collection; - -/** - * The {@code StringUtils} class defines helper methods to string collection. - * - * Operations that are null safe. - * - */ -public class StringListUtils -{ - public static final String DEFAULT_CHARSET_NAME = "UTF-8"; - - /** - * - */ - private StringListUtils() - { - } - - /** - * Builds a string concatenating many times a source string. - * - * @param source - * The string to concatenate several time. - * - * @param multiplier - * The number of concatenate to produce. - * @return - */ - public static String concatenate(final String source, final int multiplier) - { - String result; - - result = repeat(source, multiplier).toString(); - - // - return result; - } - - /** - * - * @param source - * @return - */ - public static boolean containsBlank(final Collection source) - { - boolean result; - - if (source == null) - { - result = false; - } - else if (source instanceof StringList) - { - result = ((StringList) source).containsBlank(); - } - else - { - result = new StringList(source).containsBlank(); - } - - // - return result; - } - - /** - * - * @param source - * @return - */ - public static boolean containsBlank(final String... source) - { - boolean result; - - if (source == null) - { - result = false; - } - else - { - result = new StringList(source).containsBlank(); - } - - // - return result; - } - - /** - * - * @param source - * @return - */ - public static boolean containsEmpty(final Collection source) - { - boolean result; - - if (source == null) - { - result = false; - } - else if (source instanceof StringList) - { - result = ((StringList) source).containsEmpty(); - } - else - { - result = new StringList(source).containsEmpty(); - } - - // - return result; - } - - /** - * - * @param source - * @return - */ - public static boolean containsEmpty(final String... source) - { - boolean result; - - if (source == null) - { - result = false; - } - else - { - result = new StringList(source).containsEmpty(); - } - - // - return result; - } - - /** - * - * @param source - * @return - */ - public static boolean containsNull(final Collection source) - { - boolean result; - - if (source == null) - { - result = false; - } - else if (source instanceof StringList) - { - result = ((StringList) source).containsNull(); - } - else - { - result = new StringList(source).containsNull(); - } - - // - return result; - } - - /** - * - * @param source - * @return - */ - public static boolean containsNull(final String... source) - { - boolean result; - - if (source == null) - { - result = false; - } - else - { - result = new StringList(source).containsNull(); - } - - // - return result; - } - - /** - * - * @param target - * @return - */ - public static StringSet getComplement(final Collection alpha, final Collection bravo) - { - StringSet result; - - result = getDifference(bravo, alpha); - - // - return result; - } - - /** - * - * @param target - * @return - */ - public static StringSet getDifference(final Collection alpha, final Collection bravo) - { - StringSet result; - - result = new StringSet(alpha); - result.removeAll(bravo); - - // - return result; - } - - /** - * - * @param target - * @return - */ - public static StringSet getDisjunction(final Collection alpha, final Collection bravo) - { - StringSet result; - - result = new StringSet(); - - for (String string : alpha) - { - if (!bravo.contains(string)) - { - result.add(string); - } - } - - for (String string : bravo) - { - if (!alpha.contains(string)) - { - result.add(string); - } - } - - // - return result; - } - - /** - * - * @param target - * @return - */ - public static StringSet getIntersectionOf(final Collection alpha, final Collection bravo) - { - StringSet result; - - result = new StringSet(); - - for (String string : alpha) - { - if (bravo.contains(string)) - { - result.add(string); - } - } - - // - return result; - } - - /** - * - * @param target - * @return - */ - public static StringSet getUnionOf(final Collection alpha, final Collection bravo) - { - StringSet result; - - result = new StringSet(alpha); - - for (String string : bravo) - { - result.add(string); - } - - // - return result; - } - - /** - * - * @param file - * @throws IOException - */ - public static StringList load(final File source) throws IOException - { - StringList result; - - result = load(source, DEFAULT_CHARSET_NAME); - - // - return result; - } - - /** - * - * @param file - * @throws IOException - */ - public static StringList load(final File file, final String charsetName) throws IOException - { - StringList result; - - // - result = new StringList(); - - // - read(result, new FileInputStream(file), charsetName); - - // - return result; - } - - /** - * - * @param file - * @return - * @throws IOException - */ - public static StringList load(final URL source) throws IOException - { - StringList result; - - result = load(source, DEFAULT_CHARSET_NAME); - - // - return result; - } - - /** - * - * @param file - * @throws IOException - */ - public static StringList load(final URL source, final String charsetName) throws IOException - { - StringList result; - - // - result = new StringList(); - - // - read(result, source.openStream(), charsetName); - - // - return result; - } - - /** - * - * @param file - * @throws IOException - */ - public static void read(final StringList out, final InputStream is, final String charsetName) throws IOException - { - BufferedReader in = null; - try - { - in = new BufferedReader(new InputStreamReader(is, charsetName)); - - boolean ended = false; - - while (!ended) - { - String line = in.readLine(); - - if (line == null) - { - ended = true; - } - else - { - out.append(line); - } - } - } - finally - { - try - { - if (in != null) - { - in.close(); - } - } - catch (IOException exception) - { - exception.printStackTrace(); - } - } - } - - /** - * Builds a string list concatenating many times a source string. - * - * @param source - * The string to concatenate several time. - * - * @param multiplier - * The number of concatenate to produce. - * @return - */ - public static StringList repeat(final String source, final int multiplier) - { - StringList result; - - result = new StringList(multiplier); - for (int count = 0; count < multiplier; count++) - { - result.append(source); - } - - // - return result; - } - - /** - * - * @param file - * @throws FileNotFoundException - * @throws UnsupportedEncodingException - */ - public static void save(final File file, final StringList source) throws UnsupportedEncodingException, FileNotFoundException - { - PrintWriter out = null; - try - { - out = new PrintWriter(new OutputStreamWriter(new FileOutputStream(file), DEFAULT_CHARSET_NAME)); - - if (source != null) - { - for (String string : source) - { - out.println(string); - } - } - } - finally - { - if (out != null) - { - out.close(); - } - } - } - - /** - * Sorts the string list. - * - * @param source - * The string list to sort. - */ - public static void sort(final StringList source) - { - if (source != null) - { - source.sort(); - } - } - - /** - * Concatenates the string from an array to a string. - * - * @param source - * The string array to convert. - * - * @return A string concatenation of the argument. - */ - public static String toString(final String[] source) - { - String result; - - if (source == null) - { - result = null; - } - else - { - result = new StringList(source).toString(); - } - - // - return result; - } - - /** - * - * @param prefix - * @param separator - * @param postfix - * @return - */ - public static String toString(final String[] source, final String prefix, final String separator, final String postfix) - { - String result; - - if (source == null) - { - result = new StringList().toString(prefix, null, postfix); - } - else - { - result = new StringList(source).toString(prefix, separator, postfix); - } - - // - return result; - } - - /** - * - * @param prefix - * @param separator - * @param postfix - * @return - */ - public static String toString(final StringList source, final String prefix, final String separator, final String postfix) - { - String result; - - if (source == null) - { - result = new StringList().toString(prefix, null, postfix); - } - else - { - result = source.toString(prefix, separator, postfix); - } - - // - return result; - } - - /** - * Converts a {@code Collection} to an array of {@code String}. - * - * @param source - * The string list to convert. - * - * @return The result of the conversion. - */ - public static String[] toStringArray(final Collection source) - { - String[] result; - - if (source == null) - { - result = new String[0]; - } - else - { - result = new StringList(source).toStringArray(); - } - - // - return result; - } - - /** - * Converts a {@code StringList} to an array of {@code String}. - * - * @param source - * The string list to convert. - * - * @return The result of the conversion. - */ - public static String[] toStringArray(final StringList source) - { - String[] result; - - if (source == null) - { - result = new String[0]; - } - else - { - result = source.toStringArray(); - } - - // - return result; - } - - /** - * Concatenates the string from an array to a string. - * - * @param strings - * The string array to convert. - * - * @return If argument is null then returns an empty string, otherwise - * returns a string concatenation of the argument. - */ - public static String toStringNotNull(final String[] source) - { - String result; - - result = toString(source); - - if (result == null) - { - result = ""; - } - - // - return result; - } - - /** - * - * @param source - * @return - */ - public static String toStringSeparatedBy(final Collection source, final String separator) - { - String result; - - if (source == null) - { - result = null; - } - else - { - result = new StringList(source).toStringSeparatedBy(separator); - } - - // - return result; - } - - /** - * - * @param strings - * @return - */ - public static String toStringSeparatedBy(final String[] source, final String separator) - { - String result; - - if (source == null) - { - result = null; - } - else - { - result = new StringList(source).toStringSeparatedBy(separator); - } - - // - return result; - } - - /** - * - * @param strings - * @return - */ - public static String toStringSeparatedBy(final StringList source, final String separator) - { - String result; - - if (source == null) - { - result = null; - } - else - { - result = source.toStringSeparatedBy(separator); - } - - // - return result; - } - - /** - * - * @param strings - * @return - */ - public static String toStringWithBracket(final Collection source) - { - String result; - - if (source == null) - { - result = null; - } - else - { - result = new StringList(source).toStringWithBracket(); - } - - // - return result; - } - - /** - * - * @param strings - * @return - */ - public static String toStringWithBracket(final String[] source) - { - String result; - - if (source == null) - { - result = null; - } - else - { - result = new StringList(source).toStringWithBracket(); - } - - // - return result; - } - - /** - * - * @param strings - * @return - */ - public static String toStringWithBracket(final StringList source) - { - String result; - - if (source == null) - { - result = null; - } - else - { - result = source.toStringWithBracket(); - } - - // - return result; - } - - /** - * - * @param strings - * @return - */ - public static String toStringWithBracketNotNull(final Collection source) - { - String result; - - result = toStringWithBracket(source); - - if (result == null) - { - result = ""; - } - - // - return result; - } - - /** - * - * @param strings - * @return - */ - public static String toStringWithBracketNotNull(final String[] source) - { - String result; - - result = toStringWithBracket(source); - - if (result == null) - { - result = ""; - } - - // - return result; - } - - /** - * - * @param strings - * @return - */ - public static String toStringWithBracketNotNull(final StringList source) - { - String result; - - result = toStringWithBracket(source); - - if (result == null) - { - result = ""; - } - - // - return result; - } - - /** - * - * @param source - * @return - */ - public static String toStringWithBrackets(final Collection source) - { - String result; - - if (source == null) - { - result = null; - } - else - { - result = new StringList(source).toStringWithBrackets(); - } - - // - return result; - } - - /** - * - * @param source - * @return - */ - public static String toStringWithBrackets(final String[] source) - { - String result; - - if (source == null) - { - result = null; - } - else - { - result = new StringList(source).toStringWithBrackets(); - } - - // - return result; - } - - /** - * - * @param source - * @return - */ - public static String toStringWithBrackets(final StringList source) - { - String result; - - if (source == null) - { - result = null; - } - else - { - result = source.toStringWithBrackets(); - } - - // - return result; - } - - /** - * - * @param source - * @return - */ - public static String toStringWithCommas(final Collection source) - { - String result; - - if (source == null) - { - result = null; - } - else - { - result = new StringList(source).toStringWithCommas(); - } - - // - return result; - } - - /** - * - * @param source - * @return - */ - public static String toStringWithCommas(final String[] source) - { - String result; - - if (source == null) - { - result = null; - } - else - { - result = new StringList(source).toStringWithCommas(); - } - - // - return result; - } - - /** - * - * @param source - * @return - */ - public static String toStringWithCommas(final StringList source) - { - String result; - - if (source == null) - { - result = null; - } - else - { - result = source.toStringWithCommas(); - } - - // - return result; - } - - /** - * - * @param source - * @return - */ - public static String toStringWithFrenchCommas(final Collection source) - { - String result; - - if (source == null) - { - result = null; - } - else - { - result = new StringList(source).toStringWithFrenchCommas(); - } - - // - return result; - } - - /** - * - * @param source - * @return - */ - public static String toStringWithFrenchCommas(final String[] source) - { - String result; - - if (source == null) - { - result = null; - } - else - { - result = new StringList(source).toStringWithFrenchCommas(); - } - - // - return result; - } - - /** - * - * @param source - * @return - */ - public static String toStringWithFrenchCommas(final StringList source) - { - String result; - - if (source == null) - { - result = null; - } - else - { - result = source.toStringWithFrenchCommas(); - } - - // - return result; - } -} diff --git a/src/fr/devinsy/util/strings/StringListWriter.java b/src/fr/devinsy/util/strings/StringListWriter.java deleted file mode 100644 index b52bf3c..0000000 --- a/src/fr/devinsy/util/strings/StringListWriter.java +++ /dev/null @@ -1,148 +0,0 @@ -/** - * Copyright (C) 2013-2017 Christian Pierre MOMON - * - * This file is part of Devinsy-utils. - * - * Devinsy-utils is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Devinsy-utils is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see - */ -package fr.devinsy.util.strings; - -import java.io.IOException; -import java.io.Writer; - -/** - * - */ -public class StringListWriter extends Writer -{ - private StringList out; - - /** - * - */ - public StringListWriter() - { - this.out = new StringList(); - } - - /** - * - */ - public StringListWriter(final int initialCapacity) - { - this.out = new StringList(initialCapacity); - } - - /** - * - */ - public StringListWriter(final StringList target) - { - if (target == null) - { - throw new NullPointerException("target is null."); - } - else - { - this.out = target; - } - } - - /* - * - */ - @Override - public void close() throws IOException - { - - } - - /* - * - */ - @Override - public void flush() throws IOException - { - - } - - /* - * - */ - @Override - public String toString() - { - String result; - - result = this.out.toString(); - - // - return result; - } - - /** - * - * @return - */ - public StringList toStringList() - { - StringList result; - - result = this.out; - - // - return result; - } - - /* - * - */ - public void write(final char c) throws IOException - { - this.out.append(c); - } - - /* - * - */ - @Override - public void write(final char[] cbuf, final int off, final int len) throws IOException - { - char[] target; - if ((off == 0) && (cbuf.length == len)) - { - target = cbuf; - } - else - { - target = new char[len]; - for (int index = off; index < len; index++) - { - target[index] = cbuf[index]; - } - } - - // - this.out.append(new String(target)); - } - - /* - * - */ - @Override - public void write(final String string) throws IOException - { - this.out.append(string); - } -} diff --git a/src/fr/devinsy/util/strings/StringSet.java b/src/fr/devinsy/util/strings/StringSet.java deleted file mode 100644 index f69a951..0000000 --- a/src/fr/devinsy/util/strings/StringSet.java +++ /dev/null @@ -1,411 +0,0 @@ -/** - * Copyright (C) 2014-2016 Christian Pierre MOMON - * - * This file is part of Devinsy-utils. - * - * Devinsy-utils is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Devinsy-utils is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see - */ -package fr.devinsy.util.strings; - -import java.util.Collection; -import java.util.HashSet; - -/** - * This class is a set of String objects with specific methods. It makes - * possible to build a string without any copy. The goal is to make easier the - * use of set of strings. - */ -public class StringSet extends HashSet -{ - private static final long serialVersionUID = 6674838743930005326L; - - /** - * - */ - public StringSet() - { - super(); - } - - /** - * Constructs a list of string of the specified collection, in the order - * they are returned by the collection's iterator. - * - * @param source - */ - public StringSet(final Collection source) - { - super(source.size()); - - if (source != null) - { - // - for (String string : source) - { - this.add(string); - } - } - } - - /** - * - */ - public StringSet(final int initialCapacity) - { - super(initialCapacity); - } - - /** - * - */ - public StringSet(final String[] source) - { - super(); - - if (source != null) - { - // - for (String string : source) - { - this.add(string); - } - } - } - - /** - * - */ - public StringSet(final StringSet source) - { - super(); - - if (source != null) - { - // - for (String string : source) - { - this.add(string); - } - } - } - - /** - * Check null parameter before add. - */ - @Override - public boolean add(final String string) - { - boolean result; - - if (string != null) - { - // - result = super.add(string); - } - else - { - // - result = false; - } - - // - return result; - } - - /** - * - */ - public StringSet add(final StringSet strings) - { - StringSet result; - - if (strings != null) - { - for (String string : strings) - { - this.add(string); - } - } - - result = this; - - // - return result; - } - - /** - * Deep copy and shallow copy have no sense about a list of immutable - * objects. - * - * @return - */ - @Override - public StringSet clone() - { - StringSet result; - - result = new StringSet(size()); - - for (String string : this) - { - result.add(string); - } - - // - return result; - } - - /** - * - */ - public int length() - { - int result = 0; - - for (String string : this) - { - result += string.length(); - } - - // - return result; - } - - /** - * - */ - public StringSet merge() - { - StringSet result; - - StringBuffer buffer = new StringBuffer(length()); - - for (String string : this) - { - buffer.append(string); - } - - String merge = buffer.toString(); - - clear(); - add(merge); - - // - result = this; - return result; - } - - /** - * - */ - public StringSet put(final char character) - { - StringSet result; - - this.add(String.valueOf(character)); - - result = this; - - // - return result; - } - - /** - * - */ - public StringSet put(final double value) - { - StringSet result; - - result = this.put(String.valueOf(value)); - - // - return result; - } - - /** - * - */ - public StringSet put(final int value) - { - StringSet result; - - result = this.put(String.valueOf(value)); - - // - return result; - } - - /** - * - */ - public StringSet put(final long value) - { - StringSet result; - - result = this.put(String.valueOf(value)); - - // - return result; - } - - /** - * - */ - public StringSet put(final Object value) - { - StringSet result; - - if (value != null) - { - this.put(value.toString()); - } - - result = this; - - // - return result; - } - - /** - * Check null parameter before add. - */ - public StringSet put(final String string) - { - StringSet result; - - if (string != null) - { - this.add(string); - } - - result = this; - - // - return result; - } - - /** - * - */ - public StringSet put(final String... strings) - { - StringSet result; - - if (strings != null) - { - for (String string : strings) - { - this.put(string); - } - } - - result = this; - - // - return result; - } - - /** - * - */ - public StringSet put(final StringList strings) - { - StringSet result; - - if (strings != null) - { - for (String string : strings) - { - this.put(string); - } - } - - result = this; - - // - return result; - } - - /** - * - */ - public StringSet put(final StringSet strings) - { - StringSet result; - - if (strings != null) - { - for (String string : strings) - { - this.put(string); - } - } - - result = this; - - // - return result; - } - - /** - * - */ - public StringSet putNullable(final Object value) - { - StringSet result; - - if (value == null) - { - super.add((String) null); - } - else - { - this.put(value.toString()); - } - - result = this; - - // - return result; - } - - /** - * - */ - @Override - public String toString() - { - String result; - - result = toStringList().toStringWithCommas(); - - // - return result; - } - - /** - * - * @return - */ - public StringList toStringList() - { - StringList result; - - result = new StringList(this); - - // - return result; - } -} diff --git a/src/fr/devinsy/util/unix/CachedFile.java b/src/fr/devinsy/util/unix/CachedFile.java deleted file mode 100644 index ce1881f..0000000 --- a/src/fr/devinsy/util/unix/CachedFile.java +++ /dev/null @@ -1,134 +0,0 @@ -/** - * Copyright (C) 2006-2010, 2013-2014 Christian Pierre MOMON - * - * This file is part of Devinsy-utils. - * - * Devinsy-utils is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Devinsy-utils is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see - */ -package fr.devinsy.util.unix; - -import java.io.File; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * @author Christian Pierre MOMON (christian.momon@devinsy.fr) - */ -public class CachedFile -{ - public enum Status - { - NOT_LOAD, EXPIRED, UPDATED - } - - private static final Logger logger = LoggerFactory.getLogger(CachedFile.class); - - protected String sourceName; - protected long sourceTime; - protected Status status; - - /** - * - */ - public CachedFile(final String fileName) - { - this.sourceName = fileName; - this.sourceTime = 0; - this.status = Status.NOT_LOAD; - } - - /** - * - */ - protected File getSourceFile() - { - File result; - - if (this.sourceName == null) - { - result = null; - } - else - { - File source = new File(this.sourceName); - - if (!source.exists()) - { - logger.error("source file defined but not found"); - result = null; - } - else - { - result = source; - } - } - - // - return (result); - } - - /** - * - */ - protected Status getStatus() - { - Status result; - - File source = getSourceFile(); - - if (source == null) - { - this.status = Status.NOT_LOAD; - } - else if (this.sourceTime != source.lastModified()) - { - this.status = Status.EXPIRED; - } - - result = this.status; - - // - return (result); - } - - /** - * - */ - public void setNotLoad() - { - this.status = Status.NOT_LOAD; - } - - /** - * - */ - public void setUpdated() - { - File source = getSourceFile(); - - if (source == null) - { - this.status = Status.NOT_LOAD; - } - else - { - this.sourceTime = source.lastModified(); - this.status = Status.UPDATED; - } - } -} - -// //////////////////////////////////////////////////////////////////////// diff --git a/src/fr/devinsy/util/unix/EtcGroupFile.java b/src/fr/devinsy/util/unix/EtcGroupFile.java deleted file mode 100644 index ad1ccb5..0000000 --- a/src/fr/devinsy/util/unix/EtcGroupFile.java +++ /dev/null @@ -1,200 +0,0 @@ -/** - * Copyright (C) 2006-2010, 2013-2014 Christian Pierre MOMON - * - * This file is part of Devinsy-utils. - * - * Devinsy-utils is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Devinsy-utils is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see - */ -package fr.devinsy.util.unix; - -import java.util.Vector; - -/** - * - * @author Christian Pierre MOMON (christian.momon@devinsy.fr) - */ -public class EtcGroupFile extends CachedFile -{ - // static private final Logger logger = - // LoggerFactory.getLogger(EtcGroupFile.class); - - private static EtcGroupFile instance = null; - protected Groups groups; - - /** - * - */ - protected EtcGroupFile() - { - super("/etc/group"); - this.groups = null; - } - - /* - * - */ - public boolean contains(final String name) - { - boolean result; - - Groups groups = updatedGroups(); - - if (groups == null) - { - result = false; - } - else - { - result = groups.contains(name); - } - - // - return (result); - } - - /** - * - */ - public Group get(final int gid) - { - Group result; - - Groups groups = updatedGroups(); - - if (groups == null) - { - result = null; - } - else - { - result = groups.getByGid(gid); - } - - // - return (result); - } - - /** - * - */ - public Group get(final String name) - { - Group result; - - Groups groups = updatedGroups(); - - if (groups == null) - { - result = null; - } - else - { - result = groups.getByName(name); - } - - // - return (result); - } - - /** - * - */ - public Vector getLoginGroups(final String login) - { - Vector result; - - Groups groups = updatedGroups(); - - result = groups.getLoginGroups(login); - - // - return (result); - } - - /** - * - */ - public String getLoginGroupsString(final String login) - { - String result; - - this.groups = updatedGroups(); - - result = this.groups.getLoginGroupsString(login); - - // - return (result); - } - - /** - * - */ - @Override - public String toString() - { - String result; - - result = this.groups.toString(); - - // - return (result); - } - - /** - * - */ - protected Groups updatedGroups() - { - Groups result; - - if (getStatus() != Status.UPDATED) - { - this.groups = EtcGroupFileReader.load(); - - if (this.groups == null) - { - setNotLoad(); - } - else - { - setUpdated(); - } - } - - result = this.groups; - - // - return (result); - } - - /** - * - */ - static public EtcGroupFile instance() - { - EtcGroupFile result; - - if (EtcGroupFile.instance == null) - { - EtcGroupFile.instance = new EtcGroupFile(); - } - - result = EtcGroupFile.instance; - - // - return (result); - } -} - -// //////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/src/fr/devinsy/util/unix/EtcGroupFileReader.java b/src/fr/devinsy/util/unix/EtcGroupFileReader.java deleted file mode 100644 index 35ab71f..0000000 --- a/src/fr/devinsy/util/unix/EtcGroupFileReader.java +++ /dev/null @@ -1,102 +0,0 @@ -/** - * Copyright (C) 2006-2010, 2013-2014 Christian Pierre MOMON - * - * This file is part of Devinsy-utils. - * - * Devinsy-utils is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Devinsy-utils is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see - */ -package fr.devinsy.util.unix; - -import java.io.BufferedReader; -import java.io.FileNotFoundException; -import java.io.FileReader; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * @author Christian Pierre MOMON (christian.momon@devinsy.fr) - */ -public class EtcGroupFileReader -{ - private static final Logger logger = LoggerFactory.getLogger(EtcGroupFileReader.class); - - /** - * - */ - public static Groups load() - { - Groups result; - - BufferedReader file; - - try - { - file = new BufferedReader(new FileReader("/etc/group")); - } - catch (FileNotFoundException exception) - { - logger.error("File not found"); - file = null; - } - - if (file == null) - { - result = null; - } - else - { - result = new Groups(); - - try - { - String line; - while ((line = file.readLine()) != null) - { - String[] tokens = line.split(":"); - - Group group = new Group(); - group.setName(tokens[0]); - group.setPassword(tokens[1]); - group.setGid((new Integer(tokens[2])).intValue()); - - // Manage the case of empty shell. - if (tokens.length == 4) - { - String[] tokensBis = tokens[3].split(","); - - for (int tokenCounter = 0; tokenCounter < tokensBis.length; tokenCounter++) - { - group.addMember(tokensBis[tokenCounter]); - } - } - result.add(group); - } - - file.close(); - } - catch (java.io.IOException exception) - { - logger.error("Exception here."); - result = null; - } - } - - // - return (result); - } -} - -// //////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/src/fr/devinsy/util/unix/EtcPasswdFile.java b/src/fr/devinsy/util/unix/EtcPasswdFile.java deleted file mode 100644 index 2816e37..0000000 --- a/src/fr/devinsy/util/unix/EtcPasswdFile.java +++ /dev/null @@ -1,186 +0,0 @@ -/** - * Copyright (C) 2006-2010, 2013-2014 Christian Pierre MOMON - * - * This file is part of Devinsy-utils. - * - * Devinsy-utils is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Devinsy-utils is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see - */ -package fr.devinsy.util.unix; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * @author Christian Pierre MOMON (christian.momon@devinsy.fr) - */ -public class EtcPasswdFile extends CachedFile -{ - private static final Logger logger = LoggerFactory.getLogger(EtcPasswdFile.class); - - private static EtcPasswdFile instance = null; - protected Users users; - - /** - * - */ - protected EtcPasswdFile() - { - super("/etc/passwd"); - this.users = null; - } - - /* - * - */ - public boolean contains(final String login) - { - boolean result; - - Users users = updatedUsers(); - - if (users == null) - { - result = false; - } - else - { - result = users.contains(login); - } - - // - return (result); - } - - /** - * - */ - public User get(final int uid) - { - User result; - - Users users = updatedUsers(); - - if (users == null) - { - result = null; - } - else - { - result = users.getByUid(uid); - } - - // - return (result); - } - - /** - * - */ - public User get(final String login) - { - User result; - - Users users = updatedUsers(); - - if (users == null) - { - result = null; - } - else - { - result = users.getByLogin(login); - } - - // - return (result); - } - - /** - * - */ - @Override - public String toString() - { - String result; - - result = this.users.toString(); - - // - return (result); - } - - /** - * - */ - protected Users update() - { - Users result; - - logger.debug("updating"); - this.users = EtcPasswdFileReader.load(); - - if (this.users == null) - { - setNotLoad(); - } - else - { - setUpdated(); - } - - result = this.users; - - // - return (result); - } - - /** - * - */ - protected Users updatedUsers() - { - Users result; - - if (getStatus() != Status.UPDATED) - { - update(); - } - - result = this.users; - - // - return (result); - } - - /** - * - */ - public static EtcPasswdFile instance() - { - EtcPasswdFile result; - - if (EtcPasswdFile.instance == null) - { - EtcPasswdFile.instance = new EtcPasswdFile(); - } - - result = EtcPasswdFile.instance; - - // - return (result); - } -} - -// //////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/src/fr/devinsy/util/unix/EtcPasswdFileReader.java b/src/fr/devinsy/util/unix/EtcPasswdFileReader.java deleted file mode 100644 index 1467391..0000000 --- a/src/fr/devinsy/util/unix/EtcPasswdFileReader.java +++ /dev/null @@ -1,105 +0,0 @@ -/** - * Copyright (C) 2006-2010, 2013-2014 Christian Pierre MOMON - * - * This file is part of Devinsy-utils. - * - * Devinsy-utils is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Devinsy-utils is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see - */ -package fr.devinsy.util.unix; - -import java.io.BufferedReader; -import java.io.FileNotFoundException; -import java.io.FileReader; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * @author Christian Pierre MOMON (christian.momon@devinsy.fr) - */ -public class EtcPasswdFileReader -{ - private static final Logger logger = LoggerFactory.getLogger(EtcPasswdFileReader.class); - - /** - * - */ - public static Users load() - { - Users result; - - BufferedReader file; - - try - { - file = new BufferedReader(new FileReader("/etc/passwd")); - } - catch (FileNotFoundException exception) - { - logger.error("File not found"); - file = null; - } - - if (file == null) - { - result = null; - } - else - { - result = new Users(); - - try - { - String line; - while ((line = file.readLine()) != null) - { - String[] tokens = line.split(":"); - - User user = new User(); - user.setLogin(tokens[0]); - user.setPassword(tokens[1]); - user.setUid((new Integer(tokens[2])).intValue()); - user.setGid((new Integer(tokens[3])).intValue()); - user.setRealName(tokens[4]); - user.setHomeDirectory(tokens[5]); - - // Manage the case of empty shell. - if (tokens.length == 7) - { - user.setShell(tokens[6]); - } - else - { - user.setShell(""); - } - - result.add(user); - } - - file.close(); - } - catch (java.io.IOException exception) - { - logger.error("Exception here."); - result = null; - } - } - - // - return (result); - } -} - -// //////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/src/fr/devinsy/util/unix/Group.java b/src/fr/devinsy/util/unix/Group.java deleted file mode 100644 index 04eb687..0000000 --- a/src/fr/devinsy/util/unix/Group.java +++ /dev/null @@ -1,223 +0,0 @@ -/** - * Copyright (C) 2006-2010, 2013-2014 Christian Pierre MOMON - * - * This file is part of Devinsy-utils. - * - * Devinsy-utils is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Devinsy-utils is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see - */ -package fr.devinsy.util.unix; - -import java.util.Vector; - -/** - * - * @author Christian Pierre MOMON (christian.momon@devinsy.fr) - */ -public class Group -{ - // static private final Logger logger = - // LoggerFactory.getLogger(Group.class); - - /* - * /usr/include/grp.h - * - * The group structure. - * struct group - * { - * char *gr_name; Group name. - * char *gr_passwd; Password. - * __gid_t gr_gid; Group ID. - * char **gr_mem; Member list. - * }; - */ - - protected String name; - protected String password; - protected int gid; - protected Vector members; - - /** - * - */ - public Group() - { - this.name = null; - this.password = null; - this.gid = -1; - this.members = new Vector(); - } - - /** - * - */ - public void addMember(final String login) - { - if ((login != null) && (login.length() != 0)) - { - this.members.add(login); - } - } - - /** - * - */ - public int getGid() - { - int result; - - result = this.gid; - - // - return (result); - } - - /** - * - */ - public Vector getMembers() - { - Vector result; - - result = this.members; - - // - return (result); - } - - /** - * - */ - public String getName() - { - String result; - - result = this.name; - - // - return (result); - } - - /** - * - */ - public String getPassword() - { - String result; - - result = this.password; - - // - return (result); - } - - /** - * - */ - public int gid() - { - int result; - - result = this.gid; - - // - return (result); - } - - /** - * - */ - public Vector members() - { - Vector result; - - result = this.members; - - // - return (result); - } - - /** - * - */ - public String name() - { - String result; - - result = this.name; - - // - return (result); - } - - /** - * - */ - public String passwd() - { - String result; - - result = this.password; - - // - return (result); - } - - /** - * - */ - public void setGid(final int gid) - { - this.gid = gid; - } - - /** - * - */ - public void setName(final String name) - { - this.name = name; - } - - /** - * - */ - public void setPasswd(final String password) - { - this.password = password; - } - - /** - * - */ - public void setPassword(final String password) - { - this.password = password; - } - - /** - * - */ - @Override - public String toString() - { - String result; - - result = "|" + this.name + "|" + this.password + "|" + this.gid + "|" + this.members + "|"; - - // - return (result); - } -} - -// //////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/src/fr/devinsy/util/unix/Groups.java b/src/fr/devinsy/util/unix/Groups.java deleted file mode 100644 index 34e0e4d..0000000 --- a/src/fr/devinsy/util/unix/Groups.java +++ /dev/null @@ -1,233 +0,0 @@ -/** - * Copyright (C) 2006-2010, 2013-2014 Christian Pierre MOMON - * - * This file is part of Devinsy-utils. - * - * Devinsy-utils is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Devinsy-utils is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see - */ -package fr.devinsy.util.unix; - -import java.util.Iterator; -import java.util.Vector; - -/** - * - * @author Christian Pierre MOMON (christian.momon@devinsy.fr) - */ -public class Groups extends Vector -{ - - private static final long serialVersionUID = 5802487312198869603L; - - // static private final Logger logger = - // LoggerFactory.getLogger(Groups.class); - - /** - * - */ - public Groups() - { - super(); - } - - /* - * - */ - public boolean contains(final int gid) - { - boolean result; - - if (getByGid(gid) == null) - { - result = false; - } - else - { - result = true; - } - - // - return (result); - } - - /* - * - */ - public boolean contains(final String name) - { - boolean result; - - if (getByName(name) == null) - { - result = false; - } - else - { - result = true; - } - - // - return (result); - } - - /** - * - */ - public Group getByGid(final int gid) - { - Group result; - - result = null; - boolean ended = false; - Iterator iterator = this.iterator(); - while (!ended) - { - if (iterator.hasNext()) - { - Group group = iterator.next(); - if (group.getGid() == gid) - { - ended = true; - result = group; - } - } - else - { - ended = true; - result = null; - } - } - - // - return (result); - } - - /** - * - */ - public Group getByName(final String name) - { - Group result; - - if (name == null) - { - result = null; - } - else - { - result = null; - boolean ended = false; - Iterator iterator = this.iterator(); - while (!ended) - { - if (iterator.hasNext()) - { - Group group = iterator.next(); - if (group.getName().equals(name)) - { - ended = true; - result = group; - } - } - else - { - ended = true; - result = null; - } - } - } - - // - return (result); - } - - /** - * - */ - public Vector getLoginGroups(final String login) - { - Vector result; - - result = new Vector(); - Iterator iterator = this.iterator(); - - while (iterator.hasNext()) - { - Group group = iterator.next(); - - if (group.members().contains(login)) - { - result.add(group.getName()); - } - } - - // - return (result); - } - - /** - * - */ - public String getLoginGroupsString(final String login) - { - String result; - - Vector groups = getLoginGroups(login); - - StringBuffer string = new StringBuffer(); - - for (String group : groups) - { - if (string.length() == 0) - { - string.append(group); - } - else - { - string.append(","); - string.append(group); - } - } - - result = string.toString(); - - // - return (result); - } - - /** - * - */ - @Override - public String toString() - { - String result; - - StringBuffer out = new StringBuffer(); - - Iterator iterator = this.iterator(); - - while (iterator.hasNext()) - { - out.append(iterator.next().toString() + "\n"); - } - - result = out.toString(); - - // - return (result); - } -} - -// //////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/src/fr/devinsy/util/unix/Unix.java b/src/fr/devinsy/util/unix/Unix.java deleted file mode 100644 index 5de7972..0000000 --- a/src/fr/devinsy/util/unix/Unix.java +++ /dev/null @@ -1,597 +0,0 @@ -/** - * Copyright (C) 2006-2010, 2013-2015 Christian Pierre MOMON - * - * This file is part of Devinsy-utils. - * - * Devinsy-utils is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Devinsy-utils is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see - */ -package fr.devinsy.util.unix; - -import java.io.File; -import java.util.Vector; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import fr.devinsy.util.cmdexec.CmdExec; -import fr.devinsy.util.strings.StringListUtils; -import fr.devinsy.util.unix.acl.Acl; -import fr.devinsy.util.unix.acl.AclManager; - -/** - * - * @author Christian Pierre MOMON (christian.momon@devinsy.fr) - */ -public class Unix -{ - private static final Logger logger = LoggerFactory.getLogger(Unix.class); - public static final String SUDO = "/usr/bin/sudo"; - - /** - * - */ - public static void appendToFile(final String text, final String path) throws Exception - { - if ((text == null) || (text.length() == 0) || (path == null) || (path.length() == 0)) - { - throw new Exception("Parameter undefined: [" + text + "][" + path + "]."); - } - else - { - try - { - CmdExec.run(SUDO, "bash", "-c", "echo \"" + text + "\" >> " + path); - } - catch (Exception exception) - { - throw new Exception("Error detected appending text to file [" + path + "].", exception); - } - } - } - - /** - * - */ - public static void chmod(final String changes, final String path) throws Exception - { - if ((changes == null) || (changes.length() == 0) || (path == null) || (path.length() == 0)) - { - throw new Exception("Parameter undefined: [" + changes + "][" + path + "]."); - } - else if (!new File(path).exists()) - { - throw new Exception("Path not found: [" + path + "]."); - } - else - { - try - { - CmdExec.run(SUDO, "chmod", changes, path); - } - catch (Exception exception) - { - throw new Exception("Error running chmod command for [" + changes + "][" + path + "].", exception); - } - } - } - - /** - * - */ - public static void clearAcl(final String id, final String filePathName) throws Exception - { - AclManager.clearId(id, filePathName); - } - - /** - * - */ - public static void clearAclGroup(final String group, final String filePathName) throws Exception - { - AclManager.clearGroup(group, filePathName); - } - - /** - * - */ - public static void clearAclUser(final String login, final String filePathName) throws Exception - { - AclManager.clearUser(login, filePathName); - } - - /** - * - */ - public static void createUserAccount(final String login) throws Exception - { - if ((login == null) || (login.length() == 0)) - { - throw new Exception("Login parameter undefined."); - } - else - { - createUserAccount(login, login); - } - } - - /** - * - */ - public static void createUserAccount(final String login, final String name) throws Exception - { - if ((login == null) || (login.length() == 0)) - { - throw new Exception("Login parameter undefined."); - } - else if ((name == null) || (name.length() == 0)) - { - throw new Exception("Name parameter undefined."); - } - else - { - createUserAccount(login, name, "/home/" + login); - } - } - - /** - * - */ - public static void createUserAccount(final String login, final String name, final String home) throws Exception - { - if ((login == null) || (login.length() == 0)) - { - throw new Exception("Login parameter undefined."); - } - else if ((name == null) || (name.length() == 0)) - { - throw new Exception("Name parameter undefined."); - } - else if ((home == null) || (home.length() == 0)) - { - throw new Exception("Home parameter undefined."); - } - else - { - try - { - logger.info("Creating user account for [" + login + "]."); - CmdExec.run(SUDO, "/usr/sbin/useradd", "-m", "-c", name, "-d", home, login); - EtcPasswdFile.instance().update(); - logger.info("User account created for [" + login + "]."); - } - catch (Exception exception) - { - throw new Exception("Error detected creating user account [" + login + "].", exception); - } - } - } - - /** - * - */ - public static void createUserAccount(final String login, final String name, final String home, final String password) throws Exception - { - if ((password == null) || (password.length() == 0)) - { - throw new Exception("Password parameter undefined."); - } - else if (Unix.isLogin(login)) - { - throw new Exception("Login [" + login + "] already in use"); - } - else - { - createUserAccount(login, name, home); - setPassword(login, password); - } - } - - /** - * - */ - public static void deleteGroup(final String group) throws Exception - { - if ((group == null) || (group.length() == 0)) - { - throw new Exception("Group parameter undefined."); - } - else - { - try - { - logger.info("Deleting group for [" + group + "]."); - CmdExec.run(SUDO + " groupdel " + group); - logger.info("Group deleted for [" + group + "]."); - } - catch (Exception exception) - { - throw new Exception("Error running groupdel command for group [" + group + "].", exception); - } - } - } - - /** - * - */ - public static void deleteUserAccount(final String login) throws Exception - { - if ((login == null) || (login.length() == 0)) - { - throw new Exception("Login parameter undefined."); - } - else - { - try - { - logger.info("Deleting user account for [" + login + "]."); - CmdExec.run(SUDO + " /usr/sbin/userdel " + login); - logger.info("User account delted for [" + login + "]."); - } - catch (Exception exception) - { - throw new Exception("Error running userdel command for login [" + login + "].", exception); - } - } - } - - /** - * - */ - public static String getAclData(final String filePathName) throws Exception - { - String result; - - result = AclManager.getAclData(filePathName); - - // - return (result); - } - - /** - * - */ - public static String[] getAclUsers(final String filePathName) throws Exception - { - String[] result; - - Acl acl = AclManager.getAcl(filePathName); - - result = acl.currentAcl().getUserIds(); - - // - return (result); - } - - /** - * - */ - public static boolean isGroup(final String groupName) - { - boolean result; - - result = EtcGroupFile.instance().contains(groupName); - - // - return (result); - } - - /** - * - */ - public static boolean isLogin(final String login) - { - boolean result; - - result = EtcPasswdFile.instance().contains(login); - - // - return (result); - } - - /** - * - */ - public static void link(final String sourcePath, final String targetPath) throws Exception - { - logger.info("[" + sourcePath + "][" + targetPath + "]"); - if ((sourcePath == null) || (sourcePath.length() == 0) || (targetPath == null) || (targetPath.length() == 0)) - { - throw new Exception("Parameter undefined: [" + sourcePath + "][" + targetPath + "]."); - } - else - { - File sourceFile = new File(sourcePath); - File targetFile = new File(targetPath); - - if (!sourceFile.exists()) - { - throw new Exception("Source does not exist: [" + sourcePath + "]."); - } - else if ((targetFile.exists()) && (!targetFile.isDirectory())) - { - throw new Exception("Target already exists: [" + targetPath + "]."); - } - else - { - try - { - CmdExec.run(SUDO, "ln", "-s", sourcePath, targetPath); - } - catch (Exception exception) - { - throw new Exception("Error detected linking [" + sourcePath + "][" + targetPath + "].", exception); - } - } - } - } - - /** - * - */ - public static void modifyLogin(final String sourceLogin, final String targetLogin, final String sourceHomeDirectory) throws Exception - { - logger.info("Starting login modifying: [" + sourceLogin + "] -> [" + targetLogin + "]"); - if ((sourceLogin == null) || (sourceLogin.length() == 0)) - { - throw new Exception("Original login parameters undefined"); - } - else if ((targetLogin == null) || (targetLogin.length() == 0)) - { - throw new Exception("New login parameters undefined"); - } - else if (!Unix.isLogin(sourceLogin)) - { - throw new Exception("Original login unknow: [" + sourceLogin + "]."); - } - else if (Unix.isLogin(targetLogin)) - { - throw new Exception("New login unknow: [" + targetLogin + "]."); - } - else if (sourceHomeDirectory == null) - { - throw new Exception("sourceHomeDirectory parameter undefined, thus no home directory move."); - } - else if (!new File(sourceHomeDirectory).exists()) - { - throw new Exception("Source home directory does not exist: [" + sourceHomeDirectory + "]."); - } - else - { - String targetHomeDirectory = new File(sourceHomeDirectory).getParent().toString() + "/" + targetLogin; - if (new File(targetHomeDirectory).exists()) - { - throw new Exception("Target home directory already exists: [" + targetHomeDirectory + "]."); - } - else - { - try - { - logger.info("Login modifying: [" + sourceLogin + "] -> [" + targetLogin + "]"); - CmdExec.run(SUDO + " usermod -l " + targetLogin + " " + sourceLogin); - logger.info("Login modified: [" + sourceLogin + "] -> [" + targetLogin + "]"); - } - catch (Exception exception) - { - throw new Exception("Login modification failed for [" + sourceLogin + "].", exception); - } - - try - { - logger.info("Renaming home directory: [" + sourceHomeDirectory + "] -> [" + targetLogin + "]"); - CmdExec.run(SUDO + " mv " + sourceHomeDirectory + " " + targetHomeDirectory); - logger.info("Home directory renamed: [" + sourceHomeDirectory + "] -> [" + targetLogin + "]"); - } - catch (Exception exception) - { - throw new Exception("Home directory rename failed for [" + sourceHomeDirectory + "].", exception); - } - } - } - logger.info("Login modifying done: [" + sourceLogin + "] -> [" + targetLogin + "]"); - } - - /** - * - */ - public static void recursiveChmod(final String changes, final String path) throws Exception - { - if ((changes == null) || (changes.length() == 0) || (path == null) || (path.length() == 0)) - { - throw new Exception("Parameter undefined: [" + changes + "][" + path + "]."); - } - else if (!new File(path).exists()) - { - throw new Exception("Path not found: [" + path + "]."); - } - else - { - try - { - CmdExec.run(SUDO, "chmod", "-R", changes, path); - } - catch (Exception exception) - { - throw new Exception("Error running recursive chmod command for [" + changes + "][" + path + "].", exception); - } - } - } - - /** - * - */ - public static void renameGroup(final String sourceGroup, final String targetGroup) throws Exception - { - logger.info("Starting group renaming: [" + sourceGroup + "] -> [" + targetGroup + "]"); - if ((sourceGroup == null) || (sourceGroup.length() == 0)) - { - throw new Exception("Original group name parameters undefined"); - } - else if ((targetGroup == null) || (targetGroup.length() == 0)) - { - throw new Exception("New group name parameters undefined"); - } - else if (!Unix.isGroup(sourceGroup)) - { - throw new Exception("Original group unknow: [" + sourceGroup + "]."); - } - else if (Unix.isGroup(targetGroup)) - { - throw new Exception("New group unknow: [" + targetGroup + "]."); - } - else - { - try - { - logger.info("Login modifying: [" + sourceGroup + "] -> [" + targetGroup + "]"); - CmdExec.run(SUDO + " groupmod -n " + targetGroup + " " + sourceGroup); - logger.info("Login modified: [" + sourceGroup + "] -> [" + targetGroup + "]"); - } - catch (Exception exception) - { - throw new Exception("Group renaming failed for [" + sourceGroup + "].", exception); - } - } - logger.info("Group renaming done: [" + sourceGroup + "] -> [" + targetGroup + "]"); - } - - /** - * - */ - public static Group searchGroup(final String groupName) - { - Group result; - - result = EtcGroupFile.instance().get(groupName); - - // - return (result); - } - - /** - * - */ - public static User searchLogin(final String login) - { - User result; - - result = EtcPasswdFile.instance().get(login); - - // - return (result); - } - - /** - * - */ - public static Vector searchLoginGroups(final String login) - { - Vector result; - - result = EtcGroupFile.instance().getLoginGroups(login); - - // - return (result); - } - - /** - * - */ - public static void setfacl(final String... args) throws Exception - { - try - { - CmdExec.run(SUDO, "setfacl", args, 1, 6); - } - catch (Exception exception) - { - throw new Exception("Error running setfacl command for " + StringListUtils.toStringWithBrackets(args) + ":" + exception.getMessage() + ".", exception); - } - } - - /** - * As 'passwd' command has not the option '--stdin' in all systems (eg. - * Debian), this method uses the 'chpasswd' command. - */ - public static void setPassword(final String login, final String newPassword) throws Exception - { - if ((login == null) || (login.length() == 0)) - { - throw new Exception("Login parameter undefined."); - } - else if (newPassword == null) - { - throw new Exception("New password parameter undefined."); - } - else - { - try - { - logger.info("Password setting for [" + login + "]."); - CmdExec.run(SUDO, "bash", "-c", "echo \"" + login + ":" + newPassword + "\"| chpasswd "); - logger.info("Password set for [" + login + "]."); - } - catch (Exception exception) - { - throw new Exception("Error detected on setting of the new password for [" + login + "].", exception); - } - } - } - - /** - * chfn [ -f full-name ] [ username ] - */ - public static void setRealName(final String login, final String newRealName) throws Exception - { - if ((login == null) || (login.length() == 0)) - { - throw new Exception("Login parameter undefined."); - } - else if (newRealName == null) - { - throw new Exception("New real name parameter undefined."); - } - else - { - try - { - logger.info("Real name changing for user [" + login + "]."); - CmdExec.run(SUDO, "chfn", "-f", newRealName, login); - EtcPasswdFile.instance().update(); - logger.info("Real name changed for user [" + login + "]."); - } - catch (Exception exception) - { - throw new Exception("Error detected on setting of the new real name for [" + login + "].", exception); - } - } - } - - /** - * - */ - public static void unlink(final String filePathName) throws Exception - { - logger.info("[" + filePathName + "]"); - if (filePathName == null) - { - throw new Exception("Parameter undefined: [" + filePathName + "]."); - } - else - { - new File(filePathName).delete(); - } - } -} - -// //////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/src/fr/devinsy/util/unix/User.java b/src/fr/devinsy/util/unix/User.java deleted file mode 100644 index 8942577..0000000 --- a/src/fr/devinsy/util/unix/User.java +++ /dev/null @@ -1,355 +0,0 @@ -/** - * Copyright (C) 2006-2010, 2013-2014 Christian Pierre MOMON - * - * This file is part of Devinsy-utils. - * - * Devinsy-utils is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Devinsy-utils is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see - */ -package fr.devinsy.util.unix; - -/** - * - * @author Christian Pierre MOMON (christian.momon@devinsy.fr) - */ -public class User -{ - // private static final Logger logger = LoggerFactory.getLogger(User.class); - - /* - * /usr/include/pwd.h - * - * The passwd structure. - * struct passwd - * { - * char *pw_name;D Username. - * char *pw_passwd; Password. - * __uid_t pw_uid; User ID. - * __gid_t pw_gid; Group ID. - * char *pw_gecos; Real name. - * char *pw_dir; Home directory. - * char *pw_shell; Shell program. - * }; - */ - - protected String login; - protected String password; - protected int uid; - protected int gid; - protected String realName; - protected String homeDirectory; - protected String shell; - - /** - * - */ - public User() - { - this.login = null; - this.password = null; - this.uid = -1; - this.gid = -1; - this.realName = null; - this.homeDirectory = null; - this.shell = null; - } - - /** - * - */ - public User(final User user) - { - this.login = user.login(); - this.password = user.passwd(); - this.uid = user.uid(); - this.gid = user.gid(); - this.realName = user.realName(); - this.homeDirectory = user.homeDirectory(); - this.shell = user.shell(); - } - - /** - * - */ - public int getGid() - { - int result; - - result = this.gid; - - // - return (result); - } - - /** - * - */ - public String getHomeDirectory() - { - String result; - - result = this.homeDirectory; - - // - return (result); - } - - /** - * - */ - public String getLogin() - { - String result; - - result = this.login; - - // - return (result); - } - - /** - * - */ - public String getPasswd() - { - String result; - - result = this.password; - - // - return (result); - } - - /** - * - */ - public String getPassword() - { - String result; - - result = this.password; - - // - return (result); - } - - /** - * - */ - public String getRealName() - { - String result; - - result = this.realName; - - // - return (result); - } - - /** - * - */ - public String getShell() - { - String result; - - result = this.shell; - - // - return (result); - } - - /** - * - */ - public int getUid() - { - int result; - - result = this.uid; - - // - return (result); - } - - /** - * - */ - public int gid() - { - int result; - - result = this.gid; - - // - return (result); - } - - /** - * - */ - public String homeDirectory() - { - String result; - - result = this.homeDirectory; - - // - return (result); - } - - /** - * - */ - public String login() - { - String result; - - result = this.login; - - // - return (result); - } - - /** - * - */ - public String passwd() - { - String result; - - result = this.password; - - // - return (result); - } - - /** - * - */ - public String realName() - { - String result; - - result = this.realName; - - // - return (result); - } - - /** - * - */ - public void setGid(final int gid) - { - this.gid = gid; - } - - /** - * - */ - public void setHomeDirectory(final String homeDirectory) - { - this.homeDirectory = homeDirectory; - } - - /** - * - */ - public void setLogin(final String login) - { - this.login = login; - } - - /** - * - */ - public void setPasswd(final String password) - { - this.password = password; - } - - /** - * - */ - public void setPassword(final String password) - { - this.password = password; - } - - /** - * - */ - public void setRealName(final String realName) - { - this.realName = realName; - } - - /** - * - */ - public void setShell(final String shell) - { - this.shell = shell; - } - - /** - * - */ - public void setUid(final int uid) - { - this.uid = uid; - } - - /** - * - */ - public String shell() - { - String result; - - result = this.shell; - - // - return (result); - } - - /** - * - */ - @Override - public String toString() - { - String result; - - result = "|" + this.login + "|" + this.password + "|" + this.uid + "|" + this.gid + "|" + this.realName + "|" + this.homeDirectory + "|" + this.shell + "|"; - - // - return (result); - } - - /** - * - */ - public int uid() - { - int result; - - result = this.uid; - - // - return (result); - } -} - -// //////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/src/fr/devinsy/util/unix/Users.java b/src/fr/devinsy/util/unix/Users.java deleted file mode 100644 index f33160c..0000000 --- a/src/fr/devinsy/util/unix/Users.java +++ /dev/null @@ -1,179 +0,0 @@ -/** - * Copyright (C) 2006-2010, 2013-2014 Christian Pierre MOMON - * - * This file is part of Devinsy-utils. - * - * Devinsy-utils is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Devinsy-utils is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see - */ -package fr.devinsy.util.unix; - -import java.util.Iterator; -import java.util.Vector; - -/** - * - * @author Christian Pierre MOMON (christian.momon@devinsy.fr) - */ -public class Users extends Vector -{ - private static final long serialVersionUID = -7178304512851592399L; - - // private static final Logger logger = - // LoggerFactory.getLogger(Users.class); - - /** - * - */ - public Users() - { - super(); - } - - /* - * - */ - public boolean contains(final int uid) - { - boolean result; - - if (getByUid(uid) == null) - { - result = false; - } - else - { - result = true; - } - - // - return (result); - } - - /* - * - */ - public boolean contains(final String login) - { - boolean result; - - if (getByLogin(login) == null) - { - result = false; - } - else - { - result = true; - } - - // - return (result); - } - - /** - * - */ - public User getByLogin(final String login) - { - User result; - - if (login == null) - { - result = null; - } - else - { - result = null; - boolean ended = false; - Iterator iterator = this.iterator(); - while (!ended) - { - if (iterator.hasNext()) - { - User user = iterator.next(); - if (user.getLogin().equals(login)) - { - ended = true; - result = user; - } - } - else - { - ended = true; - result = null; - } - } - } - - // - return (result); - } - - /** - * - */ - public User getByUid(final int uid) - { - User result; - - result = null; - boolean ended = false; - Iterator iterator = this.iterator(); - while (!ended) - { - if (iterator.hasNext()) - { - User user = iterator.next(); - if (user.getUid() == uid) - { - ended = true; - result = user; - } - } - else - { - ended = true; - result = null; - } - } - - // - return (result); - } - - /** - * - */ - @Override - public String toString() - { - String result; - - StringBuffer out; - out = new StringBuffer(); - - Iterator iterator = this.iterator(); - - while (iterator.hasNext()) - { - out.append(iterator.next().toString() + "\n"); - } - - result = out.toString(); - - // - return (result); - } -} - -// //////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/src/fr/devinsy/util/unix/acl/Acl.java b/src/fr/devinsy/util/unix/acl/Acl.java deleted file mode 100644 index 1f2f37c..0000000 --- a/src/fr/devinsy/util/unix/acl/Acl.java +++ /dev/null @@ -1,216 +0,0 @@ -/** - * Copyright (C) 2010, 2013-2014 Christian Pierre MOMON - * - * This file is part of Devinsy-utils. - * - * Devinsy-utils is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Devinsy-utils is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see - */ -package fr.devinsy.util.unix.acl; - -/** - * - * @author Christian Pierre MOMON (christian.momon@devinsy.fr) - */ -public class Acl -{ - // private static final Logger logger = LoggerFactory.getLogger(Acl.class); - - /* - # file: goo39 - # owner: goo39 - # group: goo39 - user::rwx - user:cpm:rwx #effective:rwx - user:goo39:rwx #effective:rwx - group::--- #effective:--- - group:goo40:rwx #effective:rwx - mask::rwx - other::--- - default:user::rwx - default:user:cpm:rwx #effective:rwx - default:group::--- #effective:--- - default:group:cpm:rwx #effective:rwx - default:group:goo40:rwx #effective:rwx - default:mask::rwx - default:other::--- - */ - - protected String filePathname; - protected String owner; - protected String group; - - protected AclEntries currentAcl; - protected AclEntries defaultAcl; - - /** - * - */ - public Acl(final String filePathname) - { - this.filePathname = filePathname; - this.owner = ""; - this.group = ""; - this.currentAcl = new AclEntries(); - this.defaultAcl = new AclEntries(); - } - - /** - * - */ - public boolean contains(final AclEntry.Type type, final String id) - { - boolean result; - - if ((this.currentAcl().contains(type, id)) || (this.defaultAcl().contains(type, id))) - { - result = true; - } - else - { - result = false; - } - - // - return (result); - } - - /** - * - */ - public boolean containsGroup(final String group) - { - boolean result; - - result = contains(AclEntry.Type.GROUP, group); - - // - return (result); - } - - /** - * - */ - public boolean containsId(final String id) - { - boolean result; - - if ((containsUser(id) || containsGroup(id))) - { - result = true; - } - else - { - result = false; - } - - // - return (result); - } - - /** - * - */ - public boolean containsUser(final String login) - { - boolean result; - - result = contains(AclEntry.Type.USER, login); - - // - return (result); - } - - /** - * - */ - public AclEntries currentAcl() - { - AclEntries result; - - result = this.currentAcl; - - // - return (result); - } - - /** - * - */ - public AclEntries defaultAcl() - { - AclEntries result; - - result = this.defaultAcl; - - // - return (result); - } - - /** - * - */ - public String filePathname() - { - String result; - - result = this.filePathname; - - // - return (result); - } - - /** - * - */ - public String group() - { - String result; - - result = this.group; - - // - return (result); - } - - /** - * - */ - public String owner() - { - String result; - - result = this.owner; - - // - return (result); - } - - /** - * - */ - public void setGroup(final String group) - { - this.group = group; - } - - /** - * - */ - public void setOwner(final String owner) - { - this.owner = owner; - } -} - -// //////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/src/fr/devinsy/util/unix/acl/AclEntries.java b/src/fr/devinsy/util/unix/acl/AclEntries.java deleted file mode 100644 index 580ab6f..0000000 --- a/src/fr/devinsy/util/unix/acl/AclEntries.java +++ /dev/null @@ -1,216 +0,0 @@ -/** - * Copyright (C) 2010, 2013-2014 Christian Pierre MOMON - * - * This file is part of Devinsy-utils. - * - * Devinsy-utils is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Devinsy-utils is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see - */ -package fr.devinsy.util.unix.acl; - -import java.util.Iterator; -import java.util.Vector; - -/** - * - * @author Christian Pierre MOMON (christian.momon@devinsy.fr) - */ -public class AclEntries extends Vector -{ - private static final long serialVersionUID = 5802487312198869603L; - - // private static final Logger logger = - // LoggerFactory.getLogger(AclEntries.class); - - /** - * - */ - public AclEntries() - { - super(); - } - - /* - * - */ - public boolean contains(final AclEntry.Type type, final String id) - { - boolean result; - - if (this.get(type, id) == null) - { - result = false; - } - else - { - result = true; - } - - // - return (result); - } - - /** - * - */ - public boolean containsId(final String id) - { - boolean result; - - if ((this.get(AclEntry.Type.USER, id) == null) && (this.get(AclEntry.Type.GROUP, id) == null)) - { - result = false; - } - else - { - result = true; - } - - // - return (result); - } - - /** - * - */ - public AclEntry get(final AclEntry.Type type, final String id) - { - AclEntry result; - - result = null; - boolean ended = false; - Iterator iterator = this.iterator(); - while (!ended) - { - if (iterator.hasNext()) - { - AclEntry entry = iterator.next(); - if ((type == entry.type()) && (entry.id().equals(id))) - { - ended = true; - result = entry; - } - } - else - { - ended = true; - result = null; - } - } - - // - return (result); - } - - /** - * - */ - public String[] getGroupIds() - { - String[] result; - - Vector ids = new Vector(); - - for (AclEntry entry : this) - { - if ((entry.type == AclEntry.Type.GROUP) && (!ids.contains(entry.id()))) - { - ids.add(entry.id()); - } - } - - result = (String[]) ids.toArray(); - - // - return (result); - } - - /** - * - */ - public String[] getIds() - { - String[] result; - - Vector ids = new Vector(); - - for (AclEntry entry : this) - { - if (!ids.contains(entry.id())) - { - ids.add(entry.id()); - } - } - - result = (String[]) ids.toArray(); - - // - return (result); - } - - /** - * - */ - public String[] getUserIds() - { - String[] result; - - // - Vector ids = new Vector(); - - for (AclEntry entry : this) - { - if ((entry.type == AclEntry.Type.USER) && (!ids.contains(entry.id()))) - { - ids.add(entry.id()); - } - } - - // - result = new String[ids.size()]; - - for (int nId = 0; nId < ids.size(); nId++) - { - result[nId] = ids.get(nId); - } - - // - return (result); - } - - /** - * - */ - @Override - public String toString() - { - String result; - - StringBuffer out; - out = new StringBuffer(); - - Iterator iterator = this.iterator(); - - while (iterator.hasNext()) - { - out.append(iterator.next().toString() + "\n"); - } - - result = out.toString(); - - // - return (result); - } -} - -// //////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/src/fr/devinsy/util/unix/acl/AclEntry.java b/src/fr/devinsy/util/unix/acl/AclEntry.java deleted file mode 100644 index 09e1eb3..0000000 --- a/src/fr/devinsy/util/unix/acl/AclEntry.java +++ /dev/null @@ -1,113 +0,0 @@ -/** - * Copyright (C) 2010, 2013-2014 Christian Pierre MOMON - * - * This file is part of Devinsy-utils. - * - * Devinsy-utils is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Devinsy-utils is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see - */ -package fr.devinsy.util.unix.acl; - -/** - * - * @author Christian Pierre MOMON (christian.momon@devinsy.fr) - */ -public class AclEntry -{ - // private static final Logger logger = - // LoggerFactory.getLogger(AclEntry.class); - - /* - user::rwx - user:cpm:rwx #effective:rwx - user:goo39:rwx #effective:rwx - group::--- #effective:--- - group:goo40:rwx #effective:rwx - mask::rwx - other::--- - */ - - public enum Type - { - NONE, USER, GROUP, MASK, OTHER - }; - - protected Type type; - protected String id; - protected String permission; - - /** - * - */ - public AclEntry(final Type type, final String id, final String permission) - { - this.type = type; - this.id = id; - this.permission = permission; - } - - /** - * - */ - public String id() - { - String result; - - result = this.id; - - // - return (result); - } - - /** - * - */ - public String permission() - { - String result; - - result = this.type.toString() + ":" + this.id + ":" + this.permission; - - // - return (result); - } - - /** - * - */ - @Override - public String toString() - { - String result; - - result = this.permission; - - // - return (result); - } - - /** - * - */ - public Type type() - { - Type result; - - result = this.type; - - // - return (result); - } -} - -// //////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/src/fr/devinsy/util/unix/acl/AclManager.java b/src/fr/devinsy/util/unix/acl/AclManager.java deleted file mode 100644 index 7484141..0000000 --- a/src/fr/devinsy/util/unix/acl/AclManager.java +++ /dev/null @@ -1,424 +0,0 @@ -/** - * Copyright (C) 2010, 2013-2015 Christian Pierre MOMON - * - * This file is part of Devinsy-utils. - * - * Devinsy-utils is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Devinsy-utils is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see - */ -package fr.devinsy.util.unix.acl; - -import java.io.File; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import fr.devinsy.util.cmdexec.CmdExec; -import fr.devinsy.util.strings.StringListUtils; -import fr.devinsy.util.unix.Unix; - -/** - * - * @author Christian Pierre MOMON (christian.momon@devinsy.fr) - */ -public class AclManager -{ - private static final Logger logger = LoggerFactory.getLogger(AclManager.class); - public static final String SUDO = "/usr/bin/sudo"; - - final static public Pattern USER_PATTERN = Pattern.compile("^user:(.*):(.*)$"); - final static public Pattern GROUP_PATTERN = Pattern.compile("^group:(.*):(.*)$"); - final static public Pattern MASK_PATTERN = Pattern.compile("^mask:(.*):(.*)$"); - final static public Pattern OTHER_PATTERN = Pattern.compile("^other:(.*):(.*)$"); - final static public Pattern DEFAULT_USER_PATTERN = Pattern.compile("^default:user:(.*):(.*)$"); - final static public Pattern DEFAULT_GROUP_PATTERN = Pattern.compile("^default:group:(.*):(.*)$"); - final static public Pattern DEFAULT_MASK_PATTERN = Pattern.compile("^default:mask:(.*):(.*)$"); - final static public Pattern DEFAULT_OTHER_PATTERN = Pattern.compile("^default:other:(.*):(.*)$"); - - /** - * - */ - public static void clearGroup(final String group, final String filePathName) throws Exception - { - if ((group == null) || (group.length() == 0) || (filePathName == null) || (filePathName.length() == 0)) - { - throw new Exception("Bad parameters [" + group + "][" + filePathName + "]."); - } - else - { - Unix.setfacl("-R", "-L", "-x", "group:" + group, filePathName); - Unix.setfacl("-R", "-L", "-d", "-x", "group:" + group, filePathName); - } - } - - /** - * - */ - public static void clearId(final String id, final String filePathName) throws Exception - { - clearUser(id, filePathName); - clearGroup(id, filePathName); - } - - /** - * - */ - public static void clearUser(final String login, final String filePathName) throws Exception - { - if ((login == null) || (login.length() == 0) || (filePathName == null) || (filePathName.length() == 0)) - { - throw new Exception("Bad parameters [" + login + "][" + filePathName + "]."); - } - else - { - Unix.setfacl("-R", "-L", "-x", "user:" + login, filePathName); - Unix.setfacl("-R", "-L", "-d", "-x", "user:" + login, filePathName); - } - } - - /** - * - */ - public static Acl getAcl(final String filePathName) throws Exception - { - Acl result; - - result = new Acl(filePathName); - - String[] entries = getAclEntryLines(filePathName); - - // Login pattern: "^[a-z_][a-z0-9_-]*$". - logger.debug("Line=[" + entries[1] + "]"); - Matcher matcher = Pattern.compile("^#\\sowner:\\s([a-z_][a-z0-9_-]*)$").matcher(entries[1]); - if (matcher.matches()) - { - logger.debug("group=[" + matcher.group(1) + "]"); - result.setOwner(matcher.group(1)); - } - - // Group pattern: "^[a-z_][a-z0-9_-]*$". - logger.debug("Line=[" + entries[2] + "]"); - matcher = Pattern.compile("^#\\sgroup:\\s([a-z_][a-z0-9_-]*)$").matcher(entries[2]); - if (matcher.matches()) - { - logger.debug("group=[" + matcher.group(1) + "]"); - result.setOwner(matcher.group(1)); - } - - for (int nEntry = 3; nEntry < entries.length; nEntry++) - { - String entryLine = entries[nEntry]; - logger.debug("Line=[" + entryLine + "]"); - - // - Matcher userMatcher = USER_PATTERN.matcher(entryLine); - Matcher groupMatcher = GROUP_PATTERN.matcher(entryLine); - Matcher maskMatcher = MASK_PATTERN.matcher(entryLine); - Matcher otherMatcher = OTHER_PATTERN.matcher(entryLine); - Matcher defaultUserMatcher = DEFAULT_USER_PATTERN.matcher(entryLine); - Matcher defaultGroupMatcher = DEFAULT_GROUP_PATTERN.matcher(entryLine); - Matcher defaultMaskMatcher = DEFAULT_MASK_PATTERN.matcher(entryLine); - Matcher defaultOtherMatcher = DEFAULT_OTHER_PATTERN.matcher(entryLine); - - AclEntry entry; - if (userMatcher.matches()) - { - entry = new AclEntry(AclEntry.Type.USER, userMatcher.group(1), userMatcher.group(2)); - result.currentAcl().add(entry); - } - else if (groupMatcher.matches()) - { - entry = new AclEntry(AclEntry.Type.GROUP, groupMatcher.group(1), groupMatcher.group(2)); - result.currentAcl().add(entry); - } - else if (maskMatcher.matches()) - { - entry = new AclEntry(AclEntry.Type.MASK, maskMatcher.group(1), maskMatcher.group(2)); - result.currentAcl().add(entry); - } - else if (otherMatcher.matches()) - { - entry = new AclEntry(AclEntry.Type.OTHER, otherMatcher.group(1), otherMatcher.group(2)); - result.currentAcl().add(entry); - } - else if (defaultUserMatcher.matches()) - { - entry = new AclEntry(AclEntry.Type.USER, defaultUserMatcher.group(1), defaultUserMatcher.group(2)); - result.defaultAcl().add(entry); - } - else if (defaultGroupMatcher.matches()) - { - entry = new AclEntry(AclEntry.Type.GROUP, defaultGroupMatcher.group(1), defaultGroupMatcher.group(2)); - result.defaultAcl().add(entry); - } - else if (defaultMaskMatcher.matches()) - { - entry = new AclEntry(AclEntry.Type.MASK, defaultMaskMatcher.group(1), defaultMaskMatcher.group(2)); - result.defaultAcl().add(entry); - } - else if (defaultOtherMatcher.matches()) - { - entry = new AclEntry(AclEntry.Type.OTHER, defaultOtherMatcher.group(1), defaultOtherMatcher.group(2)); - result.defaultAcl().add(entry); - } - else - { - throw new Exception("Unknow ACL entry line pattern for [" + entryLine + "]."); - } - - logger.debug("Acl entry decoded: [" + entry.toString() + "]"); - } - - // - return (result); - } - - /** - * - */ - public static String getAclData(final String filePathName) throws Exception - { - String result; - - try - { - logger.info("Getting Acl data for [" + filePathName + "]."); - result = CmdExec.run(SUDO, "/usr/bin/getfacl", "--no-effective", filePathName); - logger.info("Acl data got for [" + filePathName + "]."); - } - catch (Exception exception) - { - throw new Exception("Error getting ACL for [" + filePathName + "].", exception); - } - - // - return (result); - } - - /** - * - */ - public static String[] getAclEntryLines(final String filePathName) - { - String[] result; - - try - { - result = getAclData(filePathName).split("\n"); - } - catch (Exception exception) - { - result = new String[0]; - } - - // - return (result); - } - - /** - * - */ - public static boolean isUsed(final AclEntry.Type type, final String id, final String filePathName) throws Exception - { - boolean result; - - result = isUsed(type, id, filePathName, 0); - - // - return (result); - } - - /** - * - */ - public static boolean isUsed(final AclEntry.Type type, final String id, final String filePathName, final int depth) throws Exception - { - boolean result; - - if ((type == null) || (id == null) || (id.length() == 0) || (filePathName == null) || (filePathName.length() == 0) || (depth < 0)) - { - throw new Exception("Bad parameter: [" + type + "][" + id + "][" + filePathName + "][" + depth + "]."); - } - else - { - File file = new File(filePathName); - if (!file.exists()) - { - throw new Exception("File does not exist [" + filePathName + "]."); - } - else - { - Acl acl = getAcl(filePathName); - if (acl.contains(type, id)) - { - result = true; - } - else if ((file.isDirectory()) && (depth > 0)) - { - result = isUsed(type, id, filePathName, file.list(), depth - 1); - } - else - { - result = false; - } - } - } - - // - return (result); - } - - /** - * - */ - public static boolean isUsed(final AclEntry.Type type, final String id, final String filePath, final String[] filePathNames, final int depth) throws Exception - { - boolean result; - - result = false; - boolean ended = false; - int nLine = 0; - while (!ended) - { - if (nLine < filePathNames.length) - { - String filePathName = filePathNames[nLine]; - if (isUsed(type, id, filePath + "/" + filePathName, depth)) - { - ended = true; - result = true; - } - else - { - nLine += 1; - } - } - else - { - ended = true; - result = false; - } - } - - // - return (result); - } - - /** - * - */ - public static boolean isUsed(final String id, final String filePathName) throws Exception - { - boolean result; - - result = isUsed(id, filePathName, 0); - - // - return (result); - } - - /** - * - */ - public static boolean isUsed(final String id, final String filePathName, final int depth) throws Exception - { - boolean result; - - if ((id == null) || (id.length() == 0) || (filePathName == null) || (filePathName.length() == 0) || (depth < 0)) - { - throw new Exception("Bad parameter: [" + id + "][" + filePathName + "][" + depth + "]."); - } - else - { - File file = new File(filePathName); - if (!file.exists()) - { - throw new Exception("File does not exist [" + filePathName + "]."); - } - else - { - Acl acl = getAcl(filePathName); - if (acl.containsId(id)) - { - result = true; - } - else if ((file.isDirectory()) && (depth > 0)) - { - result = isUsed(id, file.list(), depth - 1); - } - else - { - result = false; - } - } - } - - // - return (result); - } - - /** - * - */ - public static boolean isUsed(final String id, final String[] filePathNames, final int depth) throws Exception - { - boolean result; - - result = false; - boolean ended = false; - int nLine = 0; - while (!ended) - { - if (nLine < filePathNames.length) - { - String filePathName = filePathNames[nLine]; - if (isUsed(id, filePathName, depth)) - { - ended = true; - result = true; - } - else - { - nLine += 1; - } - } - else - { - ended = true; - result = false; - } - } - - // - return (result); - } - - /** - * - */ - public static void setfacl(final String... args) throws Exception - { - try - { - CmdExec.run(SUDO, "setfacl", args, 1, 5); - } - catch (Exception exception) - { - throw new Exception("Error running setfacl command for " + StringListUtils.toStringWithBrackets(args) + ":" + exception.getMessage() + "."); - } - } -} - -// //////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/src/fr/devinsy/util/xml/XMLAttributes.java b/src/fr/devinsy/util/xml/XMLAttributes.java deleted file mode 100644 index 640185f..0000000 --- a/src/fr/devinsy/util/xml/XMLAttributes.java +++ /dev/null @@ -1,160 +0,0 @@ -/** - * Copyright (C) 2013-2014 Christian Pierre MOMON - * - * This file is part of Devinsy-utils. - * - * Devinsy-utils is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Devinsy-utils is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see - */ -package fr.devinsy.util.xml; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Set; - -import javax.xml.stream.events.Attribute; - -/** - * - * @author Christian Pierre MOMON (christian.momon@devinsy.fr) - */ -public class XMLAttributes extends HashMap implements Iterable -{ - - private static final long serialVersionUID = 8456469741805779474L; - - /** - * - */ - public XMLAttributes() - { - super(); - } - - /** - * - */ - public XMLAttributes(final int capacity) - { - super(capacity); - } - - /** - * - */ - public XMLAttributes(final Iterator source) - { - super(); - if (source != null) - { - while (source.hasNext()) - { - Attribute attribute = source.next(); - - add(attribute); - } - } - } - - /** - * - */ - public XMLAttributes(final XMLAttributes source) - { - super(); - addAll(source); - } - - /** - * - * @param attribute - */ - public void add(final Attribute attribute) - { - if (attribute != null) - { - put(attribute.getName().getLocalPart(), attribute); - } - } - - /** - * - * @param source - */ - public void addAll(final XMLAttributes source) - { - for (Attribute attribute : source) - { - this.add(attribute); - } - } - - /** - * - * @param label - * @return - */ - public Attribute getByLabel(final String label) - { - Attribute result; - - result = get(label); - - // - return result; - } - - /** - * - */ - @Override - public Iterator iterator() - { - Iterator result; - - result = this.values().iterator(); - - // - return result; - } - - /** - * - * @return - */ - public Set labels() - { - Set result; - - result = this.keySet(); - - // - return result; - } - - /** - * - * @return - */ - public List toList() - { - List result; - - result = new ArrayList(values()); - - // - return result; - } -} diff --git a/src/fr/devinsy/util/xml/XMLBadFormatException.java b/src/fr/devinsy/util/xml/XMLBadFormatException.java deleted file mode 100644 index 268c1f0..0000000 --- a/src/fr/devinsy/util/xml/XMLBadFormatException.java +++ /dev/null @@ -1,81 +0,0 @@ -/** - * Copyright (C) 2013-2014 Christian Pierre MOMON - * - * This file is part of Devinsy-utils. - * - * Devinsy-utils is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Devinsy-utils is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see - */ -package fr.devinsy.util.xml; - -import org.slf4j.helpers.MessageFormatter; - -/** - * - * @author Christian Pierre MOMON (christian.momon@devinsy.fr) - */ -public class XMLBadFormatException extends Exception -{ - - private static final long serialVersionUID = 768256303984176512L; - - /** - * - * @param code - * @param message - */ - public XMLBadFormatException(final String message) - { - super(message); - } - - /** - * - * @param code - * @param message - * @param exception - */ - public XMLBadFormatException(final String message, final Exception exception) - { - super(message, exception); - } - - /** - * - * @param format - * @param arguments - */ - public XMLBadFormatException(final String format, final Object... arguments) - { - this(MessageFormatter.arrayFormat(format, arguments).getMessage()); - } - - /** - * - * @param message - * @param cause - */ - public XMLBadFormatException(final String message, final Throwable cause) - { - super(message, cause); - } - - /** - * - * @param cause - */ - public XMLBadFormatException(final Throwable cause) - { - super(cause); - } -} diff --git a/src/fr/devinsy/util/xml/XMLReader.java b/src/fr/devinsy/util/xml/XMLReader.java deleted file mode 100644 index 57dd535..0000000 --- a/src/fr/devinsy/util/xml/XMLReader.java +++ /dev/null @@ -1,617 +0,0 @@ -/** - * Copyright (C) 2013-2014 Christian Pierre MOMON - * Copyright (C) 2017 Christian Pierre MOMON - * - * This file is part of Devinsy-utils. - * - * Devinsy-utils is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Devinsy-utils is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see - */ -package fr.devinsy.util.xml; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.InputStream; -import java.io.Reader; - -import javax.xml.namespace.QName; -import javax.xml.stream.XMLEventReader; -import javax.xml.stream.XMLInputFactory; -import javax.xml.stream.XMLStreamException; -import javax.xml.stream.events.XMLEvent; - -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import fr.devinsy.util.strings.StringList; -import fr.devinsy.util.xml.XMLTag.TagType; - -/** - * - * @author Christian Pierre MOMON (christian.momon@devinsy.fr) - */ -public class XMLReader -{ - private static final Logger logger = LoggerFactory.getLogger(XMLReader.class); - - protected XMLEventReader in; - private XMLEvent nextEvent; - - /** - * - */ - protected XMLReader() - { - this.in = null; - this.nextEvent = null; - } - - /** - * - * @param file - * @throws XMLStreamException - * @throws FileNotFoundException - */ - public XMLReader(final File file) throws FileNotFoundException, XMLStreamException - { - this.nextEvent = null; - XMLInputFactory factory = XMLInputFactory.newInstance(); - this.in = factory.createXMLEventReader(new FileInputStream(file), "UTF-8"); - } - - /** - * - * @param target - * @throws XMLStreamException - */ - public XMLReader(final InputStream source) throws XMLStreamException - { - this.nextEvent = null; - XMLInputFactory factory = XMLInputFactory.newInstance(); - this.in = factory.createXMLEventReader(source); - } - - /** - * - * @param target - * @throws XMLStreamException - */ - public XMLReader(final Reader source) throws XMLStreamException - { - this.nextEvent = null; - XMLInputFactory factory = XMLInputFactory.newInstance(); - this.in = factory.createXMLEventReader(source); - } - - /** - * @throws XMLStreamException - */ - public void close() throws XMLStreamException - { - if (this.in != null) - { - this.in.close(); - } - } - - /** - * This methods does a premonition act. Useful to detect end of a list. - * - * @param label - * @return - * @throws XMLStreamException - */ - public boolean hasNextStartTag(final String label) throws XMLStreamException - { - boolean result; - - // Load next event. - if (this.nextEvent == null) - { - if (this.in.hasNext()) - { - this.nextEvent = this.in.nextEvent(); - } - } - - // Analyze next event. - if (this.nextEvent == null) - { - result = false; - } - else if ((this.nextEvent.isStartElement()) && (StringUtils.equals(this.nextEvent.asStartElement().getName().getLocalPart(), label))) - { - result = true; - } - else - { - result = false; - } - - // - return result; - } - - /** - * - * @param label - * @return - * @throws XMLBadFormatException - * @throws XMLStreamException - */ - public XMLTag readContentTag(final String label) throws XMLBadFormatException, XMLStreamException - { - XMLTag result; - - // - result = readTag(); - - // - if (result == null) - { - throw new XMLBadFormatException("XML file ends prematurely, content tag [" + label + "] is expected."); - } - else if (result.getType() != TagType.CONTENT) - { - throw new XMLBadFormatException("Content tag [" + label + "] is missing."); - } - else if (!StringUtils.equals(label, result.getLabel())) - { - throw new XMLBadFormatException("Tag with label [" + label + "] is missing."); - } - - // - return result; - } - - /** - * - * @param label - * @return - * @throws XMLStreamException - * @throws XMLBadFormatException - */ - public XMLTag readEndTag(final String label) throws XMLStreamException, XMLBadFormatException - { - XMLTag result; - - // - result = readTag(); - - // - if (result == null) - { - throw new XMLBadFormatException("XML file ends prematurely, end tag [" + label + "] is expected."); - } - else if (result.getType() != TagType.END) - { - throw new XMLBadFormatException("End tag [" + label + "] is missing."); - } - else if (!StringUtils.equals(result.getLabel(), label)) - { - throw new XMLBadFormatException("Tag with label [" + label + "] is missing."); - } - - // - return result; - } - - /** - * - * @param label - * @return - * @throws XMLStreamException - * @throws XMLBadFormatException - * @throws Exception - */ - public XMLTag readListTag(final String label) throws XMLStreamException, XMLBadFormatException - { - XMLTag result; - - // - result = readTag(); - - // - if (result == null) - { - throw new XMLBadFormatException("XML file ends prematurely, tag [" + label + "] is expected."); - } - else if ((result.getType() != TagType.START) && (result.getType() != TagType.EMPTY)) - { - throw new XMLBadFormatException("List tag [" + label + "] is missing."); - } - else if (!StringUtils.equals(label, result.getLabel())) - { - throw new XMLBadFormatException("Tag with label [" + label + "] is missing."); - } - - // - return result; - } - - /** - * - * @param label - * @return - * @throws XMLStreamException - * @throws XMLBadFormatException - * @throws Exception - */ - public XMLTag readNullableContentTag(final String label) throws XMLStreamException, XMLBadFormatException - { - XMLTag result; - - // - result = readTag(); - - // - if (result == null) - { - throw new XMLBadFormatException("XML file ends prematurely, tag [" + label + "] is expected."); - } - else if (!StringUtils.equals(label, result.getLabel())) - { - throw new XMLBadFormatException("Nullable content tag [" + label + "] is missing."); - } - else if ((result.getType() != TagType.EMPTY) && (result.getType() != TagType.CONTENT)) - { - throw new XMLBadFormatException("Nullable content tag [" + label + "] is missing."); - } - - // - return result; - } - - /** - * - * @param label - * @return - * @throws XMLStreamException - * @throws XMLBadFormatException - * @throws Exception - */ - public XMLTag readNullableStartTag(final String label) throws XMLStreamException, XMLBadFormatException - { - XMLTag result; - - // - result = readTag(); - - // - if (result == null) - { - throw new XMLBadFormatException("XML file ends prematurely, start tag [" + label + "] is expected."); - } - else if ((result.getType() != TagType.START) && (result.getType() != TagType.EMPTY)) - { - throw new XMLBadFormatException("Start tag [" + label + "] is missing."); - } - else if (!StringUtils.equals(result.getLabel(), label)) - { - throw new XMLBadFormatException("Tag with label [" + label + "] is missing."); - } - - // - return result; - } - - /** - * - * @param label - * @return - * @throws XMLStreamException - * @throws XMLBadFormatException - * @throws Exception - */ - public XMLTag readStartTag(final String label) throws XMLStreamException, XMLBadFormatException - { - XMLTag result; - - // - result = readTag(); - - // - if (result == null) - { - throw new XMLBadFormatException("XML file ends prematurely, start tag [" + label + "] is expected."); - } - else if (result.getType() != TagType.START) - { - throw new XMLBadFormatException("Start tag [" + label + "] is missing."); - } - else if (!StringUtils.equals(result.getLabel(), label)) - { - throw new XMLBadFormatException("Tag with label [" + label + "] is missing."); - } - - // - return result; - } - - /** - * Transducer graph : - *
    - *
  • START_DOCUMENT => HEADER TAG - *
  • START_ELEMENT(X) + START_ELEMENT(Y) => => START TAG - *
  • START_ELEMENT(X) + CHARACTERS(C) + START_ELEMENT(Y) => SPACES=> - * START TAG - *
  • START_ELEMENT(X) + CHARACTERS(C) + END_ELEMENT(X) => C => - * CONTENT TAG - *
  • START_ELEMENT(X) + END_ELEMENT(X) => => => EMPTY - *
  • END_ELEMENT(X) => => END TAG - *
  • END_DOCUMENT => FOOTER TAG - *
- * - * @throws XMLStreamException - * @throws XMLBadFormatException - * - */ - public XMLTag readTag() throws XMLStreamException, XMLBadFormatException - { - XMLTag result; - - int level = 1; - boolean ended = false; - result = null; - XMLAttributes attributesBuffer = null; - QName nameBuffer = null; - StringList contentBuffer = null; - while (!ended) - { - // - XMLEvent event; - if (this.nextEvent != null) - { - event = this.nextEvent; - this.nextEvent = null; - } - else if (this.in.hasNext()) - { - event = this.in.nextEvent(); - } - else - { - event = null; - } - - if (event == null) - { - ended = true; - result = null; - } - else - { - logger.debug("eventType=" + XMLTools.toString(event)); - switch (level) - { - case 1: - switch (event.getEventType()) - { - case XMLEvent.START_DOCUMENT: - // START_DOCUMENT => START DOCUMENT TAG - ended = true; - result = new XMLTag(null, TagType.HEADER, null); - break; - case XMLEvent.START_ELEMENT: - // START_ELEMENT(X) => ... - nameBuffer = event.asStartElement().getName(); - attributesBuffer = new XMLAttributes(event.asStartElement().getAttributes()); - level += 1; - break; - case XMLEvent.END_ELEMENT: - // END_ELEMENT(X) => => END TAG - ended = true; - result = new XMLTag(event.asEndElement().getName(), TagType.END, null); - break; - case XMLEvent.END_DOCUMENT: - // END_DOCUMENT => END DOCUMENT TAG - ended = true; - result = new XMLTag(null, TagType.FOOTER, null); - break; - } - break; - case 2: - switch (event.getEventType()) - { - case XMLEvent.START_ELEMENT: - // START_ELEMENT(X) + START_ELEMENT(Y) => - // => START TAG - ended = true; - result = new XMLTag(nameBuffer, TagType.START, attributesBuffer); - this.nextEvent = event; - break; - case XMLEvent.CHARACTERS: - // START_ELEMENT(X) + CHARACTERS(C) => ... - contentBuffer = new StringList(50); - contentBuffer.append(event.asCharacters().getData()); - level += 1; - break; - case XMLEvent.END_ELEMENT: - // START_ELEMENT(X) + END_ELEMENT(X) => - // => => EMPTY - ended = true; - result = new XMLTag(nameBuffer, TagType.EMPTY, attributesBuffer); - break; - default: - throw new XMLBadFormatException("Unexpected XMLEvent [" + event.getEventType() + "]."); - } - break; - case 3: - switch (event.getEventType()) - { - case XMLEvent.START_ELEMENT: - // START_ELEMENT(X) + CHARACTERS(C) + - // START_ELEMENT(Y) => - // SPACES => START TAG - ended = true; - result = new XMLTag(nameBuffer, TagType.START, attributesBuffer); - this.nextEvent = event; - break; - case XMLEvent.CHARACTERS: - // START_ELEMENT(X) + CHARACTERS(C1) + - // CHARACTERS(C2)=> ... - contentBuffer.append(event.asCharacters().getData()); - break; - case XMLEvent.END_ELEMENT: - // START_ELEMENT(X) + CHARACTERS(C) + - // END_ELEMENT(X) => C - // => CONTENT TAG - ended = true; - result = new XMLTag(nameBuffer, TagType.CONTENT, attributesBuffer); - result.setContent(contentBuffer.toString()); - break; - default: - throw new XMLBadFormatException("Unexpected XMLEvent [" + event.getEventType() + "]."); - } - break; - default: - throw new XMLBadFormatException("Unexpected level [" + level + "]."); - } - } - } - - logger.debug("=> " + XMLTools.toString(result)); - - // - return result; - } - - /** - * - * @param label - * @return - * @throws XMLStreamException - * @throws XMLBadFormatException - */ - public XMLTag readXMLFooter() throws XMLStreamException, XMLBadFormatException - { - XMLTag result; - - // - result = readTag(); - - // - if (result == null) - { - throw new XMLBadFormatException("XML file ends prematurely, end document event is expected."); - } - else if (result.getType() != TagType.FOOTER) - { - throw new XMLBadFormatException("End document tag is missing."); - } - - // - return result; - } - - /** - * - * @return - * @throws XMLException - * @throws XMLStreamException - * @throws XMLBadFormatException - */ - public XMLTag readXMLHeader() throws XMLStreamException, XMLBadFormatException - { - XMLTag result; - - // - result = readTag(); - - // - if (result == null) - { - throw new XMLBadFormatException("XML file ends prematurely, start document event is expected."); - } - else if (result.getType() != TagType.HEADER) - { - throw new XMLBadFormatException("XML header is missing."); - } - - // - return result; - } - - /** - * - * @param args - * @throws Exception - */ - public static void main(final String args[]) throws Exception - { - - XMLInputFactory factory = XMLInputFactory.newInstance(); - XMLEventReader in = factory.createXMLEventReader(new FileReader("/home/cpm/C/Puck/Dev/Puck/test/TT/t3.puc")); - - XMLEvent event; - while (in.hasNext()) - { - event = in.nextEvent(); - - switch (event.getEventType()) - { - case XMLEvent.ATTRIBUTE: - System.out.println("ATTRIBUTE "); - break; - case XMLEvent.CDATA: - System.out.println("CDATA"); - break; - case XMLEvent.CHARACTERS: - System.out.println("CHARACTERS [" + event.asCharacters().getData() + "]"); - break; - case XMLEvent.COMMENT: - System.out.println("COMMENT"); - break; - case XMLEvent.DTD: - System.out.println("DTD"); - break; - case XMLEvent.END_DOCUMENT: - System.out.println("END_DOCUMENT"); - break; - case XMLEvent.END_ELEMENT: - System.out.println("END_ELEMENT " + event.asEndElement().getName()); - break; - case XMLEvent.ENTITY_DECLARATION: - System.out.println("ENTITY_DECLARATION"); - break; - case XMLEvent.ENTITY_REFERENCE: - System.out.println("ENTITY_REFERENCE"); - break; - case XMLEvent.NAMESPACE: - System.out.println("NAMESPACE"); - break; - case XMLEvent.NOTATION_DECLARATION: - System.out.println("NOTATION_DECLARATION"); - break; - case XMLEvent.PROCESSING_INSTRUCTION: - System.out.println("PROCESSING_INSTRUCTION"); - break; - case XMLEvent.SPACE: - System.out.println("SPACE"); - break; - case XMLEvent.START_DOCUMENT: - System.out.println("START_DOCUMENT"); - break; - case XMLEvent.START_ELEMENT: - System.out.println("START_ELEMENT [name=" + event.asStartElement().getName() + "][namespaceURI=" + event.asStartElement().getName().getNamespaceURI() + "][prefix=" - + event.asStartElement().getName().getPrefix() + "][localPart=" + event.asStartElement().getName().getLocalPart() + "]"); - break; - default: - System.out.println("DEFAULT"); - } - } - } -} diff --git a/src/fr/devinsy/util/xml/XMLTag.java b/src/fr/devinsy/util/xml/XMLTag.java deleted file mode 100644 index 806f754..0000000 --- a/src/fr/devinsy/util/xml/XMLTag.java +++ /dev/null @@ -1,148 +0,0 @@ -/** - * Copyright (C) 2013-2014 Christian Pierre MOMON - * - * This file is part of Devinsy-utils. - * - * Devinsy-utils is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Devinsy-utils is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see - */ -package fr.devinsy.util.xml; - -import javax.xml.namespace.QName; - -/** - * - * @author Christian Pierre MOMON (christian.momon@devinsy.fr) - */ -public class XMLTag -{ - - public enum TagType - { - HEADER, START, END, EMPTY, CONTENT, FOOTER - } - - private QName name; - private TagType type; - private XMLAttributes attributes; - private String content; - - /** - * - */ - public XMLTag(final QName name, final TagType type, final XMLAttributes attributes) - { - this.name = name; - this.type = type; - this.attributes = attributes; - this.content = null; - } - - public XMLAttributes attributes() - { - return this.attributes; - } - - public String getContent() - { - return this.content; - } - - /** - * - * @return - */ - public String getLabel() - { - String result; - - if (this.name == null) - { - result = ""; - } - else - { - result = this.name.getLocalPart(); - } - - // - return result; - } - - public QName getName() - { - return this.name; - } - - /** - * - * @return - */ - public String getNamespaceURI() - { - String result; - - if (this.name == null) - { - result = ""; - } - else - { - result = this.name.getNamespaceURI(); - } - - // - return result; - } - - /** - * - * @return - */ - public String getPrefix() - { - String result; - - if (this.name == null) - { - result = ""; - } - else - { - result = this.name.getPrefix(); - } - - // - return result; - } - - public TagType getType() - { - return this.type; - } - - public void setContent(final String content) - { - this.content = content; - } - - public void setName(final QName name) - { - this.name = name; - } - - public void setType(final TagType type) - { - this.type = type; - } -} diff --git a/src/fr/devinsy/util/xml/XMLTools.java b/src/fr/devinsy/util/xml/XMLTools.java deleted file mode 100644 index a7de117..0000000 --- a/src/fr/devinsy/util/xml/XMLTools.java +++ /dev/null @@ -1,389 +0,0 @@ -/** - * Copyright (C) 2013-2014 Christian Pierre MOMON - * - * This file is part of Devinsy-utils. - * - * Devinsy-utils is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Devinsy-utils is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see - */ -package fr.devinsy.util.xml; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.zip.ZipInputStream; - -import javax.xml.stream.events.XMLEvent; -import javax.xml.transform.sax.SAXSource; -import javax.xml.transform.stream.StreamSource; -import javax.xml.validation.Schema; -import javax.xml.validation.SchemaFactory; -import javax.xml.validation.Validator; - -import org.apache.commons.lang3.StringEscapeUtils; -import org.apache.commons.lang3.StringUtils; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; - -/** - * - * @author Christian Pierre MOMON (christian.momon@devinsy.fr) - */ -public class XMLTools -{ - /** - * - * @param source - * @return - */ - public static String escapeXmlBlank(final String source) - { - String result; - - if (StringUtils.isBlank(source)) - { - result = ""; - } - else - { - result = StringEscapeUtils.escapeXml(source); - } - - // - return result; - } - - /** - * - * - * @param source - * @throws SAXException - * @throws IOException - * @throws PuckException - */ - public static boolean isValid(final File xmlFile, final File xsdFile) throws SAXException, IOException - { - boolean result; - - // - InputStream xmlSource; - if (isZipFile(xmlFile)) - { - ZipInputStream zin = new ZipInputStream(new FileInputStream(xmlFile)); - zin.getNextEntry(); - xmlSource = zin; - } - else - { - xmlSource = new FileInputStream(xmlFile); - } - - // - result = isValid(xmlSource, new FileInputStream(xsdFile)); - - // - return result; - } - - /** - * - * - * @param source - * @throws SAXException - * @throws IOException - * @throws PuckException - */ - public static boolean isValid(final File xmlFile, final InputStream xsdSource) throws SAXException, IOException - { - boolean result; - - // - InputStream xmlSource; - if (isZipFile(xmlFile)) - { - ZipInputStream zin = new ZipInputStream(new FileInputStream(xmlFile)); - zin.getNextEntry(); - xmlSource = zin; - } - else - { - xmlSource = new FileInputStream(xmlFile); - } - - // - result = isValid(xmlSource, xsdSource); - - // - return result; - } - - /** - * - * - * @param source - * @throws SAXException - * @throws IOException - * @throws PuckException - */ - public static boolean isValid(final InputStream xmlSource, final InputStream xsdSource) throws SAXException, IOException - { - boolean result; - - if (xmlSource == null) - { - result = false; - } - else - { - try - { - // - SchemaFactory factory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema"); - InputSource sourceentree = new InputSource(xsdSource); - SAXSource sourceXSD = new SAXSource(sourceentree); - Schema schema = factory.newSchema(sourceXSD); - Validator validator = schema.newValidator(); - - // - validator.validate(new StreamSource(xmlSource)); - result = true; - - } - catch (final IllegalArgumentException exception) - { - exception.printStackTrace(); - result = false; - } - } - - // - return result; - } - - /** - * - * @param file - * @return - * @throws IOException - */ - public static boolean isZipFile(final File file) throws IOException - { - boolean result; - - // - byte[] buffer = new byte[4]; - FileInputStream is = null; - try - { - is = new FileInputStream(file); - is.read(buffer); - } - finally - { - if (is != null) - { - is.close(); - } - } - - // 50 4B 3 4 - if ((buffer[0] == 0x50) && (buffer[1] == 0x4B) && (buffer[2] == 0x03) && (buffer[3] == 0x04)) - { - result = true; - } - else - { - result = false; - } - - // - return result; - } - - /** - * - */ - public static String readTag(final BufferedReader in) throws Exception - { - String result; - - Pattern TAG_PATTERN = Pattern.compile("^<([\\w-_\\.]+)>.*$"); - Pattern SHORT_TAG_PATTERN = Pattern.compile("^<.+/>$"); - - result = in.readLine(); - boolean ended = false; - while (!ended) - { - /* - * DEBUG Matcher tagMatcher2 = TAG_PATTERN.matcher(result); if - * (tagMatcher2.find()) { logger.info("group count,0,1,2 = [" + - * tagMatcher2.groupCount() + "][" + tagMatcher2.group(0) + "][" + - * tagMatcher2.group(1) + "][" + tagMatcher2.group(2) + "]"); } - */ - - Matcher tagMatcher = TAG_PATTERN.matcher(result); - Matcher shortTagMatcher = SHORT_TAG_PATTERN.matcher(result); - - if ((tagMatcher.find()) && (tagMatcher.groupCount() == 2) && (tagMatcher.group(1).equals(tagMatcher.group(2)))) - { - ended = true; - } - else if (shortTagMatcher.matches()) - { - ended = true; - } - else - { - result += in.readLine(); - } - } - - // - return (result); - } - - /** - * - * @param source - * @return - */ - public static String toHTLM5(final String source) - { - String result; - - if (StringUtils.isBlank(source)) - { - result = ""; - } - else - { - result = source.replace(" ", " "); - } - - // - return result; - } - - /** - * - * @param value - * @return - */ - public static String toString(final XMLEvent source) - { - String result; - - switch (source.getEventType()) - { - case XMLEvent.ATTRIBUTE: - result = "ATTRIBUTE "; - break; - case XMLEvent.CDATA: - result = "CDATA"; - break; - case XMLEvent.CHARACTERS: - result = "CHARACTERS [" + source.asCharacters().getData() + "]"; - break; - case XMLEvent.COMMENT: - result = "COMMENT"; - break; - case XMLEvent.DTD: - result = "DTD"; - break; - case XMLEvent.END_DOCUMENT: - result = "END_DOCUMENT"; - break; - case XMLEvent.END_ELEMENT: - result = "END_ELEMENT " + source.asEndElement().getName(); - break; - case XMLEvent.ENTITY_DECLARATION: - result = "ENTITY_DECLARATION"; - break; - case XMLEvent.ENTITY_REFERENCE: - result = "ENTITY_REFERENCE"; - break; - case XMLEvent.NAMESPACE: - result = "NAMESPACE"; - break; - case XMLEvent.NOTATION_DECLARATION: - result = "NOTATION_DECLARATION"; - break; - case XMLEvent.PROCESSING_INSTRUCTION: - result = "PROCESSING_INSTRUCTION"; - break; - case XMLEvent.SPACE: - result = "SPACE"; - break; - case XMLEvent.START_DOCUMENT: - result = "START_DOCUMENT"; - break; - case XMLEvent.START_ELEMENT: - result = "START_ELEMENT [name=" + source.asStartElement().getName() + "][namespaceURI=" + source.asStartElement().getName().getNamespaceURI() + "][prefix=" - + source.asStartElement().getName().getPrefix() + "][localPart=" + source.asStartElement().getName().getLocalPart() + "]"; - break; - default: - result = null; - } - - // - return result; - } - - /** - * - * @param event - * @return - */ - public static String toString(final XMLTag source) - { - String result; - - if (source == null) - { - result = "null"; - } - else - { - result = "[label=" + source.getLabel() + "][type=" + source.getType().toString() + "][content=" + source.getContent() + "]"; - } - - // - return result; - } - - /** - * - * @param source - * @return - */ - public static String unescapeXmlBlank(final String source) - { - String result; - - if (StringUtils.isBlank(source)) - { - result = null; - } - else - { - result = StringEscapeUtils.unescapeXml(source); - } - - // - return result; - } -} diff --git a/src/fr/devinsy/util/xml/XMLWriter.java b/src/fr/devinsy/util/xml/XMLWriter.java deleted file mode 100644 index d5b41ec..0000000 --- a/src/fr/devinsy/util/xml/XMLWriter.java +++ /dev/null @@ -1,315 +0,0 @@ -/** - * Copyright (C) 2013-2014 Christian Pierre MOMON - * - * This file is part of Devinsy-utils. - * - * Devinsy-utils is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Devinsy-utils is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see - */ -package fr.devinsy.util.xml; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; -import java.io.UnsupportedEncodingException; -import java.io.Writer; - -import org.apache.commons.lang3.ArrayUtils; - -/** - * - * @author Christian Pierre MOMON (christian.momon@devinsy.fr) - */ -public class XMLWriter -{ - - protected PrintWriter out; - - /** - * Default constructor (useful for extend this class). - */ - protected XMLWriter() - { - this.out = null; - } - - /** - * Initialize a XML Writer to a file. - * - * @param file - * Where write the XML data. - * - * @throws FileNotFoundException - * @throws UnsupportedEncodingException - */ - public XMLWriter(final File file) throws UnsupportedEncodingException, FileNotFoundException - { - this.out = new PrintWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF-8")); - } - - /** - * Initialize a XML Writer to a OutputStream. - * - * @param target - * Where write the XML data. - * - * @throws UnsupportedEncodingException - */ - public XMLWriter(final OutputStream target) throws UnsupportedEncodingException - { - this.out = new PrintWriter(new OutputStreamWriter(target, "UTF-8")); - } - - /** - * Initialize a XML Writer to a Writer. - * - * @param target - * Where write the XML data. - * - * @throws UnsupportedEncodingException - */ - public XMLWriter(final Writer target) throws UnsupportedEncodingException - { - this.out = new PrintWriter(target); - } - - /** - * This method closes the target stream. - */ - public void close() throws IOException - { - if (this.out != null) - { - this.out.flush(); - this.out.close(); - } - } - - /** - * This method flushes the target stream. - */ - public void flush() throws IOException - { - if (this.out != null) - { - this.out.flush(); - } - } - - /** - * This method writes a XML comment. - * - * @param comment - * The comment to write. - */ - public void writeComment(final String comment) - { - this.out.print(""); - } - - /** - * This method writes a XML tag with no content. - */ - public void writeEmptyTag(final String label, final String... attributes) - { - this.out.print("<"); - this.out.print(label); - writeTagAttributes(attributes); - this.out.print("/>"); - } - - /** - * This method writes a XML ender tag. - */ - public void writeEndTag(final String label) - { - this.out.print(""); - } - - /** - * This method writes a XML start tag. - */ - public void writeStartTag(final String label, final String... attributes) - { - this.out.print("<"); - this.out.print(label); - writeTagAttributes(attributes); - this.out.print(">"); - } - - /** - * This method write a XML tag with attributes and boolean content data. - * - * @param label - * @param content - * @param attributes - */ - public void writeTag(final String label, final boolean content, final String... attributes) - { - writeStartTag(label, attributes); - writeTagContent(String.valueOf(content)); - writeEndTag(label); - } - - /** - * This method write a XML tag with attributes and long content data. - * - * @param label - * @param content - * @param attributes - */ - public void writeTag(final String label, final long content, final String... attributes) - { - writeStartTag(label, attributes); - writeTagContent(String.valueOf(content)); - writeEndTag(label); - } - - /** - * This method write a XML tag with attributes and content data. Content - * data are converted in XML format. - * - * @param label - * @param content - * @param attributes - */ - public void writeTag(final String label, final String content, final String... attributes) - { - if (content == null) - { - writeEmptyTag(label, attributes); - } - else - { - writeStartTag(label, attributes); - writeTagContent(content); - writeEndTag(label); - } - } - - /** - * This method writes attributes of a tag. - * - * @param attributes - */ - private void writeTagAttributes(final String... attributes) - { - // - if ((attributes != null) && (attributes.length > 0)) - { - for (int count = 0; count < attributes.length; count += 2) - { - this.out.print(" "); - this.out.print(attributes[count]); - this.out.print("=\""); - this.out.print(attributes[count + 1]); - this.out.print("\""); - } - } - } - - /** - * This method writes content using XML escape. - * - * @param content - * data to write in XML format. - */ - private void writeTagContent(final String content) - { - // - for (int count = 0; count < content.length(); count++) - { - // - char car = content.charAt(count); - - switch (car) - { - case '<': - this.out.print("<"); - break; - case '>': - this.out.print(">"); - break; - case '&': - this.out.print("&"); - break; - case '"': - this.out.print("""); - break; - case '\'': - this.out.print("'"); - break; - default: - this.out.print(car); - } - } - } - - /** - * This method writes a XML header with attributes. - * - * @param attributes - */ - public void writeXMLHeader(final String... attributes) - { - - // - this.out.print(""); - } -} diff --git a/src/fr/devinsy/util/xml/XMLZipReader.java b/src/fr/devinsy/util/xml/XMLZipReader.java deleted file mode 100644 index a988c32..0000000 --- a/src/fr/devinsy/util/xml/XMLZipReader.java +++ /dev/null @@ -1,68 +0,0 @@ -/** - * Copyright (C) 2013-2014 Christian Pierre MOMON - * - * This file is part of Devinsy-utils. - * - * Devinsy-utils is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Devinsy-utils is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see - */ -package fr.devinsy.util.xml; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.zip.ZipInputStream; - -import javax.xml.stream.XMLInputFactory; -import javax.xml.stream.XMLStreamException; - -/** - * - * @author Christian Pierre MOMON (christian.momon@devinsy.fr) - */ -public class XMLZipReader extends XMLReader -{ - - /** - * - * @param file - * @throws IOException - * @throws XMLStreamException - */ - public XMLZipReader(final File file) throws IOException, XMLStreamException - { - super(); - - XMLInputFactory factory = XMLInputFactory.newInstance(); - ZipInputStream zis = new ZipInputStream(new FileInputStream(file)); - zis.getNextEntry(); - this.in = factory.createXMLEventReader(zis, "UTF-8"); - } - - /** - * - * @param target - * @throws IOException - * @throws XMLStreamException - */ - public XMLZipReader(final InputStream source) throws IOException, XMLStreamException - { - super(); - - XMLInputFactory factory = XMLInputFactory.newInstance(); - ZipInputStream zis = new ZipInputStream(source); - zis.getNextEntry(); - this.in = factory.createXMLEventReader(zis, "UTF-8"); - } -} diff --git a/src/fr/devinsy/util/xml/XMLZipWriter.java b/src/fr/devinsy/util/xml/XMLZipWriter.java deleted file mode 100644 index 515ccf2..0000000 --- a/src/fr/devinsy/util/xml/XMLZipWriter.java +++ /dev/null @@ -1,149 +0,0 @@ -/** - * Copyright (C) 2013-2014 Christian Pierre MOMON - * - * This file is part of Devinsy-utils. - * - * Devinsy-utils is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Devinsy-utils is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see - */ -package fr.devinsy.util.xml; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; -import java.util.zip.Deflater; -import java.util.zip.ZipEntry; -import java.util.zip.ZipOutputStream; - -import fr.devinsy.util.FileTools; - -/** - * - * @author Christian Pierre MOMON (christian.momon@devinsy.fr) - */ -public class XMLZipWriter extends XMLWriter -{ - private ZipOutputStream zos; - - /** - * - * @param file - * @throws IOException - */ - public XMLZipWriter(final File file) throws IOException - { - super(); - - this.zos = new ZipOutputStream(new FileOutputStream(file)); - this.zos.setLevel(Deflater.BEST_COMPRESSION); - this.zos.setMethod(ZipOutputStream.DEFLATED); - this.zos.setComment("Generated by XMLZipWriter"); - this.zos.putNextEntry(new ZipEntry(FileTools.setExtension(file, ".xml").getName())); - this.out = new PrintWriter(new OutputStreamWriter(this.zos, "UTF-8")); - } - - /** - * - * @param file - * @throws IOException - */ - public XMLZipWriter(final File file, final String generator) throws IOException - { - super(); - - this.zos = new ZipOutputStream(new FileOutputStream(file)); - this.zos.setLevel(Deflater.BEST_COMPRESSION); - this.zos.setMethod(ZipOutputStream.DEFLATED); - this.zos.setComment(generator); - this.zos.putNextEntry(new ZipEntry(FileTools.setExtension(file, ".xml").getName())); - this.out = new PrintWriter(new OutputStreamWriter(this.zos, "UTF-8")); - } - - /** - * - * @param target - * @throws IOException - */ - public XMLZipWriter(final OutputStream target, final String generator) throws IOException - { - super(); - this.zos = new ZipOutputStream(target); - this.zos.setLevel(Deflater.BEST_COMPRESSION); - this.zos.setMethod(ZipOutputStream.DEFLATED); - if (generator != null) - { - this.zos.setComment(generator); - } - this.out = new PrintWriter(new OutputStreamWriter(this.zos, "UTF-8")); - } - - /** - * - * @param target - * @throws IOException - */ - public XMLZipWriter(final OutputStream target, final String fileName, final String generator) throws IOException - { - super(); - this.zos = new ZipOutputStream(target); - this.zos.setLevel(Deflater.BEST_COMPRESSION); - this.zos.setMethod(ZipOutputStream.DEFLATED); - if (generator != null) - { - this.zos.setComment(generator); - } - openEntry(fileName); - this.out = new PrintWriter(new OutputStreamWriter(this.zos, "UTF-8")); - } - - /** - * @throws IOException - * - */ - @Override - public void close() throws IOException - { - closeEntry(); - super.close(); - } - - /** - * @throws IOException - * - */ - public void closeEntry() throws IOException - { - flush(); - this.zos.closeEntry(); - } - - /** - * - * @param fileName - * @throws IOException - */ - public void openEntry(final String fileName) throws IOException - { - if (fileName == null) - { - throw new NullPointerException("fileName is null."); - } - else - { - this.zos.putNextEntry(new ZipEntry(FileTools.setExtension(fileName, ".xml"))); - } - } -} diff --git a/test/FileIteratorSandbox.java b/test/FileIteratorSandbox.java index 08452c6..6e9a375 100644 --- a/test/FileIteratorSandbox.java +++ b/test/FileIteratorSandbox.java @@ -1,20 +1,20 @@ /** * Copyright (C) 2013 Christian Pierre MOMON * - * This file is part of Devinsy-utils. + * This file is part of Devinsy-unix. * - * Devinsy-utils is free software: you can redistribute it and/or modify + * Devinsy-unix is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * - * Devinsy-utils is distributed in the hope that it will be useful, + * Devinsy-unix is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see + * along with Devinsy-unix. If not, see */ import java.io.File; diff --git a/test/fr/devinsy/util/FileToolsTest.java b/test/fr/devinsy/util/FileToolsTest.java index 2653b83..c965bad 100644 --- a/test/fr/devinsy/util/FileToolsTest.java +++ b/test/fr/devinsy/util/FileToolsTest.java @@ -1,20 +1,20 @@ /** * Copyright (C) 2014 Christian Pierre MOMON * - * This file is part of Devinsy-utils. + * This file is part of Devinsy-unix. * - * Devinsy-utils is free software: you can redistribute it and/or modify + * Devinsy-unix is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * - * Devinsy-utils is distributed in the hope that it will be useful, + * Devinsy-unix is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see + * along with Devinsy-unix. If not, see */ package fr.devinsy.util; diff --git a/test/fr/devinsy/util/cmdexec/CmdExecSandbox.java b/test/fr/devinsy/util/cmdexec/CmdExecSandbox.java deleted file mode 100644 index d0c6418..0000000 --- a/test/fr/devinsy/util/cmdexec/CmdExecSandbox.java +++ /dev/null @@ -1,108 +0,0 @@ -package fr.devinsy.util.cmdexec; - -/** - * Copyright (C) 2013 Christian Pierre MOMON - * - * This file is part of Devinsy-utils. - * - * Devinsy-utils is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Devinsy-utils is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see - */ -import org.apache.log4j.ConsoleAppender; -import org.apache.log4j.PatternLayout; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - */ -class CmdExecSandbox -{ - static private final Logger logger; - - static - { - // Initialize logger. - org.apache.log4j.BasicConfigurator.configure(); - org.apache.log4j.Logger.getRootLogger().setLevel(org.apache.log4j.Level.INFO); - - logger = LoggerFactory.getLogger(CmdExecSandbox.class); - logger.info("Enter"); - - // - logger.info("Set the log file format…"); - org.apache.log4j.Logger defaultLogger = org.apache.log4j.Logger.getRootLogger(); - defaultLogger.removeAllAppenders(); - defaultLogger.addAppender(new ConsoleAppender(new PatternLayout("%d{ISO8601} - dutils [%-5p] %34.34c.%-25M - %m%n"))); - - logger.info("… done."); - - logger.debug("Exit"); - } - - /** - * - */ - public static String check(final String title, final StringBuffer source, final String model) - { - String result; - - if (source.indexOf(model) == -1) - { - result = String.format("%-40s -> KO <-", title) + "\nGet:\n" + source + "\nWaiting:\n" + model; - - } - else - { - result = String.format("%-40s [ OK ] ", title); - } - - // - return (result); - } - - /** - * - */ - public static void main(final String[] args) - { - System.out.println("Automatic test action for CmdExec!"); - - test1(); - - } - - /** - * - */ - public static void test1() - { - try - { - System.out.println("Launch…s"); - - // String command = "/bin/sort -r /etc/passwd"; - String[] command = { "/usr/bin/sort", "-r", "/etc/passwd" }; - - CmdExec cmd = new CmdExec(command, StreamGobbler.StreamWay.BUFFER, StreamGobbler.StreamWay.BUFFER); - System.out.println("exitVal=[" + cmd.getExitValue() + "]"); - System.out.println("out=[" + cmd.getOutStream() + "]"); - System.out.println("err=[" + cmd.getErrStream() + "]"); - } - catch (Exception exception) - { - exception.printStackTrace(); - logger.info("ERRRO=" + exception); - } - } -} diff --git a/test/fr/devinsy/util/strings/StringListTest.java b/test/fr/devinsy/util/strings/StringListTest.java deleted file mode 100644 index 9afe379..0000000 --- a/test/fr/devinsy/util/strings/StringListTest.java +++ /dev/null @@ -1,402 +0,0 @@ -/** - * Copyright (C) 2013,2014 Christian Pierre MOMON - * - * This file is part of Devinsy-utils. - * - * Devinsy-utils is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Devinsy-utils is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see - */ -package fr.devinsy.util.strings; - -import java.util.Iterator; - -import org.apache.log4j.BasicConfigurator; -import org.apache.log4j.Level; -import org.apache.log4j.Logger; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import fr.devinsy.util.strings.StringList; -import fr.devinsy.util.strings.StringListCharIterator; -import fr.devinsy.util.strings.StringListCharPosition; - -/** - * - * @author Christian P. Momon - */ -public class StringListTest -{ - static protected org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(StringListTest.class); - - /** - * - */ - @Before - public void before() - { - BasicConfigurator.configure(); - Logger.getRootLogger().setLevel(Level.ERROR); - } - - /** - * - */ - @Test - public void testCharAt01() - { - // - logger.debug("===== test starting..."); - - // - StringList source = new StringList(); - source.append("abcdefghijklm"); - - // - char target = source.charAt(0); - Assert.assertEquals(target, 'a'); - - // - target = source.charAt(4); - Assert.assertEquals(target, 'e'); - - // - target = source.charAt(11); - Assert.assertEquals(target, 'l'); - - // - logger.debug("===== test done."); - } - - /** - * - */ - @Test - public void testCharAt02() - { - // - logger.debug("===== test starting..."); - - // - StringList source = new StringList(); - source.append("abc"); - source.append("def"); - source.append("ghi"); - source.append("jkl"); - source.append("mno"); - - // - char target = source.charAt(0); - Assert.assertEquals('a', target); - - // - target = source.charAt(4); - Assert.assertEquals('e', target); - - // - target = source.charAt(11); - Assert.assertEquals('l', target); - - // - logger.debug("===== test done."); - } - - /** - * - */ - @Test(expected = IndexOutOfBoundsException.class) - public void testCharAtException01() - { - // - logger.debug("===== test starting..."); - - // - StringList source = new StringList(); - source.append("abcdefghijklm"); - - // - char target = source.charAt(-2); - Assert.assertEquals('a', target); - - // - logger.debug("===== test done."); - } - - /** - * - */ - @Test(expected = IndexOutOfBoundsException.class) - public void testCharAtException02() - { - // - logger.debug("===== test starting..."); - - // - StringList source = new StringList(); - source.append("abcdefghijklm"); - - // - char target = source.charAt(100); - Assert.assertEquals('a', target); - - // - logger.debug("===== test done."); - } - - /** - * - */ - @Test(expected = IndexOutOfBoundsException.class) - public void testCharAtException03() - { - // - logger.debug("===== test starting..."); - - // - StringList source = new StringList(); - source.append("abcdefghijklm"); - - // - char target = source.charAt(source.length()); - Assert.assertEquals('a', target); - - // - logger.debug("===== test done."); - } - - /** - * - */ - @Test - public void testConstructor01() - { - // - logger.debug("===== test starting..."); - - String[] source = { "a", "b", "c" }; - - // - StringList target = new StringList(source); - - Assert.assertEquals(3, target.size()); - - // - logger.debug("===== test done."); - } - - /** - * - */ - @Test - public void testConstructor02() - { - // - logger.debug("===== test starting..."); - - // - StringList target = new StringList("a", "b", "c"); - - Assert.assertEquals(3, target.size()); - - // - logger.debug("===== test done."); - } - - /** - * - */ - @Test - public void testIteratorOfChar01() - { - // - logger.debug("===== test starting..."); - - // - StringList source = new StringList(); - source.append("abc"); - source.append("def"); - source.append("ghi"); - source.append("jkl"); - source.append("mno"); - - // - Iterator iterator = source.iteratorOfChar(); - - for (int index = 0; index < source.length(); index++) - { - StringListCharPosition position = ((StringListCharIterator) iterator).nextPosition(); - System.out.println(index + ":" + source.charAt(index) + " " + position.getCharIndex() + " " + position.getStringIndex() + " " + position.getLocalCharIndex()); - - Assert.assertTrue(iterator.hasNext()); - - Character character = ((StringListCharIterator) iterator).next(); - - Assert.assertEquals(character, new Character(source.charAt(index))); - } - - // - logger.debug("===== test done."); - } - - /** - * - */ - @Test - public void testSubstring01() - { - // - logger.debug("===== test starting..."); - - // - StringList source = new StringList(); - source.append("hamburger"); - - // - StringList target = source.substring(4, 8); - Assert.assertEquals("urge", target.toString()); - - // - logger.debug("===== test done."); - } - - /** - * - */ - @Test - public void testSubstring02() - { - // - logger.debug("===== test starting..."); - - // - StringList source = new StringList(); - source.append("ham").append("bur").append("ger"); - - // - StringList target = source.substring(4, 8); - Assert.assertEquals("urge", target.toString()); - - // - logger.debug("===== test done."); - } - - /** - */ - @Test - public void testSubstring03() - { - // - logger.debug("===== test starting..."); - - // - StringList source = new StringList(); - source.append("smiles"); - - // - StringList target = source.substring(1, 5); - Assert.assertEquals("mile", target.toString()); - - // - logger.debug("===== test done."); - } - - /** - */ - @Test - public void testSubstring04() - { - // - logger.debug("===== test starting..."); - - // - StringList source = new StringList(); - source.append("sm").append("il").append("es"); - - // - StringList target = source.substring(1, 5); - Assert.assertEquals("mile", target.toString()); - - // - logger.debug("===== test done."); - } - - /** - * - */ - @Test - public void testToString01() - { - // - logger.debug("===== test starting..."); - - // - StringList buffer = new StringList(); - - String target = buffer.toString(); - - Assert.assertTrue(target.equals("")); - - // - logger.debug("===== test done."); - } - - /** - * - */ - @Test - public void testToString02() - { - // - logger.debug("===== test starting..."); - - // - String source = "abcdefghijklm"; - - StringList buffer = new StringList(); - buffer.append(source); - - String target = buffer.toString(); - - Assert.assertEquals(source, target); - Assert.assertTrue(target.equals(source)); - - // - logger.debug("===== test done."); - } - - /** - * - */ - @Test - public void testToString03() - { - // - logger.debug("===== test starting..."); - - // - String source1 = "abcdefghijklm"; - String source2 = "other stuff"; - - StringList buffer = new StringList(); - buffer.append(source1); - buffer.append(source2); - - String target = buffer.toString(); - - Assert.assertTrue(target.equals(source1 + source2)); - - // - logger.debug("===== test done."); - } - -} diff --git a/test/fr/devinsy/util/strings/StringListUtilsTest.java b/test/fr/devinsy/util/strings/StringListUtilsTest.java deleted file mode 100644 index 097d37f..0000000 --- a/test/fr/devinsy/util/strings/StringListUtilsTest.java +++ /dev/null @@ -1,174 +0,0 @@ -/** - * Copyright (C) 2013,2014 Christian Pierre MOMON - * - * This file is part of Devinsy-utils. - * - * Devinsy-utils is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Devinsy-utils is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see - */ -package fr.devinsy.util.strings; - -import java.util.ArrayList; -import java.util.Collection; - -import org.apache.log4j.BasicConfigurator; -import org.apache.log4j.Level; -import org.apache.log4j.Logger; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -/** - * - * @author Christian P. Momon - */ -public class StringListUtilsTest -{ - private static org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(StringListUtilsTest.class); - - /** - * - */ - @Before - public void before() - { - BasicConfigurator.configure(); - Logger.getRootLogger().setLevel(Level.ERROR); - } - - /** - * - */ - @Test - public void testContainsBlank01() - { - Assert.assertFalse(StringListUtils.containsBlank((Collection) null)); - Assert.assertFalse(StringListUtils.containsBlank(new StringList("aaa", "bbb", "ccc"))); - Assert.assertTrue(StringListUtils.containsBlank(new StringList("aaa", null, "ccc"))); - Assert.assertTrue(StringListUtils.containsBlank(new StringList("aaa", "", "ccc"))); - Assert.assertTrue(StringListUtils.containsBlank(new StringList("aaa", " ", "ccc"))); - } - - /** - * - */ - @Test - public void testContainsBlank02() - { - Assert.assertFalse(StringListUtils.containsBlank((String[]) null)); - Assert.assertFalse(StringListUtils.containsBlank("aaa", "bbb", "ccc")); - Assert.assertTrue(StringListUtils.containsBlank("aaa", null, "ccc")); - Assert.assertTrue(StringListUtils.containsBlank("aaa", "", "ccc")); - Assert.assertTrue(StringListUtils.containsBlank("aaa", " ", "ccc")); - } - - /** - * - */ - @Test - public void testContainsBlank03() - { - Assert.assertFalse(StringListUtils.containsBlank((ArrayList) null)); - ArrayList source = new ArrayList(); - source.add("aaa"); - source.add("bbb"); - source.add("ccc"); - Assert.assertFalse(StringListUtils.containsBlank(source)); - source.set(1, null); - Assert.assertTrue(StringListUtils.containsBlank(source)); - source.set(1, ""); - Assert.assertTrue(StringListUtils.containsBlank(source)); - source.set(1, " "); - Assert.assertTrue(StringListUtils.containsBlank(source)); - } - - /** - * - */ - @Test - public void testContainsEmpty01() - { - Assert.assertFalse(StringListUtils.containsEmpty((Collection) null)); - Assert.assertFalse(StringListUtils.containsEmpty(new StringList("aaa", "bbb", "ccc"))); - Assert.assertTrue(StringListUtils.containsEmpty(new StringList("aaa", null, "ccc"))); - Assert.assertTrue(StringListUtils.containsEmpty(new StringList("aaa", "", "ccc"))); - } - - /** - * - */ - @Test - public void testContainsEmpty02() - { - Assert.assertFalse(StringListUtils.containsEmpty((String[]) null)); - Assert.assertFalse(StringListUtils.containsEmpty("aaa", "bbb", "ccc")); - Assert.assertTrue(StringListUtils.containsEmpty("aaa", null, "ccc")); - Assert.assertTrue(StringListUtils.containsEmpty("aaa", "", "ccc")); - } - - /** - * - */ - @Test - public void testContainsEmpty03() - { - Assert.assertFalse(StringListUtils.containsEmpty((ArrayList) null)); - ArrayList source = new ArrayList(); - source.add("aaa"); - source.add("bbb"); - source.add("ccc"); - Assert.assertFalse(StringListUtils.containsEmpty(source)); - source.set(1, null); - Assert.assertTrue(StringListUtils.containsEmpty(source)); - source.set(1, ""); - Assert.assertTrue(StringListUtils.containsEmpty(source)); - } - - /** - * - */ - @Test - public void testContainsNull01() - { - Assert.assertFalse(StringListUtils.containsNull((Collection) null)); - Assert.assertFalse(StringListUtils.containsNull(new StringList("aaa", "bbb", "ccc"))); - Assert.assertTrue(StringListUtils.containsNull(new StringList("aaa", null, "ccc"))); - } - - /** - * - */ - @Test - public void testContainsNull02() - { - Assert.assertFalse(StringListUtils.containsNull((String[]) null)); - Assert.assertFalse(StringListUtils.containsNull("aaa", "bbb", "ccc")); - Assert.assertTrue(StringListUtils.containsNull("aaa", null, "ccc")); - } - - /** - * - */ - @Test - public void testContainsNull03() - { - Assert.assertFalse(StringListUtils.containsNull((ArrayList) null)); - ArrayList source = new ArrayList(); - source.add("aaa"); - source.add("bbb"); - source.add("ccc"); - Assert.assertFalse(StringListUtils.containsNull(source)); - source.set(1, null); - Assert.assertTrue(StringListUtils.containsNull(source)); - } -} diff --git a/test/fr/devinsy/util/util/rss/RSSCacheTest.java b/test/fr/devinsy/util/util/rss/RSSCacheTest.java deleted file mode 100644 index dd3aa8a..0000000 --- a/test/fr/devinsy/util/util/rss/RSSCacheTest.java +++ /dev/null @@ -1,67 +0,0 @@ -/** - * Copyright (C) 2014 Christian Pierre MOMON - * - * This file is part of Devinsy-utils. - * - * Devinsy-utils is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Devinsy-utils is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see - */ -package fr.devinsy.util.util.rss; - -import org.apache.log4j.BasicConfigurator; -import org.apache.log4j.Level; -import org.apache.log4j.Logger; -import org.junit.Before; -import org.junit.Test; - -import fr.devinsy.util.rss.RSSCache; - -/** - * - * @author Christian P. Momon - */ -public class RSSCacheTest -{ - static protected org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(RSSCacheTest.class); - - /** - * - */ - @Before - public void before() - { - BasicConfigurator.configure(); - Logger.getRootLogger().setLevel(Level.ERROR); - } - - /** - * - */ - @Test - public void test01() - { - // - logger.debug("===== test starting..."); - - RSSCache cache = RSSCache.instance(); - - cache.put("ALPHA", "Mignonne, allons voir si la rose"); - cache.put("BRAVO", "Qui ce matin avoit desclose"); - cache.put("CHARLIE", "Sa robe de pourpre au Soleil,"); - - cache.setOudated("CHARLIE"); - - // - logger.debug("===== test done."); - } -} diff --git a/test/fr/devinsy/util/xml/XMLReaderTest.java b/test/fr/devinsy/util/xml/XMLReaderTest.java deleted file mode 100644 index 02e4f1a..0000000 --- a/test/fr/devinsy/util/xml/XMLReaderTest.java +++ /dev/null @@ -1,131 +0,0 @@ -/** - * Copyright (C) 2014 Christian Pierre MOMON - * - * This file is part of Devinsy-utils. - * - * Devinsy-utils is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Devinsy-utils is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Devinsy-utils. If not, see - */ -package fr.devinsy.util.xml; - -import java.io.File; -import java.io.FileNotFoundException; - -import javax.xml.stream.XMLStreamException; - -import org.apache.log4j.BasicConfigurator; -import org.apache.log4j.Level; -import org.apache.log4j.Logger; -import org.junit.Before; - -import fr.devinsy.util.strings.StringList; - -/** - * - * @author Christian P. Momon - */ -public class XMLReaderTest -{ - static private org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(XMLReaderTest.class); - - /** - * - */ - @Before - public void before() - { - BasicConfigurator.configure(); - Logger.getRootLogger().setLevel(Level.ERROR); - } - - /** - * @throws XMLStreamException - * @throws FileNotFoundException - * @throws XMLBadFormatException - * - */ - // @Test - public void testFoo01() throws FileNotFoundException, XMLStreamException, XMLBadFormatException - { - // - logger.debug("===== test starting..."); - - // XMLReader in = new XMLReader(new - // File("/home/cpm/C/Puck/TY/Ebrei 08.puc")); - // XMLReader in = new XMLReader(new - // File("/home/cpm/C/Puck/TY/T/kidarep.xml")); - XMLReader in = new XMLReader(new File("/home/cpm/C/Puck/TY/T2/sikevadb-2014-06-08-17h55mn49s.xml")); - - boolean ended = false; - while (!ended) - { - XMLTag tag = in.readTag(); - - if (tag == null) - { - ended = true; - } - else - { - // System.out.println(String.format("tag %s", tag.getLabel())); - } - - // - logger.debug("===== test done."); - } - System.out.println("over"); - } - - /** - * @throws XMLStreamException - * @throws FileNotFoundException - * @throws XMLBadFormatException - * - */ - // @Test - public void testFoo02() throws FileNotFoundException, XMLStreamException, XMLBadFormatException - { - // - logger.debug("===== test starting..."); - - // XMLReader in = new XMLReader(new - // File("/home/cpm/C/Puck/TY/Ebrei 08.puc")); - XMLReader in = new XMLReader(new File("/home/cpm/C/Puck/TY/T/accounts.xml")); - // XMLReader in = new XMLReader(new - // File("/home/cpm/C/Puck/TY/T2/sikevadb-2014-06-08-17h55mn49s.xml")); - - boolean ended = false; - StringList buffer = new StringList(); - while (!ended) - { - XMLTag tag = in.readTag(); - - if (tag == null) - { - ended = true; - } - else - { - if (tag.getContent() != null) - { - System.out.println(buffer.append(tag.getContent())); - } - } - - // - logger.debug("===== test done."); - } - System.out.println("over"); - } - -}