commons-io-2.11.0-src/CONTRIBUTING.md0100644 0000000 0000000 00000014565 13612062727 017251 0ustar00rootroot0000000 0000000 Contributing to Apache Commons IO ====================== You have found a bug or you have an idea for a cool new feature? Contributing code is a great way to give something back to the open source community. Before you dig right into the code there are a few guidelines that we need contributors to follow so that we can have a chance of keeping on top of things. Getting Started --------------- + Make sure you have a [JIRA account](https://issues.apache.org/jira/). + Make sure you have a [GitHub account](https://github.com/signup/free). + If you're planning to implement a new feature it makes sense to discuss your changes on the [dev list](https://commons.apache.org/mail-lists.html) first. This way you can make sure you're not wasting your time on something that isn't considered to be in Apache Commons IO's scope. + Submit a [Jira Ticket][jira] for your issue, assuming one does not already exist. + Clearly describe the issue including steps to reproduce when it is a bug. + Make sure you fill in the earliest version that you know has the issue. + Find the corresponding [repository on GitHub](https://github.com/apache/?query=commons-), [fork](https://help.github.com/articles/fork-a-repo/) and check out your forked repository. Making Changes -------------- + Create a _topic branch_ for your isolated work. * Usually you should base your branch on the `master` or `trunk` branch. * A good topic branch name can be the JIRA bug id plus a keyword, e.g. `IO-123-InputStream`. * If you have submitted multiple JIRA issues, try to maintain separate branches and pull requests. + Make commits of logical units. * Make sure your commit messages are meaningful and in the proper format. Your commit message should contain the key of the JIRA issue. * e.g. `IO-123: Close input stream earlier` + Respect the original code style: + Only use spaces for indentation. + Create minimal diffs - disable _On Save_ actions like _Reformat Source Code_ or _Organize Imports_. If you feel the source code should be reformatted create a separate PR for this change first. + Check for unnecessary whitespace with `git diff` -- check before committing. + Make sure you have added the necessary tests for your changes, typically in `src/test/java`. + Run all the tests with `mvn clean verify` to assure nothing else was accidentally broken. Making Trivial Changes ---------------------- The JIRA tickets are used to generate the changelog for the next release. For changes of a trivial nature to comments and documentation, it is not always necessary to create a new ticket in JIRA. In this case, it is appropriate to start the first line of a commit with '(doc)' instead of a ticket number. Submitting Changes ------------------ + Sign and submit the Apache [Contributor License Agreement][cla] if you haven't already. * Note that small patches & typical bug fixes do not require a CLA as clause 5 of the [Apache License](https://www.apache.org/licenses/LICENSE-2.0.html#contributions) covers them. + Push your changes to a topic branch in your fork of the repository. + Submit a _Pull Request_ to the corresponding repository in the `apache` organization. * Verify _Files Changed_ shows only your intended changes and does not include additional files like `target/*.class` + Update your JIRA ticket and include a link to the pull request in the ticket. If you prefer to not use GitHub, then you can instead use `git format-patch` (or `svn diff`) and attach the patch file to the JIRA issue. Additional Resources -------------------- + [Contributing patches](https://commons.apache.org/patches.html) + [Apache Commons IO JIRA project page][jira] + [Contributor License Agreement][cla] + [General GitHub documentation](https://help.github.com/) + [GitHub pull request documentation](https://help.github.com/articles/creating-a-pull-request/) + [Apache Commons Twitter Account](https://twitter.com/ApacheCommons) + `#apache-commons` IRC channel on `irc.freenode.net` [cla]:https://www.apache.org/licenses/#clas [jira]:https://issues.apache.org/jira/browse/IO commons-io-2.11.0-src/LICENSE.txt0100644 0000000 0000000 00000026137 13612062727 016641 0ustar00rootroot0000000 0000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. commons-io-2.11.0-src/NOTICE.txt0100644 0000000 0000000 00000000254 13612062727 016530 0ustar00rootroot0000000 0000000 Apache Commons IO Copyright 2002-2021 The Apache Software Foundation This product includes software developed at The Apache Software Foundation (https://www.apache.org/). commons-io-2.11.0-src/PROPOSAL.html0100644 0000000 0000000 00000005753 13612062727 017144 0ustar00rootroot0000000 0000000 Proposal for IO Package

Proposal for IO Package

(0) Rationale

Many software projects have a need to perform I/O in various ways, and the JDK class libraries provide a lot of functionality, but sometimes you need just a little bit more. The io package seeks to encapsulate some of the most popular i/o base classes into one easy to use package.

(1) Scope of the Package

This proposal is to create a package of Java utility classes for various types of i/o related activity.

(1.5) Interaction With Other Packages

IO relies only on standard JDK 1.2 (or later) APIs for production deployment. It utilizes the JUnit unit testing framework for developing and executing unit tests, but this is of interest only to developers of the component. IO will be a dependency for several existing components in the open source world.

No external configuration files are utilized.

(2) Initial Source of the Package

The original Java classes are splashed around various Apache subprojects. We intend to seek them out and integrate them.

The proposed package name for the new component is org.apache.commons.io.

(3) Required Jakarta-Commons Resources

(4) Initial Committers

The initial committers on the IO component shall be Scott Sanders and Nicola Ken Barozzi and Henri Yandell


commons-io-2.11.0-src/README.md0100644 0000000 0000000 00000013076 13612062727 016273 0ustar00rootroot0000000 0000000 Apache Commons IO =================== [![Travis-CI Status](https://travis-ci.org/apache/commons-io.svg)](https://travis-ci.org/apache/commons-io) [![GitHub Actions Status](https://github.com/apache/commons-io/workflows/Java%20CI/badge.svg)](https://github.com/apache/commons-io/actions) [![Coverage Status](https://coveralls.io/repos/apache/commons-io/badge.svg)](https://coveralls.io/r/apache/commons-io) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/commons-io/commons-io/badge.svg)](https://maven-badges.herokuapp.com/maven-central/commons-io/commons-io/) [![Javadocs](https://javadoc.io/badge/commons-io/commons-io/2.11.0.svg)](https://javadoc.io/doc/commons-io/commons-io/2.11.0) The Apache Commons IO library contains utility classes, stream implementations, file filters, file comparators, endian transformation classes, and much more. Documentation ------------- More information can be found on the [Apache Commons IO homepage](https://commons.apache.org/proper/commons-io). The [Javadoc](https://commons.apache.org/proper/commons-io/apidocs) can be browsed. Questions related to the usage of Apache Commons IO should be posted to the [user mailing list][ml]. Where can I get the latest release? ----------------------------------- You can download source and binaries from our [download page](https://commons.apache.org/proper/commons-io/download_io.cgi). Alternatively you can pull it from the central Maven repositories: ```xml commons-io commons-io 2.11.0 ``` Contributing ------------ We accept Pull Requests via GitHub. The [developer mailing list][ml] is the main channel of communication for contributors. There are some guidelines which will make applying PRs easier for us: + No tabs! Please use spaces for indentation. + Respect the code style. + Create minimal diffs - disable on save actions like reformat source code or organize imports. If you feel the source code should be reformatted create a separate PR for this change. + Provide JUnit tests for your changes and make sure your changes don't break any existing tests by running ```mvn clean test```. If you plan to contribute on a regular basis, please consider filing a [contributor license agreement](https://www.apache.org/licenses/#clas). You can learn more about contributing via GitHub in our [contribution guidelines](CONTRIBUTING.md). License ------- This code is under the [Apache Licence v2](https://www.apache.org/licenses/LICENSE-2.0). See the `NOTICE.txt` file for required notices and attributions. Donations --------- You like Apache Commons IO? Then [donate back to the ASF](https://www.apache.org/foundation/contributing.html) to support the development. Additional Resources -------------------- + [Apache Commons Homepage](https://commons.apache.org/) + [Apache Issue Tracker (JIRA)](https://issues.apache.org/jira/browse/IO) + [Apache Commons Twitter Account](https://twitter.com/ApacheCommons) + `#apache-commons` IRC channel on `irc.freenode.org` [ml]:https://commons.apache.org/mail-lists.html commons-io-2.11.0-src/RELEASE-NOTES.txt0100644 0000000 0000000 00000201613 13612062727 017517 0ustar00rootroot0000000 0000000 Apache Commons IO Version 2.11.0 Release Notes INTRODUCTION: Commons IO is a package of Java utility classes like java.io. Classes in this package are considered to be so standard and of such high reuse as to justify existence in java.io. The Apache Commons IO library contains utility classes, stream implementations, file filters, file comparators, endian transformation classes, and much more. ============================================================================== Apache Commons IO Version 2.11.0 ============================================================================== Java 8 required. Changes in this version include: Fixed Bugs: o IO-741: FileUtils.listFiles does not list matching files if File parameter is a symbolic link. Thanks to Zach Sherman. o IO-724: FileUtils#deleteDirectory(File) exception Javadoc inaccurate update #245. Thanks to liran2000. o Minor changes #243. Thanks to Arturo Bernal. o Replace construction of FileInputStream and FileOutputStream objects with Files NIO APIs. #221. Thanks to Arturo Bernal. o Fix IndexOutOfBoundsException in IOExceptionList constructors. Thanks to Gary Gregory. o Remove IOException from the method signatures that no longer throw IOException. This maintains binary compatibility but not source compatibility. - FilenameUtils directoryContains(String, String) - BoundedReader BoundedReader(java.io.Reader, int) - IOUtils lineIterator(java.io.InputStream, Charset) lineIterator(java.io.InputStream, String) toByteArray(String) toInputStream(CharSequence, String) toInputStream(String, String) toString(byte[]) toString(byte[], String) Thanks to Gary Gregory. Changes: o Add SymbolicLinkFileFilter. Thanks to Gary Gregory. o Add test to make sure the setter of AndFileFilter works correctly #244. Thanks to trncate. o Add XmlStreamReader(Path). Thanks to Gary Gregory. o Bump mockito-inline from 3.11.0 to 3.11.2 #247. Thanks to Dependabot. o Bump jmh.version from 1.27 to 1.32 #237. Thanks to Dependabot. o Bump spotbugs from 4.2.3 to 4.3.0 #249. Thanks to Dependabot. Compatibility with 2.6: Binary compatible: Yes. Source compatible: Yes. Semantic compatible: Yes. Commons IO 2.9.0 requires Java 8. Commons IO 2.8.0 requires Java 8. Commons IO 2.7 requires Java 8. Commons IO 2.6 requires Java 7. Commons IO 2.5 requires Java 6. Commons IO 2.4 requires Java 6. Commons IO 2.3 requires Java 6. Commons IO 2.2 requires Java 5. Commons IO 1.4 requires Java 1.3. Historical list of changes: https://commons.apache.org/proper/commons-io/changes-report.html For complete information on Apache Commons IO, including instructions on how to submit bug reports, patches, or suggestions for improvement, see the Apache Apache Commons IO website: https://commons.apache.org/proper/commons-io/ Download page: https://commons.apache.org/proper/commons-io/download_io.cgi Have fun! -Apache Commons Team Apache Commons IO Version 2.10.0 Release Notes INTRODUCTION: Commons IO is a package of Java utility classes like java.io. Classes in this package are considered to be so standard and of such high reuse as to justify existence in java.io. The Apache Commons IO library contains utility classes, stream implementations, file filters, file comparators, endian transformation classes, and much more. ============================================================================== Apache Commons IO Version 2.10.0 ============================================================================== Java 8 required. Changes in this version include: New features: o Add and use RegexFileFilter.toString(). Thanks to Gary Gregory. o Add and use RegexFileFilter.RegexFileFilter(Pattern, Function, String>) Thanks to Gary Gregory. o Add and use IOCase.isCaseSensitive(IOCase). Thanks to Gary Gregory. Fixed Bugs: o IO-733: RegexFileFilter uses the path and file name instead of just the file name. Thanks to Jim Sellers, Gary Gregory. o IO-734: The OSGi manifest now contains sun.* import packages #239. Thanks to Eric Norman. o IO-585: Sanitize double slash after prefix #79. Thanks to Adam McClenaghan. Changes: o Bump actions/cache from 2.1.5 to 2.1.6 #238. Thanks to Dependabot. o Bump junit-pioneer from 1.4.1 to 1.4.2 #240. Thanks to Dependabot. o Bump checkstyle from 8.42 to 8.43 #241. Thanks to Dependabot. o Bump mockito-inline from 3.10.0 to 3.11.0 #242. Thanks to Dependabot. Compatibility with 2.6: Binary compatible: Yes. Source compatible: Yes. Semantic compatible: Yes. Commons IO 2.9.0 requires Java 8. Commons IO 2.8.0 requires Java 8. Commons IO 2.7 requires Java 8. Commons IO 2.6 requires Java 7. Commons IO 2.5 requires Java 6. Commons IO 2.4 requires Java 6. Commons IO 2.3 requires Java 6. Commons IO 2.2 requires Java 5. Commons IO 1.4 requires Java 1.3. Historical list of changes: https://commons.apache.org/proper/commons-io/changes-report.html For complete information on Apache Commons IO, including instructions on how to submit bug reports, patches, or suggestions for improvement, see the Apache Apache Commons IO website: https://commons.apache.org/proper/commons-io/ Download page: https://commons.apache.org/proper/commons-io/download_io.cgi Have fun! -Apache Commons Team Apache Commons IO Version 2.8.0 Release Notes INTRODUCTION: Commons IO is a package of Java utility classes like java.io. Classes in this package are considered to be so standard and of such high reuse as to justify existence in java.io. The Apache Commons IO library contains utility classes, stream implementations, file filters, file comparators, endian transformation classes, and much more. ============================================================================== Apache Commons IO Version 2.8.0 ============================================================================== Java 8 required. Changes in this version include: New features: o Add org.apache.commons.io.input.CircularInputStream. Thanks to Gary Gregory. o Add org.apache.commons.io.file.PathUtils.cleanDirectory(Path, FileVisitOption...). Thanks to Gary Gregory. o Add org.apache.commons.io.file.PathUtils.deleteDirectory(Path, FileVisitOption...). Thanks to Gary Gregory. o Add NullAppendable. Thanks to Gary Gregory. o Add PathUtils.getAclEntryList(Path). Thanks to Gary Gregory. o Null-guard IOUtils.close(Closeable, IOConsumer). Thanks to Gary Gregory. o Add ReversedLinesFileReader.readLines(int). Thanks to Gary Gregory. o Add ReversedLinesFileReader.toString(int). Thanks to Gary Gregory. o IO-684: Add PathUtils.delete(Path, DeleteOption...). Add PathUtils.deleteDirectory(Path, DeleteOption...). Add PathUtils.deleteFile(Path, DeleteOption...). Add PathUtils.setReadOnly(Path, boolean, LinkOption...). Add CleaningPathVisitor.CleaningPathVisitor(PathCounters, DeleteOption[], String...). Add DeletingPathVisitor.DeletingPathVisitor(PathCounters, DeleteOption[], String...). Thanks to Gary Gregory, Robin Jansohn. o Add RandomAccessFileInputStream. Thanks to Gary Gregory. o IO-681: IOUtils.close(Closeable) should allow a list of closeables. o Add IOUtils.consume(InputStream). Thanks to Gary Gregory. o IO-676: Add isFileNewer() and isFileOlder() methods that support the Java 8 Date/Time API. #124. Thanks to Isira Seneviratne, Gary Gregory. o Add a MarkShieldInputStream #119. Thanks to Adam Retter, Gary Gregory. o Deprecate IOUtils.LINE_SEPARATOR in favor of Java 7's System.lineSeparator(). Thanks to Gary Gregory. Fixed Bugs: o CharSequenceReader.skip should return 0 instead of EOF on stream end #123. Thanks to Rob Spoor, Jochen Wiedmann. o Implement CharSequenceReader.ready() #122. Thanks to Rob Spoor. o IO-669: Fix code smells; fix typos #115. Thanks to XenoAmess, Gary Gregory. o Add caching for required charsets #120. Thanks to Jerome Wolff, Gary Gregory. o IO-673: Make some simplifications #121. Thanks to Jerome Wolff. o IO-674: InfiniteCircularInputStream is not infinite if its input buffer contains -1. Thanks to Gary Gregory. o IO-675: InfiniteCircularInputStream throws a divide-by-zero exception when reading if its input buffer is size 0. Thanks to Gary Gregory. o IO-677: FileSystem.getCurrent() does not return the correct enum. Thanks to Gary Gregory. o IO-679: input.AbstractCharacterFilterReader passes count of chars read #132. Thanks to proneel. o IO-683: CircularBufferInputStream.read() fails to convert byte to unsigned int o Fix SpotBugs issues in org.apache.commons.io.FileUtils. Thanks to Gary Gregory. o IO-672: Copying a File sets last modified date to 01 January 1970. o IO-676: Prevent NullPointerException in ReversedLinesFileReader constructors #117. Thanks to Michael Ernst, Gary Gregory. Changes: o Replace FindBugs with SpotBugs. Thanks to Gary Gregory. o maven-checkstyle-plugin 3.1.0 -> 3.1.1. Thanks to Gary Gregory. o Update tests from org.apache.commons:commons-lang3 3.10 to 3.11. Thanks to Gary Gregory. o Update commons-parent from 50 to 51 #129. Thanks to Gary Gregory. o Update actions/checkout from v1 to v2.3.1 #126. Thanks to Gary Gregory. o Update junit-pioneer from 0.6.0 to 0.8.0, #127, #135. Thanks to Gary Gregory. o Update mockito-core from 3.3.3 to 3.5.9 #128, #133, #145, #149, #151. Thanks to Gary Gregory. o Update spotbugs from 4.0.6 to 4.1.1 #134. Thanks to Dependabot. o Update junit-pioneer from 0.8.0 to 0.9.0 #138. Thanks to Dependabot. o Update actions/checkout from v2.3.1 to v2.3.2 #140. Thanks to Dependabot. o Update actions/setup-java from v1.4.0 to v1.4.2 #141, #148. Thanks to Dependabot. Compatibility with 2.7: Binary compatible: Yes. Source compatible: Yes. Semantic compatible: Yes. Commons IO 2.7 requires Java 8. Commons IO 2.6 requires Java 7. Commons IO 2.5 requires Java 6. Commons IO 2.4 requires Java 6. Commons IO 2.3 requires Java 6. Commons IO 2.2 requires Java 5. Commons IO 1.4 requires Java 1.3. Historical list of changes: https://commons.apache.org/proper/commons-io/changes-report.html For complete information on Apache Commons IO, including instructions on how to submit bug reports, patches, or suggestions for improvement, see the Apache Apache Commons IO website: https://commons.apache.org/proper/commons-io/ Download page: https://commons.apache.org/proper/commons-io/download_io.cgi Have fun! -Apache Commons Team ============================================================================== Apache Commons IO Version 2.7 Release Notes INTRODUCTION: Commons IO is a package of Java utility classes like java.io. Classes in this package are considered to be so standard and of such high reuse as to justify existence in java.io. The Apache Commons IO library contains utility classes, stream implementations, file filters, file comparators, endian transformation classes, and much more. ============================================================================== Apache Commons IO Version 2.7 ============================================================================== Java 8 required. Changes in this version include: New features: o Adding the CircularBufferInputStream, and the PeekableInputStream. o IO-553: Add org.apache.commons.io.FilenameUtils.isIllegalWindowsFileName(char). o IO-577: Add readers to filter out given characters: CharacterSetFilterReader and CharacterFilterReader. Thanks to Gary Gregory. o IO-594: Add IOUtils copy methods with java.lang.Appendable as the target. Thanks to Gary Gregory. o IO-605: Add class CanExecuteFileFilter. Thanks to Gary Gregory. o IO-578: Support java.nio.Path and non-default file systems for ReversedLinesFileReader (#62). Thanks to Mark Chesney. o IO-608: Add a convenience NullPrintStream. Thanks to Gary Gregory. o IO-612: Add class TeeReader. Thanks to Rob Spoor, Gary Gregory. o IO-613: Add classes ClosedReader and CloseShieldReader. #84. Thanks to Rob Spoor, Gary Gregory. o IO-614: Add classes TaggedWriter, ClosedWriter and BrokenWriter. #86. Thanks to Rob Spoor. o IO-615: Add classes TeeWriter, FilterCollectionWriter, ProxyCollectionWriter, IOExceptionList, IOIndexedException. Thanks to Gary Gregory, Rob Spoor. o IO-616: Add class AppendableWriter. #87. Thanks to Rob Spoor. o IO-617: Add class CloseShieldWriter. #83. Thanks to Rob Spoor, Gary Gregory. o IO-618: Add classes Added TaggedReader, ClosedReader and BrokenReader. #85. Thanks to Rob Spoor. o IO-619: Support sub sequences in CharSequenceReader. #91. Thanks to Rob Spoor. o IO-631: Add a CountingFileVisitor (as the basis for a forthcoming DeletingFileVisitor). Thanks to Gary Gregory. o IO-632: Add PathUtils for operations on NIO Path. Thanks to Gary Gregory. o IO-633: Add DeletingFileVisitor. Thanks to Gary Gregory. o IO-635: Add org.apache.commons.io.IOUtils.close(Closeable). Thanks to Gary Gregory. o IO-636: Add and reuse org.apache.commons.io.IOUtils.closeQuitely(Closeable, Consumer). Add and reuse org.apache.commons.io.IOUtils.close(Closeable, IOConsumer). Thanks to Gary Gregory. o IO-645: Add org.apache.commons.io.file.PathUtils.fileContentEquals(Path, Path, OpenOption...). Thanks to Gary Gregory. o IO-458: Add a SequenceReader similar to java.io.SequenceInputStream. Thanks to Gary Gregory, Joshua Gitlin. o IO-648: Implement directory content equality. 100#. Thanks to Gary Gregory. o IO-648: Refactor ByteArrayOutputStream into synchronized and unsynchronized versions #108. Thanks to Adam Retter, Alex Herbert, Gary Gregory. o IO-662: Refactor ByteArrayOutputStream into synchronized and unsynchronized versions #108. Thanks to Adam Retter, Gary Gregory. Fixed Bugs: o IO-589: Some tests fail if the base path contains a space. o IO-582: Make methods in ObservableInputStream.Obsever public. Thanks to Bruno Palos. o IO-535: Thread bug in FileAlterationMonitor.stop(int). Thanks to Svetlin Zarev, Anthony Raymond. o IO-557: Perform locale independent upper case conversions. Thanks to luccioman. o IO-570: Missing Javadoc in FilenameUtils causing Travis-CI build to fail. Thanks to Pranet Verma. o IO-571: Remove redundant isDirectory() check in org.apache.commons.io.FileUtils.listFilesAndDirs(File, IOFileFilter, IOFileFilter). Thanks to pranet. o IO-559: FilenameUtils.normalize now verifies hostname syntax in UNC path. o IO-554: FileUtils.copyToFile(InputStream source, File destination) should not close input stream. Thanks to Michele Mariotti. o IO-604: FileUtils.doCopyFile(File, File, boolean) can throw ClosedByInterruptException. Thanks to Gary Gregory. o IO-625: Corrected misleading exception message for FileUtils.copyDirectoryToDirectory. Thanks to Mikko Maunu. o IO-626: A mistake in the FilenameUtils.concat()'s Javadoc about an absolute path. Thanks to Yuji Konishi. o IO-640: NPE in org.apache.commons.io.IOUtils.contentEquals(InputStream, InputStream) when only one input is null. Thanks to Gary Gregory. o IO-641: NPE in org.apache.commons.io.IOUtils.contentEquals(Reader, Reader) when only one input is null. Thanks to Gary Gregory. o IO-643: NPE in org.apache.commons.io.IOUtils.contentEqualsIgnoreEOL(Reader, Reader) when only one input is null. Thanks to Gary Gregory. o IO-644: NPE in org.apache.commons.io.FileUtils.contentEqualsIgnoreEOL(File, File) when only one input is null. Thanks to Gary Gregory. o IO-664: org.apache.commons.io.FileUtils.copyURLToFile(*) open but do not close streams. Thanks to Gary Gregory. Changes: o IO-572: Refactor duplicate code in org.apache.commons.io.FileUtils. Thanks to Pranet Verma. o IO-580: Update org.apache.commons.io.FilenameUtils.isExtension(String, String[]) to use var args. o IO-701: Make array declaration in ThresholdingOutputStream consistent with other array declarations in the library #77. Thanks to Raymond Tan. o IO-607: Update from Java 7 to Java 8. Thanks to Gary Gregory. o IO-610: Remove throws IOException in method isSymlink() #80. Thanks to Sebastian. o IO-628: Migration to JUnit Jupiter #97. Thanks to Allon Mureinik. o IO-630: Deprecate org.apache.commons.io.output.NullOutputStream.NullOutputStream() in favor of org.apache.commons.io.output.NullOutputStream.NULL_OUTPUT_STREAM. Thanks to Gary Gregory. o IO-629: FileUtils#forceDelete should use Files#delete rather than File#delete so exception messages includes reason for failure. Thanks to Ian Springer, Ian Springer, Gary Gregory. o IO-634: Make getCause synchronized and use a Deque instead of a Stack #64. Thanks to Vclav Haisman, Bruno P. Kinoshita, Gary Gregory. o Update tests from Apache Commons Lang 3.9 to 3.10. Thanks to Gary Gregory. o Update tests org.junit-pioneer:junit-pioneer 0.3.0 -> 0.6.0. Thanks to Gary Gregory. o Update tests org.junit.jupiter:junit-jupiter 5.5.2 -> 5.6.2. Thanks to Gary Gregory. o Update tests org.mockito:mockito-core 3.0.0 -> 3.3.3. Thanks to Gary Gregory. o IO-666: Normalize internal buffers to 8192 bytes. Thanks to Gary Gregory. o IO-665: Ensure that passing a null InputStream results in NPE with tests #112. Thanks to Otto Fowler, Gary Gregory. o commons.jacoco.version 0.8.4 -> 0.8.5. Thanks to Gary Gregory. o com.github.siom79.japicmp:japicmp-maven-plugin 0.14.1 -> 0.14.3. Thanks to Gary Gregory. o IO-667: Add functional interfaces IOFunction and IOSupplier #110. Thanks to Adam Retter, Gary Gregory. o Support sub sequences in CharSequenceReader #91. Thanks to Rob Spoor, Gary Gregory. o Remove deprecated sudo setting. #113. Thanks to dengliming. Compatibility with 2.6: Binary compatible: Yes. Source compatible: Yes. Semantic compatible: Yes. Commons IO 2.7 requires Java 8. Commons IO 2.6 requires Java 7. Commons IO 2.5 requires Java 6. Commons IO 2.4 requires Java 6. Commons IO 2.3 requires Java 6. Commons IO 2.2 requires Java 5. Commons IO 1.4 requires Java 1.3. Historical list of changes: https://commons.apache.org/proper/commons-io/changes-report.html For complete information on Apache Commons IO, including instructions on how to submit bug reports, patches, or suggestions for improvement, see the Apache Apache Commons IO website: https://commons.apache.org/proper/commons-io/ Download page: https://commons.apache.org/proper/commons-io/download_io.cgi Have fun! -Apache Commons Team ============================================================================== Apache Commons IO Version 2.6 ============================================================================== INTRODUCTION: Apache Commons IO is a package of Java utility classes like java.io. Classes in this package are considered to be so standard and of such high reuse as to justify existence in java.io. The Apache Commons IO library contains utility classes, stream implementations, file filters, file comparators, endian transformation classes, and much more. Apache Commons IO 2.6 requires at least Java 7 to build and run. DEPRECATIONS ============ All closeQuietly overloads in org.apache.commons.io.IOUtils have been deprecated. Use the try-with-resources statement or handle suppressed exceptions manually. The class org.apache.commons.io.FileSystemUtils has been deprecated. Use equivalent methods in java.nio.file.FileStore instead, e.g. Files.getFileStore(Paths.get("/home")).getUsableSpace() or iterate over FileSystems.getDefault().getFileStores(). COMPATIBILITY WITH JAVA 9 ================== The MANIFEST.MF now contains an additional entry: Automatic-Module-Name: org.apache.commons.io This should make it possible to use Commons IO 2.6 as a module in the Java 9 module system. For more information see the corresponding issue: https://issues.apache.org/jira/browse/IO-551 Building Commons IO 2.6 should work out of the box with the latest Java 9 release. Please report any Java 9 related issues at: https://issues.apache.org/jira/browse/IO NEW FEATURES ============ o IO-551: Add Automatic-Module-Name MANIFEST entry for Java 9 compatibility. o IO-367: Add convenience methods for copyToDirectory. Thanks to James Sawle. o IO-493: Add infinite circular input stream. Thanks to Piotr Turski. o IO-507: Add a ByteOrderUtils class. o IO-518: Add ObservableInputStream. o IO-519: Add MessageDigestCalculatingInputStream. o IO-513: Add convenience methods for reading class path resources. Thanks to Behrang Saeedzadeh. FIXED BUGS ========== o IO-546: ClosedOutputStream#flush should throw. Thanks to Tomas Celaya. o IO-550: Documentation issue, fix 404 Javadoc issues in the description page. Thanks to Jimi Adrian. o IO-442: Javadoc contradictory for FileFilterUtils.ageFileFilter(cutoff) and the filter it constructs: AgeFileFilter(cutoff). Thanks to Simon Robinson. o IO-534: FileUtilTestCase.testForceDeleteDir() should not delete testDirectory parent. o IO-528: Fix Tailer.run race condition runaway logging. Thanks to Dave Moten. o IO-483: getPrefixLength return -1 if unix file contains colon. Thanks to Marko Vasic. o IO-520: FileUtilsTestCase#testContentEqualsIgnoreEOL fails on Windows. o IO-516: .gitattributes not correctly applied. Thanks to Jason Pyeron. o IO-515: Allow Specifying Initial Buffer Size of DeferredFileOutputStream. Thanks to Brett Lounsbury, Gary Gregory. o IO-512: ThresholdingOutputStream.thresholdReached() results in FileNotFoundException. Thanks to Ralf Hauser. o IO-511: After a few unit tests, a few newly created directories not cleaned completely. Thanks to Ahmet Celik. o IO-502: Exceptions are suppressed incorrectly when copying files. Thanks to Christian Schulte. o IO-503: Update platform requirement to Java 7. o IO-537: BOMInputStream shouldn't sort array of BOMs in-place. Thanks to Borys Zibrov. CHANGES ======= o IO-553: Make code style of hasBOM() consistent with getBOMCharsetName(). Thanks to Michael Ernst. o IO-542: FileUtils#readFileToByteArray: optimize reading of files with known size. Thanks to Ilmars Poikans. o IO-547: Throw a IllegalArgumentException instead of NullPointerException in FileSystemUtils.freeSpaceWindows(). Thanks to Nikhil Shinde, Michael Ernst, Gary Greory. o IO-506: Deprecate methods FileSystemUtils.freeSpaceKb(). Thanks to Christian Schulte. o IO-505: Make LineIterator implement Closeable to support try-with-resources statements. Thanks to Christian Schulte. o IO-504: Deprecated of all IOUtils.closeQuietly() methods and use try-with-resources internally. Thanks to Christian Schulte. REMOVED ======= o IO-514: Remove org.apache.commons.io.Java7Support. COMPATIBILITY WITH OLDER VERSIONS ================================= Compatibility with 2.5: Binary compatible: Yes. Source compatible: Yes. Semantic compatible: Yes. Compatibility with 2.6 and 1.4: Binary compatible: Yes. Source compatible: No, see the rare case in https://issues.apache.org/jira/browse/IO-318. Semantic compatible: No, see the rare case in https://issues.apache.org/jira/browse/IO-318. Commons IO 2.6 requires Java 7 or later. Commons IO 2.5 requires Java 6 or later. Commons IO 2.4 requires Java 6 or later. Commons IO 2.3 requires Java 6 or later. Commons IO 2.2 requires Java 5 or later. Commons IO 1.4 requires Java 1.3 or later. ============================================================================== Apache Commons IO Version 2.5 ============================================================================== New features and bug fixes. Changes in this version include: New features: o IO-487: Add ValidatingObjectInputStream for controlled deserialization o IO-471: Support for additional encodings in ReversedLinesFileReader Thanks to Leandro Reis. o IO-425: Setter method for threshold on ThresholdingOutputStream Thanks to Craig Swank. o IO-406: Introduce new class AppendableOutputStream Thanks to Niall Pemberton. o IO-459: Add WindowsLineEndingInputStream and UnixLineEndingInputStream. Thanks to Kristian Rosenvold. o IO-457: Add a BoundedReader, a wrapper that can be used to constrain access to an underlying stream when used with mark/reset - to avoid overflowing the mark limit of the underlying buffer. Thanks to Kristian Rosenvold. o IO-426: Add API IOUtils.closeQuietly(Closeable...) o IO-410: Readfully() That Returns A Byte Array Thanks to Beluga Behr. o IO-395: Overload IOUtils buffer methods to accept buffer size Thanks to Beluga Behr. o IO-382: Chunked IO for large arrays. Added writeChunked(byte[], OutputStream) and writeChunked(char[] Writer) Added ChunkedOutputStream, ChunkedWriter o IO-233: Add Methods for Buffering Streams/Writers To IOUtils Added overloaded buffer() methods - see also IO-330 o IO-330: IOUtils#toBufferedOutputStream/toBufferedWriter to conditionally wrap the output Added overloaded buffer() methods - see also IO-233 o IO-381: Add FileUtils.copyInputStreamToFile API with option to leave the source open. See copyInputStreamToFile(final InputStream source, final File destination, boolean closeSource) o IO-379: CharSequenceInputStream - add tests for available() Fix code so it really does reflect a minimum available. o IO-346: Add ByteArrayOutputStream.toInputStream() o IO-341: A constant for holding the BOM character (U+FEFF) o IO-361: Add API FileUtils.forceMkdirsParent(). o IO-360: Add API Charsets.requiredCharsets(). o IO-359: Add IOUtils.skip and skipFully(ReadableByteChannel, long). Thanks to yukoba. o IO-358: Add IOUtils.read and readFully(ReadableByteChannel, ByteBuffer buffer). Thanks to yukoba. o IO-353: Add API IOUtils.copy(InputStream, OutputStream, int) Thanks to ggregory. o IO-349: Add API with array offset and length argument to FileUtils.writeByteArrayToFile. Thanks to scop. o IO-348: Missing information in IllegalArgumentException thrown by org.apache.commons.io.FileUtils#validateListFilesParameters. Thanks to plcstpierre. o IO-345: Supply a hook method allowing Tailer actively determining stop condition. Thanks to mkresse. o IO-437: Make IOUtils.EOF public and reuse it in various classes. Fixed Bugs: o IO-446: adds an endOfFileReached method to the TailerListener Thanks to Jeffrey Barrus. o IO-484: FilenameUtils should handle embedded null bytes Thanks to Philippe Arteau. o IO-481: Changed/Corrected algorithm for waitFor o IO-428: BOMInputStream.skip returns wrong count if stream contains no BOM Thanks to Stefan Gmeiner. o IO-488: FileUtils.waitFor(...) swallows thread interrupted status Thanks to Bjrn Buchner. o IO-452: Support for symlinks with missing target. Added support for JDK7 symlink features when present Thanks to David Standish. o IO-453: Regression in FileUtils.readFileToString from 2.0.1 Thanks to Steven Christou. o IO-451: ant test fails - resources missing from test classpath Thanks to David Standish. o IO-435: Document that FileUtils.deleteDirectory, directoryContains and cleanDirectory may throw an IllegalArgumentException in case the passed directory does not exist or is not a directory. Thanks to Dominik Stadler. o IO-424: Javadoc fixes, mostly to appease 1.8.0 Thanks to Ville Skytt. o IO-389: FileUtils.sizeOfDirectory can throw IllegalArgumentException Thanks to Austin Doupnik. o IO-390: FileUtils.sizeOfDirectoryAsBigInteger can overflow. Ensure that recursive calls all use BigInteger o IO-385: FileUtils.doCopyFile can potentially loop for ever Exit loop if no data to copy o IO-383: FileUtils.doCopyFile caches the file size; needs to be documented Added Javadoc; show file lengths in exception message o IO-380: FileUtils.copyInputStreamToFile should document it closes the input source Thanks to claudio_ch. o IO-279: Tailer erroneously considers file as new. Fix to use file.lastModified() rather than System.currentTimeMillis() o IO-356: CharSequenceInputStream#reset() behaves incorrectly in case when buffer size is not dividable by data size. Fix code so skip relates to the encoded bytes; reset now re-encodes the data up to the point of the mark o IO-368: ClassLoaderObjectInputStream does not handle primitive typed members o IO-314: Deprecate all methods that use the default encoding o IO-338: When a file is rotated, finish reading previous file prior to starting new one o IO-354: Commons IO Tailer does not respect UTF-8 Charset. o IO-323: What should happen in FileUtils.sizeOf[Directory] when an overflow takes place? Added Javadoc. o IO-372: FileUtils.moveDirectory can produce misleading error message on failiure o IO-362: IOUtils.contentEquals* methods returns false if input1 == input2, should return true. Thanks to mmadson, ggregory. o IO-357: [Tailer] InterruptedException while the thread is sleeping is silently ignored Thanks to mortenh. o IO-352: Spelling fixes. Thanks to scop. o IO-436: Improper Javadoc comment for FilenameUtils.indexOfExtension. Thanks to christoph.schneegans. Changes: o IO-433: Converted all testcases to JUnit 4 o IO-466: Added testcase to show this was fixed with IO-423 o IO-479: Correct exception message in FileUtils.getFile(File, String...) Thanks to Zhouce Chen. o IO-465: Update to JUnit 4.12 Thanks to based2. o IO-462: IOExceptionWithCause no longer needed o IO-422: Deprecate Charsets Charset constants in favor of Java 7's java.nio.charset.StandardCharsets o IO-239: Convert IOCase to a Java 1.5+ Enumeration [N.B. this is binary compatible] o IO-328: getPrefixLength returns null if filename has leading slashes Javadoc: add examples to show correct behavior; add unit tests o IO-299: FileUtils.listFilesAndDirs includes original dir in results even when it doesn't match filter Javadoc: clarify that original dir is included in the results o IO-375: FilenameUtils.splitOnTokens(String text) check for '**' could be simplified o IO-374: WildcardFileFilter ctors should not use null to mean IOCase.SENSITIVE when delegating to other ctors Compatibility with 2.4: Binary compatible: Yes. Source compatible: Yes. Semantic compatible: Yes. Compatibility with 2.2 and 1.4: Binary compatible: Yes. Source compatible: No, see the rare case in https://issues.apache.org/jira/browse/IO-318. Semantic compatible: No, see the rare case in https://issues.apache.org/jira/browse/IO-318. Commons IO 2.5 requires Java 6 or later. Commons IO 2.4 requires Java 6 or later. Commons IO 2.3 requires Java 6 or later. Commons IO 2.2 requires Java 5 or later. Commons IO 1.4 requires Java 1.3 or later. ============================================================================== Apache Commons IO Version 2.4 ============================================================================== Changes in this version include: New features: o IO-269: Tailer locks file from deletion/rename on Windows. Thanks to sebb. o IO-333: Export OSGi packages at version 1.x in addition to 2.x. Thanks to fmeschbe. o IO-320: Add XmlStreamReader support for UTF-32. Thanks to ggregory. o IO-331: BOMInputStream wrongly detects UTF-32LE_BOM files as UTF-16LE_BOM files in method getBOM(). Thanks to ggregory. o IO-327: Add byteCountToDisplaySize(BigInteger). Thanks to ggregory. o IO-326: Add new FileUtils.sizeOf[Directory] APIs to return BigInteger. Thanks to ggregory. o IO-325: Add IOUtils.toByteArray methods to work with URL and URI. Thanks to raviprak. o IO-324: Add missing Charset sister APIs to method that take a String charset name. Thanks to raviprak. Fixed Bugs: o IO-336: Yottabyte (YB) incorrectly defined in FileUtils. Thanks to rleavelle. o IO-279: Tailer erroneously considers file as new. Thanks to Sergio Bossa, Chris Baron. o IO-335: Tailer#readLines - incorrect CR handling. o IO-334: FileUtils.toURLs throws NPE for null parameter; document the behavior. o IO-332: Improve tailer's reading performance. Thanks to liangly. o IO-279: Improve Tailer performance with buffered reads (see IO-332). o IO-329: FileUtils.writeLines uses unbuffered IO. Thanks to tivv. o IO-319: FileUtils.sizeOfDirectory follows symbolic links. Thanks to raviprak. Compatibility with 2.3: Binary compatible: Yes. Source compatible: Yes. Semantic compatible: Yes. Compatibility with 2.2 and 1.4: Binary compatible: Yes. Source compatible: No, see the rare case in https://issues.apache.org/jira/browse/IO-318. Semantic compatible: No, see the rare case in https://issues.apache.org/jira/browse/IO-318. Commons IO 2.4 requires Java 6 or later. Commons IO 2.3 requires Java 6 or later. Commons IO 2.2 requires Java 5 or later. Commons IO 1.4 requires Java 1.3 or later. ============================================================================== Apache Commons IO Version 2.3 ============================================================================== Changes in this version include: New features: o IO-322: Add and use class Charsets. Thanks to ggregory. o IO-321: ByteOrderMark UTF_32LE is incorrect. Thanks to ggregory. o IO-318: Add Charset sister APIs to method that take a String charset name. Thanks to ggregory. Compatibility with 2.2 and 1.4: Binary compatible: Yes. Source compatible: No, see the rare case in https://issues.apache.org/jira/browse/IO-318. Semantic compatible: No, see the rare case in https://issues.apache.org/jira/browse/IO-318. Commons IO 2.3 requires Java 6 or later. Commons IO 2.2 requires Java 5 or later. Commons IO 1.4 requires Java 1.3 or later. ============================================================================== Apache Commons IO Version 2.2 ============================================================================== Changes in this version include: New features: o Add IOUTils.toBufferedReader(Reader) Issue: IO-313. Thanks to ggregory. o Allow applications to provide buffer (or size) for copyLarge methods. Issue: IO-308. Thanks to Manoj Mokashi. o New copyLarge() method in IOUtils that takes additional offset, length arguments Issue: IO-305. Thanks to Manoj Mokashi. o Use terabyte (TB), petabyte (PB) and exabyte (EB) in FileUtils.byteCountToDisplaySize(long size) Issue: IO-287. Thanks to Ron Kuris, Gary Gregory. o FileUtils.listFiles() doesn't return directories Issue: IO-173. Thanks to Marcos Vincius da Silva. o CharSequenceInputStream to efficiently stream content of a CharSequence Issue: IO-297. Thanks to Oleg Kalnichevski. o The second constructor of Tailer class does not pass 'delay' to the third one Issue: IO-304. Thanks to liangly. o TeeOutputStream does not call branch.close() when main.close() throws an exception Issue: IO-303. Thanks to fabian.barney. o ArrayIndexOutOfBoundsException in BOMInputStream when reading a file without BOM multiple times Issue: IO-302. Thanks to jsteuerwald, detinho. o Add IOUtils.closeQuietly(Selector) necessary Issue: IO-301. Thanks to kaykay.unique. o IOUtils.closeQuietly() should take a ServerSocket as a parameter Issue: IO-292. Thanks to sebb. o Add read/readFully methods to IOUtils Issue: IO-290. Thanks to sebb. o Supply a ReversedLinesFileReader Issue: IO-288. Thanks to Georg Henzler. o Add new function FileUtils.directoryContains. Issue: IO-291. Thanks to ggregory. o FileUtils.contentEquals and IOUtils.contentEquals - Add option to ignore "line endings" Added contentEqualsIgnoreEOL methods to both classes Issue: IO-275. Thanks to CJ Aspromgos. Fixed Bugs: o IOUtils.read(InputStream/Reader) ignores the offset parameter Issue: IO-311. Thanks to Robert Muir. o CharSequenceInputStream(CharSequence s, Charset charset, int bufferSize) ignores bufferSize Issue: IO-312. o FileUtils.moveDirectoryToDirectory removes source directory if destination is a subdirectory Issue: IO-300. o ReaderInputStream#read(byte[] b, int off, int len) should check for valid parameters Issue: IO-307. o ReaderInputStream#read(byte[] b, int off, int len) should always return 0 for length == 0 Issue: IO-306. o "FileUtils#deleteDirectoryOnExit(File)" does not work Issue: IO-276. Thanks to nkami. o BoundedInputStream.read() treats max differently from BoundedInputStream.read(byte[]...) Issue: IO-273. Thanks to sebb. o Various methods of class 'org.apache.commons.io.FileUtils' incorrectly suppress 'java.io.IOException' Issue: IO-298. Thanks to Christian Schulte. Changes: o ReaderInputStream optimization: more efficient reading of small chunks of data Issue: IO-296. Thanks to Oleg Kalnichevski. Compatibility with 2.1 and 1.4: Binary compatible: Yes Source compatible: Yes Semantic compatible: Yes. Check the bug fixes section for semantic bug fixes Commons IO 2.2 requires a minimum of Java 5. Commons IO 1.4 requires a minimum of Java 1.3. ============================================================================== Apache Commons IO Version 2.1 ============================================================================== New features: o Use standard Maven directory layout Issue: IO-285. Thanks to ggregory. o Add IOUtils API toString for URL and URI to get contents Issue: IO-284. Thanks to ggregory. o Add API FileUtils.copyFile(File input, OutputStream output) Issue: IO-282. Thanks to ggregory. o FileAlterationObserver has no getter for FileFilter Issue: IO-262. o Add FileUtils.getFile API with varargs parameter Issue: IO-261. o Add new APPEND parameter for writing string into files Issue: IO-182. o Add new read method "toByteArray" to handle InputStream with known size. Issue: IO-251. Thanks to Marco Albini. Fixed Bugs: o Dubious use of mkdirs() return code Issue: IO-280. Thanks to sebb. o ReaderInputStream enters infinite loop when it encounters an unmappable character Issue: IO-277. o FileUtils.moveFile() Javadoc should specify FileExistsException thrown Issue: IO-264. o ClassLoaderObjectInputStream does not handle Proxy classes Issue: IO-260. o Tailer returning partial lines when reaching EOF before EOL Issue: IO-274. Thanks to Frank Grimes. o FileUtils.copyFile() throws IOException when copying large files to a shared directory (on Windows) Issue: IO-266. Thanks to Igor Smereka. o FileSystemUtils.freeSpaceKb throws exception for Windows volumes with no visible files. Improve coverage by also looking for hidden files. Issue: IO-263. Thanks to Gil Adam. Changes: o FileAlterationMonitor.stop(boolean allowIntervalToFinish) Issue: IO-259. ============================================================================== Apache Commons IO Package 2.0.1 ============================================================================== Compatibility with 2.0 and 1.4 ------------------------------ Binary compatible - Yes Source compatible - Yes Semantic compatible - Yes Check the bug fixes section for semantic bug fixes Commons IO 2.0.1 requires a minimum of Java 5 (Commons IO 1.4 had a minimum of Java 1.3) Enhancements from 2.0 --------------------- * [IO-256] - Provide thread factory for FileAlternationMonitor Bug fixes from 2.0 ------------------ * [IO-257] - BOMInputStream.read(byte[]) can return 0 which it should not * [IO-258] - XmlStreamReader consumes the stream during encoding detection ============================================================================== Apache Commons IO Package 2.0 ============================================================================== Compatibility with 1.4 ---------------------- Binary compatible - Yes Source compatible - Yes Semantic compatible - Yes Check the bug fixes section for semantic bug fixes Commons IO 2.0 requires a minimum of Java 5 (Commons IO 1.4 had a minimum of Java 1.3) Deprecations from 1.4 --------------------- - IOUtils - write(StringBuffer, Writer) in favour of write(CharSequence, Writer) - write(StringBuffer, OutputStream) in favour of write(CharSequence, OutputStream) - write(StringBuffer, OutputStream, String) in favour of write(CharSequence, OutputStream, String) - FileFilterUtils - andFileFilter(IOFileFilter, IOFileFilter) in favour of and(IOFileFilter...) - orFileFilter(IOFileFilter, IOFileFilter) in favour of or(IOFileFilter...) Enhancements from 1.4 --------------------- * [IO-140] Move minimum Java requirement from Java 1.3 to Java 5 - use Generics - add new CharSequence write() flavour methods to IOUtils and FileUtils - replace StringBuffer with StringBuilder, where appropriate - add new Reader/Writer methods to ProxyReader and ProxyWriter - Annotate with @Override and @Deprecated * [IO-178] New BOMInputStream and ByteOrderMark implementations - to detect and optionally exclude an initial Byte Order mark (BOM) * [IO-197] New BoundedInputStream (copied from from Apache JackRabbit) * [IO-193] New Broken Input and Output streams * [IO-132] New File Listener/Monitor facility * [IO-158] New ReaderInputStream and WriterOutputStream implementations * [IO-139] New StringBuilder Writer implementation * [IO-192] New Tagged Input and Output streams * [IO-177] New Tailer class - simple implementation of the Unix "tail -f" functionality * [IO-162] New XML Stream Reader/Writer implementations (from ROME via plexus-utils) * [IO-142] Comparators - add facility to sort file lists/arrays * [IO-186] Comparators - new Composite and Directory File Comparator implementations * [IO-176] DirectoryWalker - add filterDirectoryContents() callback method for filtering directory contents * [IO-210] FileFilter - new Magic Number FileFilter * [IO-221] FileFilterUtils - add methods for suffix and prefix filters which take an IOCase object * [IO-232] FileFilterUtils - add method for name filters which take an IOCase object * [IO-229] FileFilterUtils - add varargs and() and or() methods * [IO-198] FileFilterUtils - add ability to apply file filters to collections and arrays * [IO-156] FilenameUtils - add normalize() and normalizeNoEndSeparator() methods which allow the separator character to be specified * [IO-194] FileSystemUtils - add freeSpaceKb() method with no input arguments * [IO-185] FileSystemUtils - add freeSpaceKb() methods that take a timeout parameter - fixes freeSpaceWindows() blocks * [IO-155] FileUtils - use NIO to copy files * [IO-168] FileUtils - add new isSymlink() method * [IO-219] FileUtils - throw FileExistsException when moving a file or directory if the destination already exists * [IO-234] FileUtils - add Methods for retrieving System User/Temp directories/paths * [IO-208] FileUtils - add timeout (connection and read) support for copyURLToFile() method * [IO-238] FileUtils - add sizeOf(File) method * [IO-181] LineIterator now implements Iterable * [IO-224] IOUtils - add closeQuietly(Closeable) and closeQuietly(Socket) methods * [IO-203] IOUtils - add skipFully() method for InputStreams * [IO-137] IOUtils and ByteArrayOutputStream - add toBufferedInputStream() method to avoid unnecessary array allocation/copy * [IO-195] Proxy streams/Reader/Writer - provide exception handling methods * [IO-211] Proxy Input/Output streams - add pre/post processing support * [IO-242] Proxy Reader/Writer - add pre/post processing support Bug fixes from 1.4 ------------------ * [IO-214] ByteArrayOutputStream - fix inconsistent synchronization of fields * [IO-201] Counting Input/Output streams - fix inconsistent synchronization * [IO-159] FileCleaningTracker - fix remove() never returns null * [IO-220] FileCleaningTracker - fix Vector performs badly under load * [IO-167] FilenameUtils - fix case-insensitive string handling in FilenameUtils and FilesystemUtils * [IO-179] FilenameUtils - fix StringIndexOutOfBounds exception in getPathNoEndSeparator() * [IO-248] FilenameUtils - fix getFullPathNoEndSeparator() returns empty while path is a one level directory * [IO-246] FilenameUtils - fix wildcardMatch gives incorrect results * [IO-187] FileSystemUtils - fix freeSpaceKb() doesn't work with relative paths on Linux * [IO-160] FileSystemUtils - fix freeSpace() fails on solaris * [IO-209] FileSystemUtils - fix freeSpaceKb() fails to return correct size for a windows mount point * [IO-163] FileUtils - fix toURLs() using deprecated method of conversion to URL * [IO-168] FileUtils - fix Symbolic links followed when deleting directory * [IO-231] FileUtils - fix wrong exception message generated in isFileNewer() method * [IO-207] FileUtils - fix race condition in forceMkdir() method * [IO-217] FileUtils - fix copyDirectoryToDirectory() makes infinite loops * [IO-166] FileUtils - fix URL decoding in toFile(URL) * [IO-190] FileUtils - fix copyDirectory not preserving lastmodified date on sub-directories * [IO-240] FileFilterUtils - ensure cvsFilter and svnFilter are only created once. * [IO-175] IOUtils - fix copyFile() issues with very large files * [IO-191] Improvements from static analysis * [IO-216] LockableFileWriter - delete files quietly when an exception is thrown during initialization * [IO-243] SwappedDataInputStream - fix readBoolean is inverted * [IO-235] Tests - remove unused YellOnFlushAndCloseOutputStream from CopyUtilsTest * [IO-161] Tests - fix FileCleaningTrackerTestCase hanging Documentation changes from 1.4 ------------------------------ * [IO-183 FilenameUtils.getExtension() method documentation improvements * [IO-226 FileUtils.byteCountToDisplaySize() documentation corrections * [IO-205 FileUtils.forceMkdir() documentation improvements * [IO-215 FileUtils copy file/directory improve documentation regarding preserving the last modified date * [IO-189 HexDump.dump() method documentation improvements * [IO-171 IOCase document that it assumes there are only two OSes: Windows and Unix * [IO-223 IOUtils.copy() documentation corrections * [IO-247 IOUtils.closeQuietly() improve documentation with examples * [IO-202 NotFileFilter documentation corrections * [IO-206 ProxyInputStream - fix misleading parameter names * [IO-212 ProxyInputStream.skip() documentation corrections ============================================================================== Apache Commons IO Version 1.4 ============================================================================== Compatibility with 1.3.2 ------------------------ Binary compatible - Yes Source compatible - Yes Semantic compatible - Yes Check the bug fixes section for semantic bug fixes Commons IO 1.4 introduces four new implementations which depend on Java 4 features (CharSequenceReader, FileWriterWithEncoding, IOExceptionWithCause and RegexFileFilter). It has been built with the JDK source and target options set to Java 1.3 and, except for those implementations, can be used with Java 1.3 (see IO IO-127). Deprecations from 1.3.2 ----------------------- - FileCleaner deprecated in favour of FileCleaningTracker [see IO-116] Bug fixes from 1.3.2 -------------------- - FileUtils - forceDelete of orphaned Softlinks does not work [IO-147] - Infinite loop on FileUtils.copyDirectory when the destination directory is within the source directory [IO-141] - Add a copyDirectory() method that makes use of FileFilter [IO-105] - Add moveDirectory() and moveFile() methods [IO-77] - HexDump - HexDump's use of static StringBuffers isn't thread-safe [IO-136] Enhancements from 1.3.2 ----------------------- - FileUtils - Add a deleteQuietly method [IO-135] - FilenameUtils - Add file name extension separator constants[IO-149] - IOExceptionWithCause [IO-148] - Add a new IOException implementation with constructors which take a cause - TeeInputStream [IO-129] - Add new Tee input stream implementation - FileWriterWithEncoding [IO-153] - Add new File Writer implementation that accepts an encoding - CharSequenceReader [IO-138] - Add new Reader implementation that handles any CharSequence (String, StringBuffer, StringBuilder or CharBuffer) - ThesholdingOuputStream [IO-121] - Add a reset() method which sets the count of the bytes written back to zero. - DeferredFileOutputStream [IO-130] - Add support for temporary files - ByteArrayOutputStream - Add a new write(InputStream) method [IO-152] - New Closed Input/Output stream implementations [IO-122] - AutoCloseInputStream - automatically closes and discards the underlying input stream - ClosedInputStream - returns -1 for any read attempts - ClosedOutputStream - throws an IOException for any write attempts - CloseShieldInputStream - prevents the underlying input stream from being closed. - CloseShieldOutputStream - prevents the underlying output stream from being closed. - Add Singleton Constants to several stream classes [IO-143] - PrefixFileFilter [IO-126] - Add faciltiy to specify case sensitivity on prefix matching - SuffixFileFilter [IO-126] - Add faciltiy to specify case sensitivity on suffix matching - RegexFileFilter [IO-74] - Add new regular expression file filter implementation - Make IOFileFilter implementations Serializable [IO-131] - Improve IOFileFilter toString() methods [IO-120] - Make fields final so classes are immutable/threadsafe [IO-133] - changes to Age, Delegate, Name, Not, Prefix, Regex, Size, Suffix and Wildcard IOFileFilter implementations. - IOCase - Add a compare method to IOCase [IO-144] - Add a package of java.util.Comparator implementations for files [IO-145] - DefaultFileComparator - compare files using the default File.compareTo(File) method. - ExtensionFileComparator - compares files using file name extensions. - LastModifiedFileComparator - compares files using the last modified date/time. - NameFileComparator - compares files using file names. - PathFileComparator - compares files using file paths. - SizeFileComparator - compares files using file sizes. ============================================================================== Apache Commons IO Version 1.3.2 ============================================================================== Compatibility with 1.3.1 ---------------------- Binary compatible - Yes Source compatible - Yes Semantic compatible - Yes Compatibility with 1.3 ---------------------- Binary compatible - No See [IO-113] Source compatible - No See [IO-113] Semantic compatible - Yes Enhancements since 1.3.1 ------------------------ - Created the FileCleaningTracker, basically a non-static version of the FileCleaner, which can be controlled by the user. [IO-116] - The FileCleaner is deprecated. Bug fixes from 1.3.1 -------------------- - Some tests, which are implicitly assuming a Unix-like file system, are now skipped on Windows. [IO-115] - EndianUtils - Both readSwappedUnsignedInteger(...) methods could return negative numbers due to int/long casting. [IO-117] Bug fixes from 1.3 ------------------ - FileUtils - NPE in openOutputStream(File) when file has no parent in path [IO-112] - readFileToString(File) is not static [IO-113] ============================================================================== Apache Commons IO Version 1.3.1 ============================================================================== Compatibility with 1.3 ---------------------- Binary compatible - No See [IO-113] Source compatible - No See [IO-113] Semantic compatible - Yes Bug fixes from 1.3 ------------------ - FileUtils - NPE in openOutputStream(File) when file has no parent in path [IO-112] - readFileToString(File) is not static [IO-113] ============================================================================== Apache Commons IO Version 1.3 ============================================================================== Compatibility with 1.2 ---------------------- Binary compatible - Yes Source compatible - Yes Semantic compatible - Yes Check the bug fixes section for semantic bug fixes Deprecations from 1.2 --------------------- - WildcardFilter deprecated, replaced by WildcardFileFilter - old class only accepted files, thus had a confusing dual purpose - FileSystemUtils.freeSpace deprecated, replaced by freeSpaceKb - freeSpace returns a result that varies by operating system and thus isn't that useful - freeSpaceKb returns much better and more consistent results - freeSpaceKb existed in v1.2, so this is a gentle cutover Bug fixes from 1.2 ------------------ - LineIterator now implements Iterator - It was always supposed to... - FileSystemUtils.freeSpace/freeSpaceKb [IO-83] - These should now work on AIX and HP-UX - FileSystemUtils.freeSpace/freeSpaceKb [IO-90] - Avoid infinite looping in Windows - Catch more errors with nice messages - FileSystemUtils.freeSpace [IO-91] - This is now documented not to work on SunOS 5 - FileSystemUtils [IO-93] - Fixed resource leak leading to 'Too many open files' error - Previously did not destroy Process instances (as JDK Javadoc is so poor) - http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4801027 - FileUtils.touch [IO-100] - The touch method previously gave no indication when the file could not be touched successfully (such as due to access restrictions) - it now throws an IOException if the last modified date cannot be changed - FileCleaner - This now handles the situation where an error occurs when deleting the file - IOUtils.copy [IO-84] - Copy methods could return inaccurate byte/char count for large streams - The copy(InputStream, OutputStream) method now returns -1 if the count is greater than an int - The copy(Reader, Writer) method now throws now returns -1 if the count is greater than an int - Added a new copyLarge(InputStream, OutputStream) method that returns a long - Added a new copyLarge(Reader, Writer) method that returns a long - CountingInputStream/CountingOutputStream [IO-84] - Methods were declared as int thus the count was innacurate for large streams - new long based methods getByteCount()/resetByteCount() added - existing methods changed to throw an exception if the count is greater than an int - FileBasedTestCase - Fixed bug in compare content methods identified by GNU classpath - EndianUtils.writeSwappedLong(byte[], int) [IO-101] - An int overrun in the bit shifting when it should have been a long - EndianUtils.writeSwappedLong(InputStream) [IO-102] - The return of input.read(byte[]) was not being checked to ensure all 8 bytes were read Enhancements from 1.2 --------------------- - DirectoryWalker [IO-86] - New class designed for subclassing to walk through a set of files. DirectoryWalker provides the walk of the directories, filtering of directories and files, and cancellation support. The subclass must provide the specific behavior, such as text searching or image processing. - IOCase - New class/enumeration for case-sensitivity control - FilenameUtils - New methods to handle case-sensitivity - wildcardMatch - new method that has IOCase as a parameter - equals - new method that has IOCase as a parameter - FileUtils [IO-108] - new default encoding methods for: - readFileToString(File) - readLines(File) - lineIterator(File) - writeStringToFile(File, String) - writeLines(File, Collection) - writeLines(File, Collection, String) - FileUtils.openOutputStream [IO-107] - new method to open a FileOutputStream, creating parent directories if required - FileUtils.touch - FileUtils.copyURLToFile - FileUtils.writeStringToFile - FileUtils.writeByteArrayToFile - FileUtils.writeLines - enhanced to create parent directories if required - FileUtils.openInputStream [IO-107] - new method to open a FileInputStream, providing better error messages than the JDK - FileUtils.isFileOlder - new methods to check if a file is older (i.e. isFileOlder()) - counterparts to the existing isFileNewer() methods. - FileUtils.checksum, FileUtils.checksumCRC32 - new methods to create a checksum of a file - FileUtils.copyFileToDirectory [IO-104] - new variant that optionally retains the file date - FileDeleteStrategy - FileCleaner [IO-56,IO-70] - FileDeleteStrategy is a strategy for handling file deletion - This can be used as a calback in FileCleaner - Together these allow FileCleaner to do a forceDelete to kill directories - FileCleaner.exitWhenFinished [IO-99] - A new method that allows the internal cleaner thread to be cleanly terminated - WildcardFileFilter - Replacement for WildcardFilter - Accepts both files and directories - Ability to control case-sensitivity - NameFileFilter - Ability to control case-sensitivity - FileFileFilter - New IOFileFilter implementation - Accepts files where File.isFile() is true - In other words it filters out directories - Singleton instance provided (FILE) - CanReadFileFilter - New IOFileFilter implementation - Accepts files where File.canRead() is true - Singleton instances provided (CAN_READ/CANNOT_READ/READ_ONLY) - CanWriteFileFilter - New IOFileFilter implementation - Accepts files where File.canWrite() is true - Singleton instances provided (CAN_WRITE/CANNOT_WRITE) - HiddenFileFilter - New IOFileFilter implementation - Accepts files where File.isHidden() is true - Singleton instances provided (HIDDEN/VISIBLE) - EmptyFileFilter - New IOFileFilter implementation - Accepts files or directories that are empty - Singleton instances provided (EMPTY/NOT_EMPTY) - TrueFileFilter/FalseFileFilter/DirectoryFileFilter - New singleton instance constants (TRUE/FALSE/DIRECTORY) - The new constants are more Java 5 friendly with regards to static imports (whereas if everything uses INSTANCE, then they just clash) - The old INSTANCE constants are still present and have not been deprecated - FileFilterUtils.sizeRangeFileFilter - new sizeRangeFileFilter(long minimumSize, long maximumSize) method which creates a filter that accepts files within the specified size range. - FileFilterUtils.makeDirectoryOnly/makeFileOnly - two new methods that decorate a file filter to make it apply to directories only or files only - NullWriter - New writer that acts as a sink for all data, as per /dev/null - NullInputStream - New input stream that emulates a stream of a specified size - NullReader - New reader that emulates a reader of a specified size - ByteArrayOutputStream [IO-97] - Performance enhancements ============================================================================== Apache Commons IO Version 1.2 ============================================================================== Compatibility with 1.1 ---------------------- Binary compatible - Yes Source compatible - Yes Semantic compatible - Yes Deprecations from 1.1 --------------------- Bug fixes from 1.1 ------------------ - FileSystemUtils.freeSpace(drive) Fix to allow Windows based command to function in French locale - FileUtils.read* Increase certainty that files are closed in case of error - LockableFileWriter Locking mechanism was broken and only provided limited protection [38942] File deletion and locking in case of constructor error was broken Enhancements from 1.1 --------------------- - AgeFileFilter/SizeFileFilter New file filters that compares against the age and size of the file - FileSystemUtils.freeSpaceKb(drive) New method that unifies result to be in kilobytes [38574] - FileUtils.contentEquals(File,File) Performance improved by adding length and file location checking - FileUtils.iterateFiles Two new method to provide direct access to iterators over files - FileUtils.lineIterator IOUtils.lineIterator New methods to provide an iterator over the lines in a file [38083] - FileUtils.copyDirectoryToDirectory New method to copy a directory to within another directory [36315] ============================================================================== Apache Commons IO Version 1.1 ============================================================================== Incompatible changes from 1.0 ----------------------------- Binary compatible - Yes Source compatible - Yes Semantic compatible - Yes, except: - FileUtils.writeStringToFile() A null encoding previously used 'ISO-8859-1', now it uses the platform default Generally this will make no difference - LockableFileWriter Improved validation and now create directories if necesssary plus these bug fixes may affect you semantically: - FileUtils.touch() (Bug fix 29821) Now creates the file if it did not previously exist - FileUtils.toFile(URL) (Bug fix 32575) Now handles escape syntax such as %20 - FileUtils.sizeOfDirectory() (Bug fix 36801) May now return a size of 0 if the directory is security restricted Deprecations from 1.0 --------------------- - CopyUtils has been deprecated. Its methods have been moved to IOUtils. The new IOUtils methods handle nulls better, and have clearer names. - IOUtils.toByteArray(String) - Use {@link String#getBytes()} - IOUtils.toString(byte[]) - Use {@link String#String(byte[])} - IOUtils.toString(byte[],String) - Use {@link String#String(byte[],String)} Bug fixes from 1.0 ------------------ - FileUtils - touch() [29821] Now creates the file if it did not previously exist - FileUtils - toFile(URL) [32575] Now handles escape syntax such as %20 - FileFilterUtils - makeCVSAware(IOFileFilter) [33023] Fixed bug that caused method to be completely broken - CountingInputStream [33336] Fixed bug that caused the count to reduce by one at the end of the stream - CountingInputStream - skip(long) [34311] Bytes from calls to this method were not previously counted - NullOutputStream [33481] Remove unnecessary synchronization - AbstractFileFilter - accept(File, String) [30992] Fixed broken implementation - FileUtils [36801] Previously threw NPE when listing files in a security restricted directory Now throw IOException with a better message - FileUtils - writeStringToFile() Null encoding now correctly uses the platform default Enhancements from 1.0 --------------------- - FilenameUtils - new class [33303,29351] A static utility class for working with filenames Seeks to ease the pain of developing on Windows and deploying on Unix - FileSystemUtils - new class [32982,36325] A static utility class for working with file systems Provides one method at present, to get the free space on the filing system - IOUtils - new public constants Constants for directory and line separators on Windows and Unix - IOUtils - toByteArray(Reader,encoding) Handles encodings when reading to a byte array - IOUtils - toCharArray(InputStream) [28979] - toCharArray(InputStream,encoding) - toCharArray(Reader) Reads a stream/reader into a charatcter array - IOUtils - readLines(InputStream) [36214] - readLines(InputStream,encoding) - readLines(Reader) Reads a stream/reader line by line into a List of Strings - IOUtils - toInputStream(String) [32958] - toInputStream(String,encoding) Creates an input stream that uses the string as a source of data - IOUtils - writeLines(Collection,lineEnding,OutputStream) [36214] - writeLines(Collection,lineEnding,OutputStream,encoding) - writeLines(Collection,lineEnding,Writer) Writes a collection to a stream/writer line by line - IOUtils - write(...) Write data to a stream/writer (moved from CopyUtils with better null handling) - IOUtils - copy(...) Copy data between streams (moved from CopyUtils with better null handling) - IOUtils - contentEquals(Reader,Reader) Method to compare the contents of two readers - FileUtils - toFiles(URL[]) Converts an array of URLs to an array of Files - FileUtils - copyDirectory() [32944] New methods to copy a directory - FileUtils - readFileToByteArray(File) Reads an entire file into a byte array - FileUtils - writeByteArrayToFile(File,byte[]) Writes a byte array to a file - FileUtils - readLines(File,encoding) [36214] Reads a file line by line into a List of Strings - FileUtils - writeLines(File,encoding,List) writeLines(File,encoding,List,lineEnding) Writes a collection to a file line by line - FileUtils - EMPTY_FILE_ARRAY Constant for an empty array of File objects - ConditionalFileFilter - new interface [30705] Defines the behavior of list based filters - AndFileFilter, OrFileFilter [30705] Now support a list of filters to and/or - WildcardFilter [31115] New filter that can match using wildcard file names - FileFilterUtils - makeSVNAware(IOFileFilter) New method, like makeCVSAware, that ignores Subversion source control directories - ClassLoaderObjectInputStream An ObjectInputStream that supports a ClassLoader - CountingInputStream,CountingOutputStream - resetCount() [28976] Adds the ability to reset the count part way through reading/writing the stream - DeferredFileOutputStream - writeTo(OutputStream) [34173] New method to allow current contents to be written to a stream - DeferredFileOutputStream [34142] Performance optimizations avoiding double buffering - LockableFileWriter - encoding support [36825] Add support for character encodings to LockableFileWriter Improve the validation Create directories if necesssary - IOUtils and EndianUtils are no longer final [28978] Allows developers to have subclasses if desired ============================================================================== Feedback ============================================================================== Open source works best when you give feedback: https://commons.apache.org/io/ Please direct all bug reports to JIRA https://issues.apache.org/jira/browse/IO Or subscribe to the commons-user mailing list (prefix emails by [io]) https://commons.apache.org/mail-lists.html The Commons-IO Team commons-io-2.11.0-src/SECURITY.md0100644 0000000 0000000 00000001604 13612062727 016577 0ustar00rootroot0000000 0000000 The Apache Commons security page is [https://commons.apache.org/security.html](https://commons.apache.org/security.html). commons-io-2.11.0-src/checkstyle.xml0100644 0000000 0000000 00000003263 13612062727 017671 0ustar00rootroot0000000 0000000 commons-io-2.11.0-src/pom.xml0100644 0000000 0000000 00000046421 13612062727 016331 0ustar00rootroot0000000 0000000 org.apache.commons commons-parent 52 4.0.0 commons-io commons-io 2.11.0 Apache Commons IO 2002 The Apache Commons IO library contains utility classes, stream implementations, file filters, file comparators, endian transformation classes, and much more. https://commons.apache.org/proper/commons-io/ jira https://issues.apache.org/jira/browse/IO apache.website Apache Commons Site scm:svn:https://svn.apache.org/repos/infra/websites/production/commons/content/proper/commons-io/ scm:git:https://gitbox.apache.org/repos/asf/commons-io.git scm:git:https://gitbox.apache.org/repos/asf/commons-io.git https://gitbox.apache.org/repos/asf?p=commons-io.git rel/commons-io-2.11.0 Scott Sanders sanders sanders@apache.org Java Developer dIon Gillard dion dion@apache.org Java Developer Nicola Ken Barozzi nicolaken nicolaken@apache.org Java Developer Henri Yandell bayard bayard@apache.org Java Developer Stephen Colebourne scolebourne Java Developer 0 Jeremias Maerki jeremias jeremias@apache.org Java Developer +1 Matthew Hawthorne matth matth@apache.org Java Developer Martin Cooper martinc martinc@apache.org Java Developer Rob Oxspring roxspring roxspring@apache.org Java Developer Jochen Wiedmann jochen jochen.wiedmann@gmail.com Niall Pemberton niallp Java Developer Jukka Zitting jukka Java Developer ggregory Gary Gregory ggregory at apache.org https://www.garygregory.com The Apache Software Foundation https://www.apache.org/ PMC Member America/New_York https://people.apache.org/~ggregory/img/garydgregory80.png Kristian Rosenvold krosenvold krosenvold@apache.org +1 Rahul Akolkar Jason Anderson Nathan Beyer Emmanuel Bourg Chris Eldredge Magnus Grimsell Jim Harrington Thomas Ledoux Andy Lehane Marcelo Liberato Alban Peignier alban.peignier at free.fr Adam Retter Evolved Binary Ian Springer Dominik Stadler Masato Tezuka James Urie Frank W. Zammetti org.junit junit-bom 5.7.2 pom import org.junit.jupiter junit-jupiter test org.junit-pioneer junit-pioneer 1.4.2 test org.mockito mockito-inline 3.11.2 test com.google.jimfs jimfs 1.2 test org.apache.commons commons-lang3 3.12.0 test org.openjdk.jmh jmh-core ${jmh.version} test org.openjdk.jmh jmh-generator-annprocess ${jmh.version} test 1.8 1.8 io org.apache.commons.io RC1 2.10.0 2.11.0 (requires Java 8) IO 12310477 org.apache.commons.io; org.apache.commons.io.comparator; org.apache.commons.io.filefilter; org.apache.commons.io.input; org.apache.commons.io.output;version=1.4.9999;-noimport:=true, org.apache.commons.io; org.apache.commons.io.comparator; org.apache.commons.io.filefilter; org.apache.commons.io.input; org.apache.commons.io.output; org.apache.commons.io.*;version=${project.version};-noimport:=true sun.nio.ch;resolution:=optional, sun.misc;resolution:=optional, * https://svn.apache.org/repos/infra/websites/production/commons/content/proper/commons-io/ site-content 3.1.2 0.8.7 3.0.0-M5 0.15.3 4.2.3 4.3.0 1.32 false ${env.JACOCO_SKIP} true Gary Gregory 86fdc7e2a11262cb clean package apache-rat:check japicmp:cmp checkstyle:check javadoc:javadoc org.apache.rat apache-rat-plugin 0.13 src/test/resources/**/*.bin src/test/resources/dir-equals-tests/** test/** org.apache.maven.plugins maven-checkstyle-plugin ${checkstyle.plugin.version} ${basedir}/checkstyle.xml false com.puppycrawl.tools checkstyle 8.44 org.apache.maven.plugins maven-enforcer-plugin 3.0.0-M3 enforce-maven enforce 3.0.5 org.apache.maven.plugins maven-jar-plugin test-jar ${commons.module.name} org.apache.maven.plugins maven-surefire-plugin xerces:xercesImpl 1 false ${argLine} -Xmx25M **/*Test*.class **/*AbstractTestCase* **/testtools/** **/*$* maven-assembly-plugin src/assembly/bin.xml src/assembly/src.xml gnu org.apache.maven.plugins maven-checkstyle-plugin org.apache.maven.plugins maven-scm-publish-plugin javadocs com.github.spotbugs spotbugs-maven-plugin ${spotbugs.plugin.version} com.github.spotbugs spotbugs ${spotbugs.impl.version} ${basedir}/spotbugs-exclude-filter.xml com.github.siom79.japicmp japicmp-maven-plugin org.apache.maven.plugins maven-checkstyle-plugin com.github.spotbugs spotbugs-maven-plugin ${spotbugs.plugin.version} ${basedir}/spotbugs-exclude-filter.xml com.github.siom79.japicmp japicmp-maven-plugin setup-checkout site-content org.apache.maven.plugins maven-antrun-plugin 3.0.0 prepare-checkout pre-site run java9+ [9,) true benchmark true org.apache org.codehaus.mojo exec-maven-plugin 3.0.0 benchmark test exec test java -classpath org.openjdk.jmh.Main -rf json -rff target/jmh-result.${benchmark}.json ${benchmark} commons-io-2.11.0-src/spotbugs-exclude-filter.xml0100644 0000000 0000000 00000003072 13612062727 022311 0ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/0040755 0000000 0000000 00000000000 13612062727 015577 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/assembly/0040755 0000000 0000000 00000000000 13612062727 017416 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/changes/0040755 0000000 0000000 00000000000 13612062727 017207 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/main/0040755 0000000 0000000 00000000000 13612062727 016523 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/main/java/0040755 0000000 0000000 00000000000 13612062727 017444 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/main/java/org/0040755 0000000 0000000 00000000000 13612062727 020233 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/main/java/org/apache/0040755 0000000 0000000 00000000000 13612062727 021454 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/main/java/org/apache/commons/0040755 0000000 0000000 00000000000 13612062727 023127 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/main/java/org/apache/commons/io/0040755 0000000 0000000 00000000000 13612062727 023536 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/main/java/org/apache/commons/io/comparator/0040755 0000000 0000000 00000000000 13612062727 025705 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/main/java/org/apache/commons/io/file/0040755 0000000 0000000 00000000000 13612062727 024455 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/main/java/org/apache/commons/io/file/spi/0040755 0000000 0000000 00000000000 13612062727 025250 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/main/java/org/apache/commons/io/filefilter/0040755 0000000 0000000 00000000000 13612062727 025663 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/main/java/org/apache/commons/io/function/0040755 0000000 0000000 00000000000 13612062727 025363 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/0040755 0000000 0000000 00000000000 13612062727 024675 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/buffer/0040755 0000000 0000000 00000000000 13612062727 026146 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/main/java/org/apache/commons/io/monitor/0040755 0000000 0000000 00000000000 13612062727 025225 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/main/java/org/apache/commons/io/output/0040755 0000000 0000000 00000000000 13612062727 025076 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/main/java/org/apache/commons/io/serialization/0040755 0000000 0000000 00000000000 13612062727 026413 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/media/0040755 0000000 0000000 00000000000 13612062727 016656 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/site/0040755 0000000 0000000 00000000000 13612062727 016543 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/site/resources/0040755 0000000 0000000 00000000000 13612062727 020555 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/site/resources/images/0040755 0000000 0000000 00000000000 13612062727 022022 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/site/xdoc/0040755 0000000 0000000 00000000000 13612062727 017500 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/test/0040755 0000000 0000000 00000000000 13612062727 016556 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/test/java/0040755 0000000 0000000 00000000000 13612062727 017477 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/test/java/org/0040755 0000000 0000000 00000000000 13612062727 020266 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/test/java/org/apache/0040755 0000000 0000000 00000000000 13612062727 021507 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/test/java/org/apache/commons/0040755 0000000 0000000 00000000000 13612062727 023162 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/test/java/org/apache/commons/io/0040755 0000000 0000000 00000000000 13612062727 023571 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/test/java/org/apache/commons/io/comparator/0040755 0000000 0000000 00000000000 13612062727 025740 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/test/java/org/apache/commons/io/file/0040755 0000000 0000000 00000000000 13612062727 024510 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/test/java/org/apache/commons/io/file/spi/0040755 0000000 0000000 00000000000 13612062727 025303 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/test/java/org/apache/commons/io/filefilter/0040755 0000000 0000000 00000000000 13612062727 025716 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/test/java/org/apache/commons/io/function/0040755 0000000 0000000 00000000000 13612062727 025416 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/0040755 0000000 0000000 00000000000 13612062727 024730 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/buffer/0040755 0000000 0000000 00000000000 13612062727 026201 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/compatibility/0040755 0000000 0000000 00000000000 13612062727 027601 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/test/java/org/apache/commons/io/jmh/0040755 0000000 0000000 00000000000 13612062727 024347 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/test/java/org/apache/commons/io/monitor/0040755 0000000 0000000 00000000000 13612062727 025260 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/test/java/org/apache/commons/io/output/0040755 0000000 0000000 00000000000 13612062727 025131 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/test/java/org/apache/commons/io/serialization/0040755 0000000 0000000 00000000000 13612062727 026446 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/test/java/org/apache/commons/io/test/0040755 0000000 0000000 00000000000 13612062727 024550 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/test/resources/0040755 0000000 0000000 00000000000 13612062727 020570 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/test/resources/dir-equals-tests/0040755 0000000 0000000 00000000000 13612062727 023776 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/0040755 0000000 0000000 00000000000 13612062727 030643 5ustar00rootroot0000000 0000000 ././@LongLink0100644 0000000 0000000 00000000145 13612062727 011641 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files1/commons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files1/0040755 0000000 0000000 00000000000 13612062727 033525 5ustar00rootroot0000000 0000000 ././@LongLink0100644 0000000 0000000 00000000173 13612062727 011642 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files1/directory-files-only1/commons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files1/0040755 0000000 0000000 00000000000 13612062727 033525 5ustar00rootroot0000000 0000000 ././@LongLink0100644 0000000 0000000 00000000145 13612062727 011641 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files2/commons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files2/0040755 0000000 0000000 00000000000 13612062727 033526 5ustar00rootroot0000000 0000000 ././@LongLink0100644 0000000 0000000 00000000173 13612062727 011642 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files2/directory-files-only2/commons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files2/0040755 0000000 0000000 00000000000 13612062727 033526 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/0040755 0000000 0000000 00000000000 13612062727 031037 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/dir1/0040755 0000000 0000000 00000000000 13612062727 031676 5ustar00rootroot0000000 0000000 ././@LongLink0100644 0000000 0000000 00000000161 13612062727 011637 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/dir1/directory-files-only1/commons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/dir1/directory-0040755 0000000 0000000 00000000000 13612062727 033700 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/dir2/0040755 0000000 0000000 00000000000 13612062727 031677 5ustar00rootroot0000000 0000000 ././@LongLink0100644 0000000 0000000 00000000161 13612062727 011637 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/dir2/directory-files-only1/commons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/dir2/directory-0040755 0000000 0000000 00000000000 13612062727 033701 5ustar00rootroot0000000 0000000 ././@LongLink0100644 0000000 0000000 00000000154 13612062727 011641 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/directory-files-only1/commons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/directory-files0040755 0000000 0000000 00000000000 13612062727 034064 5ustar00rootroot0000000 0000000 ././@LongLink0100644 0000000 0000000 00000000154 13612062727 011641 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/directory-files-only2/commons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/directory-files0040755 0000000 0000000 00000000000 13612062727 034064 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-files-only/0040755 0000000 0000000 00000000000 13612062727 030123 5ustar00rootroot0000000 0000000 ././@LongLink0100644 0000000 0000000 00000000147 13612062727 011643 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-files-only/directory-files-only1/commons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-files-only/directory-files-only0040755 0000000 0000000 00000000000 13612062727 034127 5ustar00rootroot0000000 0000000 ././@LongLink0100644 0000000 0000000 00000000147 13612062727 011643 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-files-only/directory-files-only2/commons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-files-only/directory-files-only0040755 0000000 0000000 00000000000 13612062727 034127 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/test/resources/org/0040755 0000000 0000000 00000000000 13612062727 021357 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/test/resources/org/apache/0040755 0000000 0000000 00000000000 13612062727 022600 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/test/resources/org/apache/commons/0040755 0000000 0000000 00000000000 13612062727 024253 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/test/resources/org/apache/commons/io/0040755 0000000 0000000 00000000000 13612062727 024662 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/test/resources/org/apache/commons/io/dirs-1-file-size-0/0040755 0000000 0000000 00000000000 13612062727 030003 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/test/resources/org/apache/commons/io/dirs-1-file-size-1/0040755 0000000 0000000 00000000000 13612062727 030004 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/test/resources/org/apache/commons/io/dirs-2-file-size-2/0040755 0000000 0000000 00000000000 13612062727 030006 5ustar00rootroot0000000 0000000 ././@LongLink0100644 0000000 0000000 00000000146 13612062727 011642 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/resources/org/apache/commons/io/dirs-2-file-size-2/dirs-a-file-size-1/commons-io-2.11.0-src/src/test/resources/org/apache/commons/io/dirs-2-file-size-2/dirs-a-file-size-10040755 0000000 0000000 00000000000 13612062727 033131 5ustar00rootroot0000000 0000000 ././@LongLink0100644 0000000 0000000 00000000146 13612062727 011642 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/resources/org/apache/commons/io/dirs-2-file-size-2/dirs-b-file-size-1/commons-io-2.11.0-src/src/test/resources/org/apache/commons/io/dirs-2-file-size-2/dirs-b-file-size-10040755 0000000 0000000 00000000000 13612062727 033132 5ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/assembly/bin.xml0100644 0000000 0000000 00000003404 13612062727 020706 0ustar00rootroot0000000 0000000 bin tar.gz zip false LICENSE.txt NOTICE.txt RELEASE-NOTES.txt target *.jar target/site/apidocs docs **/customsorttypes.js **/sortabletable.js **/stringbuilder.js commons-io-2.11.0-src/src/assembly/src.xml0100644 0000000 0000000 00000003210 13612062727 020720 0ustar00rootroot0000000 0000000 src tar.gz zip ${artifactId}-${commons.release.version}-src checkstyle.xml CONTRIBUTING.md LICENSE.txt NOTICE.txt pom.xml PROPOSAL.html README.md RELEASE-NOTES.txt SECURITY.md spotbugs-exclude-filter.xml src commons-io-2.11.0-src/src/changes/changes.xml0100644 0000000 0000000 00000172353 13612062727 021351 0ustar00rootroot0000000 0000000 Apache Commons IO Release Notes FileUtils.listFiles does not list matching files if File parameter is a symbolic link. FileUtils#deleteDirectory(File) exception Javadoc inaccurate update #245. Minor changes #243. Replace construction of FileInputStream and FileOutputStream objects with Files NIO APIs. #221. Fix IndexOutOfBoundsException in IOExceptionList constructors. Remove IOException from the method signatures that no longer throw IOException. This maintains binary compatibility but not source compatibility. - FilenameUtils directoryContains(String, String) - BoundedReader BoundedReader(java.io.Reader, int) - IOUtils lineIterator(java.io.InputStream, Charset) lineIterator(java.io.InputStream, String) toByteArray(String) toInputStream(CharSequence, String) toInputStream(String, String) toString(byte[]) toString(byte[], String) Add SymbolicLinkFileFilter. Add test to make sure the setter of AndFileFilter works correctly #244. Add XmlStreamReader(Path). Bump mockito-inline from 3.11.0 to 3.11.2 #247. Bump jmh.version from 1.27 to 1.32 #237. Bump spotbugs from 4.2.3 to 4.3.0 #249. RegexFileFilter uses the path and file name instead of just the file name. The OSGi manifest now contains sun.* import packages #239. Sanitize double slash after prefix #79. Add and use RegexFileFilter.toString(). Add and use RegexFileFilter.RegexFileFilter(Pattern, Function<Path>, String>) Add and use IOCase.isCaseSensitive(IOCase). Bump actions/cache from 2.1.5 to 2.1.6 #238. Bump junit-pioneer from 1.4.1 to 1.4.2 #240. Bump checkstyle from 8.42 to 8.44 #241, #248. Bump mockito-inline from 3.10.0 to 3.11.0 #242. IOUtils.toByteArray(InputStream) Javadoc does not match code. FileUtils: Remove Instant->ZonedDateTime->Instant round-trip. Make FilenameUtils.equals() not throw an exception #154. Un-deprecate IOUtils.closeQuietly() methods. FileUtils#copyDirectory(File, File, FileFilter, preserveFileDate) clean up #163. AccumulatorPathVisitor does not track directories properly. FileUtils.iterateFiles runs out of memory when executed for a directory with large number of files. Re-implement FileUtils' iterateFiles(), iterateFilesAndDirs(), listFiles(), listFilesAndDirs() to use NIO file tree walking instead of IO file listings to avoid memory consumption issues on large file trees. FileUtils.forceDelete(File) actually forces deletion of read-only files as it did in version 2.6. PathUtils.deleteFile() no longer throws a NoSuchFileException when applied on a symbolic link pointing to a file that doesn't exist. Behavior change in FileUtils.copyDirectory() file last modified timestamp preservation. Match Javadoc to code. Fix getPrefixLength method for Linux filename #179. Wrong logging in FileUtils.setLastModified. IOUtils.toByteArray(InputStream) Javadoc does not match code. CopyUtils deprecation message gives wrong version. Make PathUtils.setReadOnly deal with LinuxDosFileAttributeView #186. FileUtils.forceDelete does not delete invalid links. #187. IOUtils.toByteArray(null) no longer throws a NullPointerException. MarkShieldInputStream#reset should throw UnsupportedOperationException. LockableFileWriter.close() should fail when the lock file cannot be deleted. Fix infinite loops in ObservableInputStream read(*) when an exception is caught but not re-thrown. Fixed error of copying directories between different file systems #203. Fix Typos in JavaDoc, Comments and Tests #201. FileUtils.checksumCRC32 and FileUtils.checksum are not thread safe. Fix error about usage of DirectBuffer in JRE 16/17 #205. Prevent infinite loop with AbstractCharacterFilterReader if EOF is filtered out #226. Check for long streams in IOUtils.toByteArray #175. Add FileSystemProviders class. Let org.apache.commons.io.filefilter classes work with java.nio.file.Files.walk* APIs. Let org.apache.commons.io.filefilter classes work with java.nio.file.Files#newDirectoryStream(Path, DirectoryStream.Filter). Add and adapt ReadAheadInputStream and BufferedFileChannelInputStream from Apache Spark. Add PathUtils.createParentDirectories(Path, FileAttribute...). Add factory methods to CloseShieldInputStream, CloseShieldReader, CloseShieldOutputStream, CloseShieldWriter, #173. Add QueueInputStream and QueueOutputStream as simpler alternatives to PipedInputStream and PipedOutputStream #171. Add StandardLineSeparator. Replace magic numbers with constants with the new IOUtils.CR and LF. Add FileSystem#supportsDriveLetter(). Add FileUtils.delete(File). Add FileUtils.moveFile(File, File, CopyOption...) #185. Add FileUtils.isEmptyDirectory(File). Add FileUtils.lastModified[Unchecked](File) to workaround https://bugs.openjdk.java.net/browse/JDK-8177809. Add null safe variants of isDirectory and isRegularFile. Add and use IOExceptionList(String, List). Add and use ObservableInputStream.ObservableInputStream(InputStream, Observer...). Make ObservableInputStream.getObservers() public. Add TimestampedObserver. Add and use IOUtils.byteArray(*). Make public and reuse IOUtils.EMPTY_BYTE_ARRAY. Add IOUtils.copy(URL, File). Add copy(URL, OutputStream). Add DeferredFileOutputStream.toInputStream() #206. Add CharacterSetFilterReader.CharacterSetFilterReader(Reader, Integer...). Add AbstractCharacterFilterReader(Reader, IntPredicate), #227. Add CharacterFilterReader(Reader, IntPredicate), #227. Add CharacterFilterReaderIntPredicateTest, #227. Add IOConsumer.noop(). Add constructor ThresholdingOutputStream(int, IOConsumer, IOFunction) and make the class concrete. Add constructor accepting collection of file alteration observers #236. Update junit-jupiter from 5.6.2 to 5.7.0 #153. Update mockito-core from 3.5.9 to 3.10.0, #152, #155, #157, #166, #167, #169, #182. Bump mockito-inline from 3.7.0 to 3.10.0 #188, #207, #230. Update commons.jacoco.version 0.8.5 to 0.8.7, fixes Java 15 builds and up. Update spotbugs from 4.1.2 to 4.2.2, 4.2.3, #158, #164, #165, #180, #199, #213, #224. Bump spotbugs-maven-plugin from 4.0.4 to 4.2.3, #161, #172, #223. Update org.junit-pioneer:junit-pioneer 0.9.0 -> 1.4,1, #159, #162, #170, #189, #191, #210, #229. Update actions/checkout from v2.3.2 to v2.3.4, #156, #168. Bump actions/setup-java from v1.4.2 to v2 #160. Update maven-surefire-plugin from 2.22.2 to 3.0.0-M5. Minor improvements, #176, 177, #190. Update commons.japicmp.version 0.14.4 -> 0.15.3. Tiny performance improvement in FileUtils#moveDirectoryToDirectory() #174. Bump checkstyle from 8.38 to 8.42 #689, #209, #225. Bump maven-checkstyle-plugin from 3.1.1 to 3.1.2 #198. Bump jimfs from 1.1 to 1.2 #183. Improve performance of IOUtils.contentEquals(InputStream, InputStream). Improve performance of IOUtils.contentEquals(Reader, Reader). Bump actions/cache from v2 to v2.1.5 #202, #228. Bump junit-bom from 5.7.0 to 5.7.2 #200, #232. Update from Apache Commons Lang 3.11 to 3.12.0. Minor improvements #233. Simplify Assertions in tests #234. Add org.apache.commons.io.input.CircularInputStream. Add org.apache.commons.io.file.PathUtils.cleanDirectory(Path, FileVisitOption...). Add org.apache.commons.io.file.PathUtils.deleteDirectory(Path, FileVisitOption...). Add NullAppendable. CharSequenceReader.skip should return 0 instead of EOF on stream end #123. Implement CharSequenceReader.ready() #122. Fix code smells; fix typos #115. Add caching for required charsets #120. Make some simplifications #121. InfiniteCircularInputStream is not infinite if its input buffer contains -1. InfiniteCircularInputStream throws a divide-by-zero exception when reading if its input buffer is size 0. FileSystem.getCurrent() does not return the correct enum. input.AbstractCharacterFilterReader passes count of chars read #132. Add PathUtils.getAclEntryList(Path). Null-guard IOUtils.close(Closeable, IOConsumer). Add ReversedLinesFileReader.readLines(int). Add ReversedLinesFileReader.toString(int). Add PathUtils.delete(Path, DeleteOption...). Add PathUtils.deleteDirectory(Path, DeleteOption...). Add PathUtils.deleteFile(Path, DeleteOption...). Add PathUtils.setReadOnly(Path, boolean, LinkOption...). Add CleaningPathVisitor.CleaningPathVisitor(PathCounters, DeleteOption[], String...). Add DeletingPathVisitor.DeletingPathVisitor(PathCounters, DeleteOption[], String...). CircularBufferInputStream.read() fails to convert byte to unsigned int Fix SpotBugs issues in org.apache.commons.io.FileUtils. Add RandomAccessFileInputStream. IOUtils.close(Closeable) should allow a list of closeables. Copying a File sets last modified date to 01 January 1970. Add IOUtils.consume(InputStream). Add isFileNewer() and isFileOlder() methods that support the Java 8 Date/Time API. #124. Prevent NullPointerException in ReversedLinesFileReader constructors #117. Add a MarkShieldInputStream #119. Deprecate IOUtils.LINE_SEPARATOR in favor of Java 7's System.lineSeparator(). Replace FindBugs with SpotBugs. maven-checkstyle-plugin 3.1.0 -> 3.1.1. Update tests from org.apache.commons:commons-lang3 3.10 to 3.11. Update commons-parent from 50 to 51 #129. Update actions/checkout from v1 to v2.3.1 #126. Update junit-pioneer from 0.6.0 to 0.9.0, #127, #135, #138. Update mockito-core from 3.3.3 to 3.5.9 #128, #133, #145, #149, #151. Update spotbugs from 4.0.6 to 4.1.1 #134. Update actions/checkout from v2.3.1 to v2.3.2 #140. Update actions/setup-java from v1.4.0 to v1.4.2 #141, #148. Update com.github.siom79.japicmp:japicmp-maven-plugin 0.14.3 -> 0.14.4. Some tests fail if the base path contains a space. Adding the CircularBufferInputStream, and the PeekableInputStream. Make methods in ObservableInputStream.Obsever public. Thread bug in FileAlterationMonitor#stop(int). Add org.apache.commons.io.FilenameUtils.isIllegalWindowsFileName(char). Perform locale independent upper case conversions. Missing Javadoc in FilenameUtils causing Travis-CI build to fail. Remove redundant isDirectory() check in org.apache.commons.io.FileUtils.listFilesAndDirs(File, IOFileFilter, IOFileFilter). Refactor duplicate code in org.apache.commons.io.FileUtils. Add readers to filter out given characters: CharacterSetFilterReader and CharacterFilterReader. FilenameUtils.normalize now verifies hostname syntax in UNC path. Update org.apache.commons.io.FilenameUtils.isExtension(String, String[]) to use var args. FileUtils.copyToFile(InputStream source, File destination) should not close input stream. Add IOUtils copy methods with java.lang.Appendable as the target. FileUtils.doCopyFile(File, File, boolean) can throw ClosedByInterruptException. Add class CanExecuteFileFilter. Make array declaration in ThresholdingOutputStream consistent with other array declarations in the library #77. Support java.nio.Path and non-default file systems for ReversedLinesFileReader (#62). Add a convenience NullPrintStream. Update from Java 7 to Java 8. Remove throws IOException in method isSymlink() #80. Add class TeeReader. Add classes ClosedReader and CloseShieldReader. #84. Add classes TaggedWriter, ClosedWriter and BrokenWriter. #86. Add classes TeeWriter, FilterCollectionWriter, ProxyCollectionWriter, IOExceptionList, IOIndexedException. Add class AppendableWriter. #87. Add class CloseShieldWriter. #83. Add classes Added TaggedReader, ClosedReader and BrokenReader. #85. Support sub sequences in CharSequenceReader. #91. Corrected misleading exception message for FileUtils.copyDirectoryToDirectory. A mistake in the FilenameUtils.concat()'s Javadoc about an absolute path. Migration to JUnit Jupiter #97. Deprecate org.apache.commons.io.output.NullOutputStream.NullOutputStream() in favor of org.apache.commons.io.output.NullOutputStream.NULL_OUTPUT_STREAM. Add a CountingFileVisitor (as the basis for a forthcoming DeletingFileVisitor). Add PathUtils for operations on NIO Path. Add DeletingFileVisitor. FileUtils#forceDelete should use Files#delete rather than File#delete so exception messages includes reason for failure. Make getCause synchronized and use a Deque instead of a Stack #64. Add org.apache.commons.io.IOUtils.close(Closeable). Add and reuse org.apache.commons.io.IOUtils.closeQuitely(Closeable, Consumer<IOException>). Add and reuse org.apache.commons.io.IOUtils.close(Closeable, IOConsumer<IOException>). NPE in org.apache.commons.io.IOUtils.contentEquals(InputStream, InputStream) when only one input is null. NPE in org.apache.commons.io.IOUtils.contentEquals(Reader, Reader) when only one input is null. NPE in org.apache.commons.io.IOUtils.contentEqualsIgnoreEOL(Reader, Reader) when only one input is null. NPE in org.apache.commons.io.FileUtils.contentEqualsIgnoreEOL(File, File) when only one input is null. Add org.apache.commons.io.file.PathUtils.fileContentEquals(Path, Path, OpenOption...). Add a SequenceReader similar to java.io.SequenceInputStream. Implement directory content equality. 100#. Update tests from Apache Commons Lang 3.9 to 3.10. Update tests org.junit-pioneer:junit-pioneer 0.3.0 -> 0.6.0. Update tests org.junit.jupiter:junit-jupiter 5.5.2 -> 5.6.2. Update tests org.mockito:mockito-core 3.0.0 -> 3.3.3. Refactor ByteArrayOutputStream into synchronized and unsynchronized versions #108. Refactor ByteArrayOutputStream into synchronized and unsynchronized versions #108. org.apache.commons.io.FileUtils.copyURLToFile(*) open but do not close streams. Normalize internal buffers to 8192 bytes. Ensure that passing a null InputStream results in NPE with tests #112. commons.jacoco.version 0.8.4 -> 0.8.5. com.github.siom79.japicmp:japicmp-maven-plugin 0.14.1 -> 0.14.3. Add functional interfaces IOFunction and IOSupplier #110. Support sub sequences in CharSequenceReader #91. Remove deprecated sudo setting. #113. Make code style of hasBOM() consistent with getBOMCharsetName() ClosedOutputStream#flush should throw Add Automatic-Module-Name MANIFEST entry for Java 9 compatibility Documentation issue, fix 404 Javadoc issues in the description page FileUtils#readFileToByteArray: optimize reading of files with known size Throw a IllegalArgumentException instead of NullPointerException in FileSystemUtils.freeSpaceWindows(). Add convenience methods for copyToDirectory Javadoc contradictory for FileFilterUtils.ageFileFilter(cutoff) and the filter it constructs: AgeFileFilter(cutoff) FileUtilTestCase.testForceDeleteDir() should not delete testDirectory parent fix Tailer.run race condition runaway logging getPrefixLength return -1 if unix file contains colon FileUtilsTestCase#testContentEqualsIgnoreEOL fails on Windows .gitattributes not correctly applied Allow Specifying Initial Buffer Size of DeferredFileOutputStream. ThresholdingOutputStream.thresholdReached() results in FileNotFoundException. After a few unit tests, a few newly created directories not cleaned completely. Exceptions are suppressed incorrectly when copying files. Update platform requirement to Java 7. BOMInputStream shouldn't sort array of BOMs in-place. Deprecate methods FileSystemUtils.freeSpaceKb(). Make LineIterator implement Closeable to support try-with-resources statements. Deprecated of all IOUtils.closeQuietly() methods and use try-with-resources internally. Add infinite circular input stream Add a ByteOrderParser class. Add ObservableInputStream Add MessageDigestCalculatingInputStream Add convenience methods for reading class path resources. Remove org.apache.commons.io.Java7Support Implement special case handling for NTFS ADS names: FilenameUtils.getExtension(String), and FilenameUtils.indexOfExtension(String) are now throwing an IllegalArgumentException, if the file name in question appears to identify an alternate data stream (Windows only). Typo: In an IOUtils.java comment it says "focussed" instead of "focused". Converted all test cases to JUnit 4 Add ValidatingObjectInputStream for controlled deserialization adds an endOfFileReached method to the TailerListener FilenameUtils should handle embedded null bytes Changed/Corrected algorithm for waitFor Support for additional encodings in ReversedLinesFileReader BOMInputStream.skip returns wrong count if stream contains no BOM Setter method for threshold on ThresholdingOutputStream FileUtils.waitFor(...) swallows thread interrupted status Support for symlinks with missing target. Added support for JDK7 symlink features when present Added testcase to show this was fixed with IO-423 Correct exception message in FileUtils.getFile(File, String...) Introduce new class AppendableOutputStream Update to JUnit 4.12 IOExceptionWithCause no longer needed Add WindowsLineEndingInputStream and UnixLineEndingInputStream. Add a BoundedReader, a wrapper that can be used to constrain access to an underlying stream when used with mark/reset - to avoid overflowing the mark limit of the underlying buffer. Regression in FileUtils.readFileToString from 2.0.1 ant test fails - resources missing from test classpath Document that FileUtils.deleteDirectory, directoryContains and cleanDirectory may throw an IllegalArgumentException in case the passed directory does not exist or is not a directory. Add API IOUtils.closeQuietly(Closeable...) Javadoc fixes, mostly to appease 1.8.0 Deprecate Charsets Charset constants in favor of Java 7's java.nio.charset.StandardCharsets Readfully() That Returns A Byte Array Overload IOUtils buffer methods to accept buffer size FileUtils.sizeOfDirectory can throw IllegalArgumentException FileUtils.sizeOfDirectoryAsBigInteger can overflow. Ensure that recursive calls all use BigInteger Chunked IO for large arrays. Added writeChunked(byte[], OutputStream) and writeChunked(char[] Writer) Added ChunkedOutputStream, ChunkedWriter FileUtils.doCopyFile can potentially loop for ever Exit loop if no data to copy FileUtils.doCopyFile caches the file size; needs to be documented Added Javadoc; show file lengths in exception message Convert IOCase to a Java 1.5+ Enumeration [N.B. this is binary compatible] Add Methods for Buffering Streams/Writers To IOUtils Added overloaded buffer() methods - see also IO-330 IOUtils#toBufferedOutputStream/toBufferedWriter to conditionally wrap the output Added overloaded buffer() methods - see also IO-233 Add FileUtils.copyInputStreamToFile API with option to leave the source open. See copyInputStreamToFile(final InputStream source, final File destination, boolean closeSource) FileUtils.copyInputStreamToFile should document it closes the input source Tailer erroneously considers file as new. Fix to use file.lastModified() rather than System.currentTimeMillis() CharSequenceInputStream#reset() behaves incorrectly in case when buffer size is not dividable by data size. Fix code so skip relates to the encoded bytes; reset now re-encodes the data up to the point of the mark CharSequenceInputStream - add tests for available() Fix code so it really does reflect a minimum available. getPrefixLength returns null if filename has leading slashes Javadoc: add examples to show correct behavior; add unit tests FileUtils.listFilesAndDirs includes original dir in results even when it doesn't match filter Javadoc: clarify that original dir is included in the results Add ByteArrayOutputStream.toInputStream() ClassLoaderObjectInputStream does not handle primitive typed members A constant for holding the BOM character (U+FEFF) Deprecate all methods that use the default encoding When a file is rotated, finish reading previous file prior to starting new one Commons IO Tailer does not respect UTF-8 Charset. What should happen in FileUtils.sizeOf[Directory] when an overflow takes place? Added Javadoc. FileUtils.moveDirectory can produce misleading error message on failiure FilenameUtils.splitOnTokens(String text) check for '**' could be simplified WildcardFileFilter ctors should not use null to mean IOCase.SENSITIVE when delegating to other ctors IOUtils.contentEquals* methods returns false if input1 == input2, should return true. Add API FileUtils.forceMkdirsParent(). Add API Charsets.requiredCharsets(). Add IOUtils.skip and skipFully(ReadableByteChannel, long). Add IOUtils.read and readFully(ReadableByteChannel, ByteBuffer buffer). [Tailer] InterruptedException while the thread is sleeping is silently ignored Add API IOUtils.copy(InputStream, OutputStream, int) Add API with array offset and length argument to FileUtils.writeByteArrayToFile. Spelling fixes. Missing information in IllegalArgumentException thrown by org.apache.commons.io.FileUtils#validateListFilesParameters. Supply a hook method allowing Tailer actively determining stop condition. Improper Javadoc comment for FilenameUtils.indexOfExtension. Make IOUtils.EOF public and reuse it in various classes. org.apache.commons.io.comparator Javadoc is inconsistent with real code. Yottabyte (YB) incorrectly defined in FileUtils. Tailer locks file from deletion/rename on Windows. Tailer erroneously considers file as new. Tailer#readLines - incorrect CR handling. FileUtils.toURLs throws NPE for null parameter; document the behavior. Export OSGi packages at version 1.x in addition to 2.x. Add XmlStreamReader support for UTF-32. BOMInputStream wrongly detects UTF-32LE_BOM files as UTF-16LE_BOM files in method getBOM(). Improve tailer's reading performance. Improve Tailer performance with buffered reads (see IO-332). FileUtils.writeLines uses unbuffered IO. Add byteCountToDisplaySize(BigInteger). Add new FileUtils.sizeOf[Directory] APIs to return BigInteger. Add IOUtils.toByteArray methods to work with URL and URI. Add missing Charset sister APIs to method that take a String charset name. FileUtils.sizeOfDirectory follows symbolic links. Add and use class Charsets. ByteOrderMark UTF_32LE is incorrect. Add Charset sister APIs to method that take a String charset name. Add IOUTils.toBufferedReader(Reader) Allow applications to provide buffer (or size) for copyLarge methods. IOUtils.read(InputStream/Reader) ignores the offset parameter CharSequenceInputStream(CharSequence s, Charset charset, int bufferSize) ignores bufferSize New copyLarge() method in IOUtils that takes additional offset, length arguments FileUtils.moveDirectoryToDirectory removes source directory if destination is a sub-directory ReaderInputStream#read(byte[] b, int off, int len) should check for valid parameters Use terabyte (TB), petabyte (PB) and exabyte (EB) in FileUtils.byteCountToDisplaySize(long size) ReaderInputStream#read(byte[] b, int off, int len) should always return 0 for length == 0 FileUtils.listFiles() doesn't return directories "FileUtils#deleteDirectoryOnExit(File)" does not work BoundedInputStream.read() treats max differently from BoundedInputStream.read(byte[]...) CharSequenceInputStream to efficiently stream content of a CharSequence ReaderInputStream optimization: more efficient reading of small chunks of data Various methods of class 'org.apache.commons.io.FileUtils' incorrectly suppress 'java.io.IOException' The second constructor of Tailer class does not pass 'delay' to the third one TeeOutputStream does not call branch.close() when main.close() throws an exception ArrayIndexOutOfBoundsException in BOMInputStream when reading a file without BOM multiple times Add IOUtils.closeQuietly(Selector) necessary IOUtils.closeQuietly() should take a ServerSocket as a parameter Add read/readFully methods to IOUtils Supply a ReversedLinesFileReader Add new function FileUtils.directoryContains. FileUtils.contentEquals and IOUtils.contentEquals - Add option to ignore "line endings" Added contentEqualsIgnoreEOL methods to both classes Use standard Maven directory layout Add IOUtils API toString for URL and URI to get contents Add API FileUtils.copyFile(File input, OutputStream output) Dubious use of mkdirs() return code ReaderInputStream enters infinite loop when it encounters an unmappable character FileUtils.moveFile() Javadoc should specify FileExistsException thrown FileAlterationObserver has no getter for FileFilter Add FileUtils.getFile API with varargs parameter ClassLoaderObjectInputStream does not handle Proxy classes FileAlterationMonitor.stop(boolean allowIntervalToFinish) Add new APPEND parameter for writing string into files Tailer returning partial lines when reaching EOF before EOL FileUtils.copyFile() throws IOException when copying large files to a shared directory (on Windows) FileSystemUtils.freeSpaceKb throws exception for Windows volumes with no visible files. Improve coverage by also looking for hidden files. Add new read method "toByteArray" to handle InputStream with known size. TODO: Convert RELEASE-NOTES.txt from 2.0.1? TODO: Convert RELEASE-NOTES.txt from 2.0? TODO: Convert RELEASE-NOTES.txt from 1.4? Some tests, which are implicitly assuming a Unix-like file system, are now skipped on Windows. Created the FileCleaningTracker, basically a non-static version of the FileCleaner, which can be controlled by the user. EndianUtils - both readSwappedUnsignedInteger(...) methods could return negative numbers due to int/long casting. commons-io-2.11.0-src/src/changes/release-notes.vm0100644 0000000 0000000 00000200276 13612062727 022325 0ustar00rootroot0000000 0000000 ## Licensed to the Apache Software Foundation (ASF) under one ## or more contributor license agreements. See the NOTICE file ## distributed with this work for additional information ## regarding copyright ownership. The ASF licenses this file ## to you under the Apache License, Version 2.0 (the ## "License"); you may not use this file except in compliance ## with the License. You may obtain a copy of the License at ## ## http://www.apache.org/licenses/LICENSE-2.0 ## ## Unless required by applicable law or agreed to in writing, ## software distributed under the License is distributed on an ## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY ## KIND, either express or implied. See the License for the ## specific language governing permissions and limitations ## under the License. Apache Commons IO Version ${version} Release Notes INTRODUCTION: Commons IO is a package of Java utility classes like java.io. Classes in this package are considered to be so standard and of such high reuse as to justify existence in java.io. $introduction.replaceAll("(? 3.1.1. Thanks to Gary Gregory. o Update tests from org.apache.commons:commons-lang3 3.10 to 3.11. Thanks to Gary Gregory. o Update commons-parent from 50 to 51 #129. Thanks to Gary Gregory. o Update actions/checkout from v1 to v2.3.1 #126. Thanks to Gary Gregory. o Update junit-pioneer from 0.6.0 to 0.8.0, #127, #135. Thanks to Gary Gregory. o Update mockito-core from 3.3.3 to 3.5.9 #128, #133, #145, #149, #151. Thanks to Gary Gregory. o Update spotbugs from 4.0.6 to 4.1.1 #134. Thanks to Dependabot. o Update junit-pioneer from 0.8.0 to 0.9.0 #138. Thanks to Dependabot. o Update actions/checkout from v2.3.1 to v2.3.2 #140. Thanks to Dependabot. o Update actions/setup-java from v1.4.0 to v1.4.2 #141, #148. Thanks to Dependabot. Compatibility with 2.7: Binary compatible: Yes. Source compatible: Yes. Semantic compatible: Yes. Commons IO 2.7 requires Java 8. Commons IO 2.6 requires Java 7. Commons IO 2.5 requires Java 6. Commons IO 2.4 requires Java 6. Commons IO 2.3 requires Java 6. Commons IO 2.2 requires Java 5. Commons IO 1.4 requires Java 1.3. Historical list of changes: https://commons.apache.org/proper/commons-io/changes-report.html For complete information on Apache Commons IO, including instructions on how to submit bug reports, patches, or suggestions for improvement, see the Apache Apache Commons IO website: https://commons.apache.org/proper/commons-io/ Download page: https://commons.apache.org/proper/commons-io/download_io.cgi Have fun! -Apache Commons Team ============================================================================== Apache Commons IO Version 2.7 Release Notes INTRODUCTION: Commons IO is a package of Java utility classes like java.io. Classes in this package are considered to be so standard and of such high reuse as to justify existence in java.io. The Apache Commons IO library contains utility classes, stream implementations, file filters, file comparators, endian transformation classes, and much more. ============================================================================== Apache Commons IO Version 2.7 ============================================================================== Java 8 required. Changes in this version include: New features: o Adding the CircularBufferInputStream, and the PeekableInputStream. o IO-553: Add org.apache.commons.io.FilenameUtils.isIllegalWindowsFileName(char). o IO-577: Add readers to filter out given characters: CharacterSetFilterReader and CharacterFilterReader. Thanks to Gary Gregory. o IO-594: Add IOUtils copy methods with java.lang.Appendable as the target. Thanks to Gary Gregory. o IO-605: Add class CanExecuteFileFilter. Thanks to Gary Gregory. o IO-578: Support java.nio.Path and non-default file systems for ReversedLinesFileReader (#62). Thanks to Mark Chesney. o IO-608: Add a convenience NullPrintStream. Thanks to Gary Gregory. o IO-612: Add class TeeReader. Thanks to Rob Spoor, Gary Gregory. o IO-613: Add classes ClosedReader and CloseShieldReader. #84. Thanks to Rob Spoor, Gary Gregory. o IO-614: Add classes TaggedWriter, ClosedWriter and BrokenWriter. #86. Thanks to Rob Spoor. o IO-615: Add classes TeeWriter, FilterCollectionWriter, ProxyCollectionWriter, IOExceptionList, IOIndexedException. Thanks to Gary Gregory, Rob Spoor. o IO-616: Add class AppendableWriter. #87. Thanks to Rob Spoor. o IO-617: Add class CloseShieldWriter. #83. Thanks to Rob Spoor, Gary Gregory. o IO-618: Add classes Added TaggedReader, ClosedReader and BrokenReader. #85. Thanks to Rob Spoor. o IO-619: Support sub sequences in CharSequenceReader. #91. Thanks to Rob Spoor. o IO-631: Add a CountingFileVisitor (as the basis for a forthcoming DeletingFileVisitor). Thanks to Gary Gregory. o IO-632: Add PathUtils for operations on NIO Path. Thanks to Gary Gregory. o IO-633: Add DeletingFileVisitor. Thanks to Gary Gregory. o IO-635: Add org.apache.commons.io.IOUtils.close(Closeable). Thanks to Gary Gregory. o IO-636: Add and reuse org.apache.commons.io.IOUtils.closeQuitely(Closeable, Consumer). Add and reuse org.apache.commons.io.IOUtils.close(Closeable, IOConsumer). Thanks to Gary Gregory. o IO-645: Add org.apache.commons.io.file.PathUtils.fileContentEquals(Path, Path, OpenOption...). Thanks to Gary Gregory. o IO-458: Add a SequenceReader similar to java.io.SequenceInputStream. Thanks to Gary Gregory, Joshua Gitlin. o IO-648: Implement directory content equality. 100#. Thanks to Gary Gregory. o IO-648: Refactor ByteArrayOutputStream into synchronized and unsynchronized versions #108. Thanks to Adam Retter, Alex Herbert, Gary Gregory. o IO-662: Refactor ByteArrayOutputStream into synchronized and unsynchronized versions #108. Thanks to Adam Retter, Gary Gregory. Fixed Bugs: o IO-589: Some tests fail if the base path contains a space. o IO-582: Make methods in ObservableInputStream.Obsever public. Thanks to Bruno Palos. o IO-535: Thread bug in FileAlterationMonitor.stop(int). Thanks to Svetlin Zarev, Anthony Raymond. o IO-557: Perform locale independent upper case conversions. Thanks to luccioman. o IO-570: Missing Javadoc in FilenameUtils causing Travis-CI build to fail. Thanks to Pranet Verma. o IO-571: Remove redundant isDirectory() check in org.apache.commons.io.FileUtils.listFilesAndDirs(File, IOFileFilter, IOFileFilter). Thanks to pranet. o IO-559: FilenameUtils.normalize now verifies hostname syntax in UNC path. o IO-554: FileUtils.copyToFile(InputStream source, File destination) should not close input stream. Thanks to Michele Mariotti. o IO-604: FileUtils.doCopyFile(File, File, boolean) can throw ClosedByInterruptException. Thanks to Gary Gregory. o IO-625: Corrected misleading exception message for FileUtils.copyDirectoryToDirectory. Thanks to Mikko Maunu. o IO-626: A mistake in the FilenameUtils.concat()'s Javadoc about an absolute path. Thanks to Yuji Konishi. o IO-640: NPE in org.apache.commons.io.IOUtils.contentEquals(InputStream, InputStream) when only one input is null. Thanks to Gary Gregory. o IO-641: NPE in org.apache.commons.io.IOUtils.contentEquals(Reader, Reader) when only one input is null. Thanks to Gary Gregory. o IO-643: NPE in org.apache.commons.io.IOUtils.contentEqualsIgnoreEOL(Reader, Reader) when only one input is null. Thanks to Gary Gregory. o IO-644: NPE in org.apache.commons.io.FileUtils.contentEqualsIgnoreEOL(File, File) when only one input is null. Thanks to Gary Gregory. o IO-664: org.apache.commons.io.FileUtils.copyURLToFile(*) open but do not close streams. Thanks to Gary Gregory. Changes: o IO-572: Refactor duplicate code in org.apache.commons.io.FileUtils. Thanks to Pranet Verma. o IO-580: Update org.apache.commons.io.FilenameUtils.isExtension(String, String[]) to use var args. o IO-701: Make array declaration in ThresholdingOutputStream consistent with other array declarations in the library #77. Thanks to Raymond Tan. o IO-607: Update from Java 7 to Java 8. Thanks to Gary Gregory. o IO-610: Remove throws IOException in method isSymlink() #80. Thanks to Sebastian. o IO-628: Migration to JUnit Jupiter #97. Thanks to Allon Mureinik. o IO-630: Deprecate org.apache.commons.io.output.NullOutputStream.NullOutputStream() in favor of org.apache.commons.io.output.NullOutputStream.NULL_OUTPUT_STREAM. Thanks to Gary Gregory. o IO-629: FileUtils#forceDelete should use Files#delete rather than File#delete so exception messages includes reason for failure. Thanks to Ian Springer, Ian Springer, Gary Gregory. o IO-634: Make getCause synchronized and use a Deque instead of a Stack #64. Thanks to Vclav Haisman, Bruno P. Kinoshita, Gary Gregory. o Update tests from Apache Commons Lang 3.9 to 3.10. Thanks to Gary Gregory. o Update tests org.junit-pioneer:junit-pioneer 0.3.0 -> 0.6.0. Thanks to Gary Gregory. o Update tests org.junit.jupiter:junit-jupiter 5.5.2 -> 5.6.2. Thanks to Gary Gregory. o Update tests org.mockito:mockito-core 3.0.0 -> 3.3.3. Thanks to Gary Gregory. o IO-666: Normalize internal buffers to 8192 bytes. Thanks to Gary Gregory. o IO-665: Ensure that passing a null InputStream results in NPE with tests #112. Thanks to Otto Fowler, Gary Gregory. o commons.jacoco.version 0.8.4 -> 0.8.5. Thanks to Gary Gregory. o com.github.siom79.japicmp:japicmp-maven-plugin 0.14.1 -> 0.14.3. Thanks to Gary Gregory. o IO-667: Add functional interfaces IOFunction and IOSupplier #110. Thanks to Adam Retter, Gary Gregory. o Support sub sequences in CharSequenceReader #91. Thanks to Rob Spoor, Gary Gregory. o Remove deprecated sudo setting. #113. Thanks to dengliming. Compatibility with 2.6: Binary compatible: Yes. Source compatible: Yes. Semantic compatible: Yes. Commons IO 2.7 requires Java 8. Commons IO 2.6 requires Java 7. Commons IO 2.5 requires Java 6. Commons IO 2.4 requires Java 6. Commons IO 2.3 requires Java 6. Commons IO 2.2 requires Java 5. Commons IO 1.4 requires Java 1.3. Historical list of changes: https://commons.apache.org/proper/commons-io/changes-report.html For complete information on Apache Commons IO, including instructions on how to submit bug reports, patches, or suggestions for improvement, see the Apache Apache Commons IO website: https://commons.apache.org/proper/commons-io/ Download page: https://commons.apache.org/proper/commons-io/download_io.cgi Have fun! -Apache Commons Team ============================================================================== Apache Commons IO Version 2.6 ============================================================================== INTRODUCTION: Apache Commons IO is a package of Java utility classes like java.io. Classes in this package are considered to be so standard and of such high reuse as to justify existence in java.io. The Apache Commons IO library contains utility classes, stream implementations, file filters, file comparators, endian transformation classes, and much more. Apache Commons IO 2.6 requires at least Java 7 to build and run. DEPRECATIONS ============ All closeQuietly overloads in org.apache.commons.io.IOUtils have been deprecated. Use the try-with-resources statement or handle suppressed exceptions manually. The class org.apache.commons.io.FileSystemUtils has been deprecated. Use equivalent methods in java.nio.file.FileStore instead, e.g. Files.getFileStore(Paths.get("/home")).getUsableSpace() or iterate over FileSystems.getDefault().getFileStores(). COMPATIBILITY WITH JAVA 9 ================== The MANIFEST.MF now contains an additional entry: Automatic-Module-Name: org.apache.commons.io This should make it possible to use Commons IO 2.6 as a module in the Java 9 module system. For more information see the corresponding issue: https://issues.apache.org/jira/browse/IO-551 Building Commons IO 2.6 should work out of the box with the latest Java 9 release. Please report any Java 9 related issues at: https://issues.apache.org/jira/browse/IO NEW FEATURES ============ o IO-551: Add Automatic-Module-Name MANIFEST entry for Java 9 compatibility. o IO-367: Add convenience methods for copyToDirectory. Thanks to James Sawle. o IO-493: Add infinite circular input stream. Thanks to Piotr Turski. o IO-507: Add a ByteOrderUtils class. o IO-518: Add ObservableInputStream. o IO-519: Add MessageDigestCalculatingInputStream. o IO-513: Add convenience methods for reading class path resources. Thanks to Behrang Saeedzadeh. FIXED BUGS ========== o IO-546: ClosedOutputStream#flush should throw. Thanks to Tomas Celaya. o IO-550: Documentation issue, fix 404 Javadoc issues in the description page. Thanks to Jimi Adrian. o IO-442: Javadoc contradictory for FileFilterUtils.ageFileFilter(cutoff) and the filter it constructs: AgeFileFilter(cutoff). Thanks to Simon Robinson. o IO-534: FileUtilTestCase.testForceDeleteDir() should not delete testDirectory parent. o IO-528: Fix Tailer.run race condition runaway logging. Thanks to Dave Moten. o IO-483: getPrefixLength return -1 if unix file contains colon. Thanks to Marko Vasic. o IO-520: FileUtilsTestCase#testContentEqualsIgnoreEOL fails on Windows. o IO-516: .gitattributes not correctly applied. Thanks to Jason Pyeron. o IO-515: Allow Specifying Initial Buffer Size of DeferredFileOutputStream. Thanks to Brett Lounsbury, Gary Gregory. o IO-512: ThresholdingOutputStream.thresholdReached() results in FileNotFoundException. Thanks to Ralf Hauser. o IO-511: After a few unit tests, a few newly created directories not cleaned completely. Thanks to Ahmet Celik. o IO-502: Exceptions are suppressed incorrectly when copying files. Thanks to Christian Schulte. o IO-503: Update platform requirement to Java 7. o IO-537: BOMInputStream shouldn't sort array of BOMs in-place. Thanks to Borys Zibrov. CHANGES ======= o IO-553: Make code style of hasBOM() consistent with getBOMCharsetName(). Thanks to Michael Ernst. o IO-542: FileUtils#readFileToByteArray: optimize reading of files with known size. Thanks to Ilmars Poikans. o IO-547: Throw a IllegalArgumentException instead of NullPointerException in FileSystemUtils.freeSpaceWindows(). Thanks to Nikhil Shinde, Michael Ernst, Gary Greory. o IO-506: Deprecate methods FileSystemUtils.freeSpaceKb(). Thanks to Christian Schulte. o IO-505: Make LineIterator implement Closeable to support try-with-resources statements. Thanks to Christian Schulte. o IO-504: Deprecated of all IOUtils.closeQuietly() methods and use try-with-resources internally. Thanks to Christian Schulte. REMOVED ======= o IO-514: Remove org.apache.commons.io.Java7Support. COMPATIBILITY WITH OLDER VERSIONS ================================= Compatibility with 2.5: Binary compatible: Yes. Source compatible: Yes. Semantic compatible: Yes. Compatibility with 2.6 and 1.4: Binary compatible: Yes. Source compatible: No, see the rare case in https://issues.apache.org/jira/browse/IO-318. Semantic compatible: No, see the rare case in https://issues.apache.org/jira/browse/IO-318. Commons IO 2.6 requires Java 7 or later. Commons IO 2.5 requires Java 6 or later. Commons IO 2.4 requires Java 6 or later. Commons IO 2.3 requires Java 6 or later. Commons IO 2.2 requires Java 5 or later. Commons IO 1.4 requires Java 1.3 or later. ============================================================================== Apache Commons IO Version 2.5 ============================================================================== New features and bug fixes. Changes in this version include: New features: o IO-487: Add ValidatingObjectInputStream for controlled deserialization o IO-471: Support for additional encodings in ReversedLinesFileReader Thanks to Leandro Reis. o IO-425: Setter method for threshold on ThresholdingOutputStream Thanks to Craig Swank. o IO-406: Introduce new class AppendableOutputStream Thanks to Niall Pemberton. o IO-459: Add WindowsLineEndingInputStream and UnixLineEndingInputStream. Thanks to Kristian Rosenvold. o IO-457: Add a BoundedReader, a wrapper that can be used to constrain access to an underlying stream when used with mark/reset - to avoid overflowing the mark limit of the underlying buffer. Thanks to Kristian Rosenvold. o IO-426: Add API IOUtils.closeQuietly(Closeable...) o IO-410: Readfully() That Returns A Byte Array Thanks to Beluga Behr. o IO-395: Overload IOUtils buffer methods to accept buffer size Thanks to Beluga Behr. o IO-382: Chunked IO for large arrays. Added writeChunked(byte[], OutputStream) and writeChunked(char[] Writer) Added ChunkedOutputStream, ChunkedWriter o IO-233: Add Methods for Buffering Streams/Writers To IOUtils Added overloaded buffer() methods - see also IO-330 o IO-330: IOUtils#toBufferedOutputStream/toBufferedWriter to conditionally wrap the output Added overloaded buffer() methods - see also IO-233 o IO-381: Add FileUtils.copyInputStreamToFile API with option to leave the source open. See copyInputStreamToFile(final InputStream source, final File destination, boolean closeSource) o IO-379: CharSequenceInputStream - add tests for available() Fix code so it really does reflect a minimum available. o IO-346: Add ByteArrayOutputStream.toInputStream() o IO-341: A constant for holding the BOM character (U+FEFF) o IO-361: Add API FileUtils.forceMkdirsParent(). o IO-360: Add API Charsets.requiredCharsets(). o IO-359: Add IOUtils.skip and skipFully(ReadableByteChannel, long). Thanks to yukoba. o IO-358: Add IOUtils.read and readFully(ReadableByteChannel, ByteBuffer buffer). Thanks to yukoba. o IO-353: Add API IOUtils.copy(InputStream, OutputStream, int) Thanks to ggregory. o IO-349: Add API with array offset and length argument to FileUtils.writeByteArrayToFile. Thanks to scop. o IO-348: Missing information in IllegalArgumentException thrown by org.apache.commons.io.FileUtils#validateListFilesParameters. Thanks to plcstpierre. o IO-345: Supply a hook method allowing Tailer actively determining stop condition. Thanks to mkresse. o IO-437: Make IOUtils.EOF public and reuse it in various classes. Fixed Bugs: o IO-446: adds an endOfFileReached method to the TailerListener Thanks to Jeffrey Barrus. o IO-484: FilenameUtils should handle embedded null bytes Thanks to Philippe Arteau. o IO-481: Changed/Corrected algorithm for waitFor o IO-428: BOMInputStream.skip returns wrong count if stream contains no BOM Thanks to Stefan Gmeiner. o IO-488: FileUtils.waitFor(...) swallows thread interrupted status Thanks to Bjrn Buchner. o IO-452: Support for symlinks with missing target. Added support for JDK7 symlink features when present Thanks to David Standish. o IO-453: Regression in FileUtils.readFileToString from 2.0.1 Thanks to Steven Christou. o IO-451: ant test fails - resources missing from test classpath Thanks to David Standish. o IO-435: Document that FileUtils.deleteDirectory, directoryContains and cleanDirectory may throw an IllegalArgumentException in case the passed directory does not exist or is not a directory. Thanks to Dominik Stadler. o IO-424: Javadoc fixes, mostly to appease 1.8.0 Thanks to Ville Skytt. o IO-389: FileUtils.sizeOfDirectory can throw IllegalArgumentException Thanks to Austin Doupnik. o IO-390: FileUtils.sizeOfDirectoryAsBigInteger can overflow. Ensure that recursive calls all use BigInteger o IO-385: FileUtils.doCopyFile can potentially loop for ever Exit loop if no data to copy o IO-383: FileUtils.doCopyFile caches the file size; needs to be documented Added Javadoc; show file lengths in exception message o IO-380: FileUtils.copyInputStreamToFile should document it closes the input source Thanks to claudio_ch. o IO-279: Tailer erroneously considers file as new. Fix to use file.lastModified() rather than System.currentTimeMillis() o IO-356: CharSequenceInputStream#reset() behaves incorrectly in case when buffer size is not dividable by data size. Fix code so skip relates to the encoded bytes; reset now re-encodes the data up to the point of the mark o IO-368: ClassLoaderObjectInputStream does not handle primitive typed members o IO-314: Deprecate all methods that use the default encoding o IO-338: When a file is rotated, finish reading previous file prior to starting new one o IO-354: Commons IO Tailer does not respect UTF-8 Charset. o IO-323: What should happen in FileUtils.sizeOf[Directory] when an overflow takes place? Added Javadoc. o IO-372: FileUtils.moveDirectory can produce misleading error message on failiure o IO-362: IOUtils.contentEquals* methods returns false if input1 == input2, should return true. Thanks to mmadson, ggregory. o IO-357: [Tailer] InterruptedException while the thread is sleeping is silently ignored Thanks to mortenh. o IO-352: Spelling fixes. Thanks to scop. o IO-436: Improper Javadoc comment for FilenameUtils.indexOfExtension. Thanks to christoph.schneegans. Changes: o IO-433: Converted all testcases to JUnit 4 o IO-466: Added testcase to show this was fixed with IO-423 o IO-479: Correct exception message in FileUtils.getFile(File, String...) Thanks to Zhouce Chen. o IO-465: Update to JUnit 4.12 Thanks to based2. o IO-462: IOExceptionWithCause no longer needed o IO-422: Deprecate Charsets Charset constants in favor of Java 7's java.nio.charset.StandardCharsets o IO-239: Convert IOCase to a Java 1.5+ Enumeration [N.B. this is binary compatible] o IO-328: getPrefixLength returns null if filename has leading slashes Javadoc: add examples to show correct behavior; add unit tests o IO-299: FileUtils.listFilesAndDirs includes original dir in results even when it doesn't match filter Javadoc: clarify that original dir is included in the results o IO-375: FilenameUtils.splitOnTokens(String text) check for '**' could be simplified o IO-374: WildcardFileFilter ctors should not use null to mean IOCase.SENSITIVE when delegating to other ctors Compatibility with 2.4: Binary compatible: Yes. Source compatible: Yes. Semantic compatible: Yes. Compatibility with 2.2 and 1.4: Binary compatible: Yes. Source compatible: No, see the rare case in https://issues.apache.org/jira/browse/IO-318. Semantic compatible: No, see the rare case in https://issues.apache.org/jira/browse/IO-318. Commons IO 2.5 requires Java 6 or later. Commons IO 2.4 requires Java 6 or later. Commons IO 2.3 requires Java 6 or later. Commons IO 2.2 requires Java 5 or later. Commons IO 1.4 requires Java 1.3 or later. ============================================================================== Apache Commons IO Version 2.4 ============================================================================== Changes in this version include: New features: o IO-269: Tailer locks file from deletion/rename on Windows. Thanks to sebb. o IO-333: Export OSGi packages at version 1.x in addition to 2.x. Thanks to fmeschbe. o IO-320: Add XmlStreamReader support for UTF-32. Thanks to ggregory. o IO-331: BOMInputStream wrongly detects UTF-32LE_BOM files as UTF-16LE_BOM files in method getBOM(). Thanks to ggregory. o IO-327: Add byteCountToDisplaySize(BigInteger). Thanks to ggregory. o IO-326: Add new FileUtils.sizeOf[Directory] APIs to return BigInteger. Thanks to ggregory. o IO-325: Add IOUtils.toByteArray methods to work with URL and URI. Thanks to raviprak. o IO-324: Add missing Charset sister APIs to method that take a String charset name. Thanks to raviprak. Fixed Bugs: o IO-336: Yottabyte (YB) incorrectly defined in FileUtils. Thanks to rleavelle. o IO-279: Tailer erroneously considers file as new. Thanks to Sergio Bossa, Chris Baron. o IO-335: Tailer#readLines - incorrect CR handling. o IO-334: FileUtils.toURLs throws NPE for null parameter; document the behavior. o IO-332: Improve tailer's reading performance. Thanks to liangly. o IO-279: Improve Tailer performance with buffered reads (see IO-332). o IO-329: FileUtils.writeLines uses unbuffered IO. Thanks to tivv. o IO-319: FileUtils.sizeOfDirectory follows symbolic links. Thanks to raviprak. Compatibility with 2.3: Binary compatible: Yes. Source compatible: Yes. Semantic compatible: Yes. Compatibility with 2.2 and 1.4: Binary compatible: Yes. Source compatible: No, see the rare case in https://issues.apache.org/jira/browse/IO-318. Semantic compatible: No, see the rare case in https://issues.apache.org/jira/browse/IO-318. Commons IO 2.4 requires Java 6 or later. Commons IO 2.3 requires Java 6 or later. Commons IO 2.2 requires Java 5 or later. Commons IO 1.4 requires Java 1.3 or later. ============================================================================== Apache Commons IO Version 2.3 ============================================================================== Changes in this version include: New features: o IO-322: Add and use class Charsets. Thanks to ggregory. o IO-321: ByteOrderMark UTF_32LE is incorrect. Thanks to ggregory. o IO-318: Add Charset sister APIs to method that take a String charset name. Thanks to ggregory. Compatibility with 2.2 and 1.4: Binary compatible: Yes. Source compatible: No, see the rare case in https://issues.apache.org/jira/browse/IO-318. Semantic compatible: No, see the rare case in https://issues.apache.org/jira/browse/IO-318. Commons IO 2.3 requires Java 6 or later. Commons IO 2.2 requires Java 5 or later. Commons IO 1.4 requires Java 1.3 or later. ============================================================================== Apache Commons IO Version 2.2 ============================================================================== Changes in this version include: New features: o Add IOUTils.toBufferedReader(Reader) Issue: IO-313. Thanks to ggregory. o Allow applications to provide buffer (or size) for copyLarge methods. Issue: IO-308. Thanks to Manoj Mokashi. o New copyLarge() method in IOUtils that takes additional offset, length arguments Issue: IO-305. Thanks to Manoj Mokashi. o Use terabyte (TB), petabyte (PB) and exabyte (EB) in FileUtils.byteCountToDisplaySize(long size) Issue: IO-287. Thanks to Ron Kuris, Gary Gregory. o FileUtils.listFiles() doesn't return directories Issue: IO-173. Thanks to Marcos Vincius da Silva. o CharSequenceInputStream to efficiently stream content of a CharSequence Issue: IO-297. Thanks to Oleg Kalnichevski. o The second constructor of Tailer class does not pass 'delay' to the third one Issue: IO-304. Thanks to liangly. o TeeOutputStream does not call branch.close() when main.close() throws an exception Issue: IO-303. Thanks to fabian.barney. o ArrayIndexOutOfBoundsException in BOMInputStream when reading a file without BOM multiple times Issue: IO-302. Thanks to jsteuerwald, detinho. o Add IOUtils.closeQuietly(Selector) necessary Issue: IO-301. Thanks to kaykay.unique. o IOUtils.closeQuietly() should take a ServerSocket as a parameter Issue: IO-292. Thanks to sebb. o Add read/readFully methods to IOUtils Issue: IO-290. Thanks to sebb. o Supply a ReversedLinesFileReader Issue: IO-288. Thanks to Georg Henzler. o Add new function FileUtils.directoryContains. Issue: IO-291. Thanks to ggregory. o FileUtils.contentEquals and IOUtils.contentEquals - Add option to ignore "line endings" Added contentEqualsIgnoreEOL methods to both classes Issue: IO-275. Thanks to CJ Aspromgos. Fixed Bugs: o IOUtils.read(InputStream/Reader) ignores the offset parameter Issue: IO-311. Thanks to Robert Muir. o CharSequenceInputStream(CharSequence s, Charset charset, int bufferSize) ignores bufferSize Issue: IO-312. o FileUtils.moveDirectoryToDirectory removes source directory if destination is a subdirectory Issue: IO-300. o ReaderInputStream#read(byte[] b, int off, int len) should check for valid parameters Issue: IO-307. o ReaderInputStream#read(byte[] b, int off, int len) should always return 0 for length == 0 Issue: IO-306. o "FileUtils#deleteDirectoryOnExit(File)" does not work Issue: IO-276. Thanks to nkami. o BoundedInputStream.read() treats max differently from BoundedInputStream.read(byte[]...) Issue: IO-273. Thanks to sebb. o Various methods of class 'org.apache.commons.io.FileUtils' incorrectly suppress 'java.io.IOException' Issue: IO-298. Thanks to Christian Schulte. Changes: o ReaderInputStream optimization: more efficient reading of small chunks of data Issue: IO-296. Thanks to Oleg Kalnichevski. Compatibility with 2.1 and 1.4: Binary compatible: Yes Source compatible: Yes Semantic compatible: Yes. Check the bug fixes section for semantic bug fixes Commons IO 2.2 requires a minimum of Java 5. Commons IO 1.4 requires a minimum of Java 1.3. ============================================================================== Apache Commons IO Version 2.1 ============================================================================== New features: o Use standard Maven directory layout Issue: IO-285. Thanks to ggregory. o Add IOUtils API toString for URL and URI to get contents Issue: IO-284. Thanks to ggregory. o Add API FileUtils.copyFile(File input, OutputStream output) Issue: IO-282. Thanks to ggregory. o FileAlterationObserver has no getter for FileFilter Issue: IO-262. o Add FileUtils.getFile API with varargs parameter Issue: IO-261. o Add new APPEND parameter for writing string into files Issue: IO-182. o Add new read method "toByteArray" to handle InputStream with known size. Issue: IO-251. Thanks to Marco Albini. Fixed Bugs: o Dubious use of mkdirs() return code Issue: IO-280. Thanks to sebb. o ReaderInputStream enters infinite loop when it encounters an unmappable character Issue: IO-277. o FileUtils.moveFile() Javadoc should specify FileExistsException thrown Issue: IO-264. o ClassLoaderObjectInputStream does not handle Proxy classes Issue: IO-260. o Tailer returning partial lines when reaching EOF before EOL Issue: IO-274. Thanks to Frank Grimes. o FileUtils.copyFile() throws IOException when copying large files to a shared directory (on Windows) Issue: IO-266. Thanks to Igor Smereka. o FileSystemUtils.freeSpaceKb throws exception for Windows volumes with no visible files. Improve coverage by also looking for hidden files. Issue: IO-263. Thanks to Gil Adam. Changes: o FileAlterationMonitor.stop(boolean allowIntervalToFinish) Issue: IO-259. ============================================================================== Apache Commons IO Package 2.0.1 ============================================================================== Compatibility with 2.0 and 1.4 ------------------------------ Binary compatible - Yes Source compatible - Yes Semantic compatible - Yes Check the bug fixes section for semantic bug fixes Commons IO 2.0.1 requires a minimum of Java 5 (Commons IO 1.4 had a minimum of Java 1.3) Enhancements from 2.0 --------------------- * [IO-256] - Provide thread factory for FileAlternationMonitor Bug fixes from 2.0 ------------------ * [IO-257] - BOMInputStream.read(byte[]) can return 0 which it should not * [IO-258] - XmlStreamReader consumes the stream during encoding detection ============================================================================== Apache Commons IO Package 2.0 ============================================================================== Compatibility with 1.4 ---------------------- Binary compatible - Yes Source compatible - Yes Semantic compatible - Yes Check the bug fixes section for semantic bug fixes Commons IO 2.0 requires a minimum of Java 5 (Commons IO 1.4 had a minimum of Java 1.3) Deprecations from 1.4 --------------------- - IOUtils - write(StringBuffer, Writer) in favour of write(CharSequence, Writer) - write(StringBuffer, OutputStream) in favour of write(CharSequence, OutputStream) - write(StringBuffer, OutputStream, String) in favour of write(CharSequence, OutputStream, String) - FileFilterUtils - andFileFilter(IOFileFilter, IOFileFilter) in favour of and(IOFileFilter...) - orFileFilter(IOFileFilter, IOFileFilter) in favour of or(IOFileFilter...) Enhancements from 1.4 --------------------- * [IO-140] Move minimum Java requirement from Java 1.3 to Java 5 - use Generics - add new CharSequence write() flavour methods to IOUtils and FileUtils - replace StringBuffer with StringBuilder, where appropriate - add new Reader/Writer methods to ProxyReader and ProxyWriter - Annotate with @Override and @Deprecated * [IO-178] New BOMInputStream and ByteOrderMark implementations - to detect and optionally exclude an initial Byte Order mark (BOM) * [IO-197] New BoundedInputStream (copied from from Apache JackRabbit) * [IO-193] New Broken Input and Output streams * [IO-132] New File Listener/Monitor facility * [IO-158] New ReaderInputStream and WriterOutputStream implementations * [IO-139] New StringBuilder Writer implementation * [IO-192] New Tagged Input and Output streams * [IO-177] New Tailer class - simple implementation of the Unix "tail -f" functionality * [IO-162] New XML Stream Reader/Writer implementations (from ROME via plexus-utils) * [IO-142] Comparators - add facility to sort file lists/arrays * [IO-186] Comparators - new Composite and Directory File Comparator implementations * [IO-176] DirectoryWalker - add filterDirectoryContents() callback method for filtering directory contents * [IO-210] FileFilter - new Magic Number FileFilter * [IO-221] FileFilterUtils - add methods for suffix and prefix filters which take an IOCase object * [IO-232] FileFilterUtils - add method for name filters which take an IOCase object * [IO-229] FileFilterUtils - add varargs and() and or() methods * [IO-198] FileFilterUtils - add ability to apply file filters to collections and arrays * [IO-156] FilenameUtils - add normalize() and normalizeNoEndSeparator() methods which allow the separator character to be specified * [IO-194] FileSystemUtils - add freeSpaceKb() method with no input arguments * [IO-185] FileSystemUtils - add freeSpaceKb() methods that take a timeout parameter - fixes freeSpaceWindows() blocks * [IO-155] FileUtils - use NIO to copy files * [IO-168] FileUtils - add new isSymlink() method * [IO-219] FileUtils - throw FileExistsException when moving a file or directory if the destination already exists * [IO-234] FileUtils - add Methods for retrieving System User/Temp directories/paths * [IO-208] FileUtils - add timeout (connection and read) support for copyURLToFile() method * [IO-238] FileUtils - add sizeOf(File) method * [IO-181] LineIterator now implements Iterable * [IO-224] IOUtils - add closeQuietly(Closeable) and closeQuietly(Socket) methods * [IO-203] IOUtils - add skipFully() method for InputStreams * [IO-137] IOUtils and ByteArrayOutputStream - add toBufferedInputStream() method to avoid unnecessary array allocation/copy * [IO-195] Proxy streams/Reader/Writer - provide exception handling methods * [IO-211] Proxy Input/Output streams - add pre/post processing support * [IO-242] Proxy Reader/Writer - add pre/post processing support Bug fixes from 1.4 ------------------ * [IO-214] ByteArrayOutputStream - fix inconsistent synchronization of fields * [IO-201] Counting Input/Output streams - fix inconsistent synchronization * [IO-159] FileCleaningTracker - fix remove() never returns null * [IO-220] FileCleaningTracker - fix Vector performs badly under load * [IO-167] FilenameUtils - fix case-insensitive string handling in FilenameUtils and FilesystemUtils * [IO-179] FilenameUtils - fix StringIndexOutOfBounds exception in getPathNoEndSeparator() * [IO-248] FilenameUtils - fix getFullPathNoEndSeparator() returns empty while path is a one level directory * [IO-246] FilenameUtils - fix wildcardMatch gives incorrect results * [IO-187] FileSystemUtils - fix freeSpaceKb() doesn't work with relative paths on Linux * [IO-160] FileSystemUtils - fix freeSpace() fails on solaris * [IO-209] FileSystemUtils - fix freeSpaceKb() fails to return correct size for a windows mount point * [IO-163] FileUtils - fix toURLs() using deprecated method of conversion to URL * [IO-168] FileUtils - fix Symbolic links followed when deleting directory * [IO-231] FileUtils - fix wrong exception message generated in isFileNewer() method * [IO-207] FileUtils - fix race condition in forceMkdir() method * [IO-217] FileUtils - fix copyDirectoryToDirectory() makes infinite loops * [IO-166] FileUtils - fix URL decoding in toFile(URL) * [IO-190] FileUtils - fix copyDirectory not preserving lastmodified date on sub-directories * [IO-240] FileFilterUtils - ensure cvsFilter and svnFilter are only created once. * [IO-175] IOUtils - fix copyFile() issues with very large files * [IO-191] Improvements from static analysis * [IO-216] LockableFileWriter - delete files quietly when an exception is thrown during initialization * [IO-243] SwappedDataInputStream - fix readBoolean is inverted * [IO-235] Tests - remove unused YellOnFlushAndCloseOutputStream from CopyUtilsTest * [IO-161] Tests - fix FileCleaningTrackerTestCase hanging Documentation changes from 1.4 ------------------------------ * [IO-183 FilenameUtils.getExtension() method documentation improvements * [IO-226 FileUtils.byteCountToDisplaySize() documentation corrections * [IO-205 FileUtils.forceMkdir() documentation improvements * [IO-215 FileUtils copy file/directory improve documentation regarding preserving the last modified date * [IO-189 HexDump.dump() method documentation improvements * [IO-171 IOCase document that it assumes there are only two OSes: Windows and Unix * [IO-223 IOUtils.copy() documentation corrections * [IO-247 IOUtils.closeQuietly() improve documentation with examples * [IO-202 NotFileFilter documentation corrections * [IO-206 ProxyInputStream - fix misleading parameter names * [IO-212 ProxyInputStream.skip() documentation corrections ============================================================================== Apache Commons IO Version 1.4 ============================================================================== Compatibility with 1.3.2 ------------------------ Binary compatible - Yes Source compatible - Yes Semantic compatible - Yes Check the bug fixes section for semantic bug fixes Commons IO 1.4 introduces four new implementations which depend on Java 4 features (CharSequenceReader, FileWriterWithEncoding, IOExceptionWithCause and RegexFileFilter). It has been built with the JDK source and target options set to Java 1.3 and, except for those implementations, can be used with Java 1.3 (see IO IO-127). Deprecations from 1.3.2 ----------------------- - FileCleaner deprecated in favour of FileCleaningTracker [see IO-116] Bug fixes from 1.3.2 -------------------- - FileUtils - forceDelete of orphaned Softlinks does not work [IO-147] - Infinite loop on FileUtils.copyDirectory when the destination directory is within the source directory [IO-141] - Add a copyDirectory() method that makes use of FileFilter [IO-105] - Add moveDirectory() and moveFile() methods [IO-77] - HexDump - HexDump's use of static StringBuffers isn't thread-safe [IO-136] Enhancements from 1.3.2 ----------------------- - FileUtils - Add a deleteQuietly method [IO-135] - FilenameUtils - Add file name extension separator constants[IO-149] - IOExceptionWithCause [IO-148] - Add a new IOException implementation with constructors which take a cause - TeeInputStream [IO-129] - Add new Tee input stream implementation - FileWriterWithEncoding [IO-153] - Add new File Writer implementation that accepts an encoding - CharSequenceReader [IO-138] - Add new Reader implementation that handles any CharSequence (String, StringBuffer, StringBuilder or CharBuffer) - ThesholdingOuputStream [IO-121] - Add a reset() method which sets the count of the bytes written back to zero. - DeferredFileOutputStream [IO-130] - Add support for temporary files - ByteArrayOutputStream - Add a new write(InputStream) method [IO-152] - New Closed Input/Output stream implementations [IO-122] - AutoCloseInputStream - automatically closes and discards the underlying input stream - ClosedInputStream - returns -1 for any read attempts - ClosedOutputStream - throws an IOException for any write attempts - CloseShieldInputStream - prevents the underlying input stream from being closed. - CloseShieldOutputStream - prevents the underlying output stream from being closed. - Add Singleton Constants to several stream classes [IO-143] - PrefixFileFilter [IO-126] - Add faciltiy to specify case sensitivity on prefix matching - SuffixFileFilter [IO-126] - Add faciltiy to specify case sensitivity on suffix matching - RegexFileFilter [IO-74] - Add new regular expression file filter implementation - Make IOFileFilter implementations Serializable [IO-131] - Improve IOFileFilter toString() methods [IO-120] - Make fields final so classes are immutable/threadsafe [IO-133] - changes to Age, Delegate, Name, Not, Prefix, Regex, Size, Suffix and Wildcard IOFileFilter implementations. - IOCase - Add a compare method to IOCase [IO-144] - Add a package of java.util.Comparator implementations for files [IO-145] - DefaultFileComparator - compare files using the default File.compareTo(File) method. - ExtensionFileComparator - compares files using file name extensions. - LastModifiedFileComparator - compares files using the last modified date/time. - NameFileComparator - compares files using file names. - PathFileComparator - compares files using file paths. - SizeFileComparator - compares files using file sizes. ============================================================================== Apache Commons IO Version 1.3.2 ============================================================================== Compatibility with 1.3.1 ---------------------- Binary compatible - Yes Source compatible - Yes Semantic compatible - Yes Compatibility with 1.3 ---------------------- Binary compatible - No See [IO-113] Source compatible - No See [IO-113] Semantic compatible - Yes Enhancements since 1.3.1 ------------------------ - Created the FileCleaningTracker, basically a non-static version of the FileCleaner, which can be controlled by the user. [IO-116] - The FileCleaner is deprecated. Bug fixes from 1.3.1 -------------------- - Some tests, which are implicitly assuming a Unix-like file system, are now skipped on Windows. [IO-115] - EndianUtils - Both readSwappedUnsignedInteger(...) methods could return negative numbers due to int/long casting. [IO-117] Bug fixes from 1.3 ------------------ - FileUtils - NPE in openOutputStream(File) when file has no parent in path [IO-112] - readFileToString(File) is not static [IO-113] ============================================================================== Apache Commons IO Version 1.3.1 ============================================================================== Compatibility with 1.3 ---------------------- Binary compatible - No See [IO-113] Source compatible - No See [IO-113] Semantic compatible - Yes Bug fixes from 1.3 ------------------ - FileUtils - NPE in openOutputStream(File) when file has no parent in path [IO-112] - readFileToString(File) is not static [IO-113] ============================================================================== Apache Commons IO Version 1.3 ============================================================================== Compatibility with 1.2 ---------------------- Binary compatible - Yes Source compatible - Yes Semantic compatible - Yes Check the bug fixes section for semantic bug fixes Deprecations from 1.2 --------------------- - WildcardFilter deprecated, replaced by WildcardFileFilter - old class only accepted files, thus had a confusing dual purpose - FileSystemUtils.freeSpace deprecated, replaced by freeSpaceKb - freeSpace returns a result that varies by operating system and thus isn't that useful - freeSpaceKb returns much better and more consistent results - freeSpaceKb existed in v1.2, so this is a gentle cutover Bug fixes from 1.2 ------------------ - LineIterator now implements Iterator - It was always supposed to... - FileSystemUtils.freeSpace/freeSpaceKb [IO-83] - These should now work on AIX and HP-UX - FileSystemUtils.freeSpace/freeSpaceKb [IO-90] - Avoid infinite looping in Windows - Catch more errors with nice messages - FileSystemUtils.freeSpace [IO-91] - This is now documented not to work on SunOS 5 - FileSystemUtils [IO-93] - Fixed resource leak leading to 'Too many open files' error - Previously did not destroy Process instances (as JDK Javadoc is so poor) - http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4801027 - FileUtils.touch [IO-100] - The touch method previously gave no indication when the file could not be touched successfully (such as due to access restrictions) - it now throws an IOException if the last modified date cannot be changed - FileCleaner - This now handles the situation where an error occurs when deleting the file - IOUtils.copy [IO-84] - Copy methods could return inaccurate byte/char count for large streams - The copy(InputStream, OutputStream) method now returns -1 if the count is greater than an int - The copy(Reader, Writer) method now throws now returns -1 if the count is greater than an int - Added a new copyLarge(InputStream, OutputStream) method that returns a long - Added a new copyLarge(Reader, Writer) method that returns a long - CountingInputStream/CountingOutputStream [IO-84] - Methods were declared as int thus the count was innacurate for large streams - new long based methods getByteCount()/resetByteCount() added - existing methods changed to throw an exception if the count is greater than an int - FileBasedTestCase - Fixed bug in compare content methods identified by GNU classpath - EndianUtils.writeSwappedLong(byte[], int) [IO-101] - An int overrun in the bit shifting when it should have been a long - EndianUtils.writeSwappedLong(InputStream) [IO-102] - The return of input.read(byte[]) was not being checked to ensure all 8 bytes were read Enhancements from 1.2 --------------------- - DirectoryWalker [IO-86] - New class designed for subclassing to walk through a set of files. DirectoryWalker provides the walk of the directories, filtering of directories and files, and cancellation support. The subclass must provide the specific behavior, such as text searching or image processing. - IOCase - New class/enumeration for case-sensitivity control - FilenameUtils - New methods to handle case-sensitivity - wildcardMatch - new method that has IOCase as a parameter - equals - new method that has IOCase as a parameter - FileUtils [IO-108] - new default encoding methods for: - readFileToString(File) - readLines(File) - lineIterator(File) - writeStringToFile(File, String) - writeLines(File, Collection) - writeLines(File, Collection, String) - FileUtils.openOutputStream [IO-107] - new method to open a FileOutputStream, creating parent directories if required - FileUtils.touch - FileUtils.copyURLToFile - FileUtils.writeStringToFile - FileUtils.writeByteArrayToFile - FileUtils.writeLines - enhanced to create parent directories if required - FileUtils.openInputStream [IO-107] - new method to open a FileInputStream, providing better error messages than the JDK - FileUtils.isFileOlder - new methods to check if a file is older (i.e. isFileOlder()) - counterparts to the existing isFileNewer() methods. - FileUtils.checksum, FileUtils.checksumCRC32 - new methods to create a checksum of a file - FileUtils.copyFileToDirectory [IO-104] - new variant that optionally retains the file date - FileDeleteStrategy - FileCleaner [IO-56,IO-70] - FileDeleteStrategy is a strategy for handling file deletion - This can be used as a calback in FileCleaner - Together these allow FileCleaner to do a forceDelete to kill directories - FileCleaner.exitWhenFinished [IO-99] - A new method that allows the internal cleaner thread to be cleanly terminated - WildcardFileFilter - Replacement for WildcardFilter - Accepts both files and directories - Ability to control case-sensitivity - NameFileFilter - Ability to control case-sensitivity - FileFileFilter - New IOFileFilter implementation - Accepts files where File.isFile() is true - In other words it filters out directories - Singleton instance provided (FILE) - CanReadFileFilter - New IOFileFilter implementation - Accepts files where File.canRead() is true - Singleton instances provided (CAN_READ/CANNOT_READ/READ_ONLY) - CanWriteFileFilter - New IOFileFilter implementation - Accepts files where File.canWrite() is true - Singleton instances provided (CAN_WRITE/CANNOT_WRITE) - HiddenFileFilter - New IOFileFilter implementation - Accepts files where File.isHidden() is true - Singleton instances provided (HIDDEN/VISIBLE) - EmptyFileFilter - New IOFileFilter implementation - Accepts files or directories that are empty - Singleton instances provided (EMPTY/NOT_EMPTY) - TrueFileFilter/FalseFileFilter/DirectoryFileFilter - New singleton instance constants (TRUE/FALSE/DIRECTORY) - The new constants are more Java 5 friendly with regards to static imports (whereas if everything uses INSTANCE, then they just clash) - The old INSTANCE constants are still present and have not been deprecated - FileFilterUtils.sizeRangeFileFilter - new sizeRangeFileFilter(long minimumSize, long maximumSize) method which creates a filter that accepts files within the specified size range. - FileFilterUtils.makeDirectoryOnly/makeFileOnly - two new methods that decorate a file filter to make it apply to directories only or files only - NullWriter - New writer that acts as a sink for all data, as per /dev/null - NullInputStream - New input stream that emulates a stream of a specified size - NullReader - New reader that emulates a reader of a specified size - ByteArrayOutputStream [IO-97] - Performance enhancements ============================================================================== Apache Commons IO Version 1.2 ============================================================================== Compatibility with 1.1 ---------------------- Binary compatible - Yes Source compatible - Yes Semantic compatible - Yes Deprecations from 1.1 --------------------- Bug fixes from 1.1 ------------------ - FileSystemUtils.freeSpace(drive) Fix to allow Windows based command to function in French locale - FileUtils.read* Increase certainty that files are closed in case of error - LockableFileWriter Locking mechanism was broken and only provided limited protection [38942] File deletion and locking in case of constructor error was broken Enhancements from 1.1 --------------------- - AgeFileFilter/SizeFileFilter New file filters that compares against the age and size of the file - FileSystemUtils.freeSpaceKb(drive) New method that unifies result to be in kilobytes [38574] - FileUtils.contentEquals(File,File) Performance improved by adding length and file location checking - FileUtils.iterateFiles Two new method to provide direct access to iterators over files - FileUtils.lineIterator IOUtils.lineIterator New methods to provide an iterator over the lines in a file [38083] - FileUtils.copyDirectoryToDirectory New method to copy a directory to within another directory [36315] ============================================================================== Apache Commons IO Version 1.1 ============================================================================== Incompatible changes from 1.0 ----------------------------- Binary compatible - Yes Source compatible - Yes Semantic compatible - Yes, except: - FileUtils.writeStringToFile() A null encoding previously used 'ISO-8859-1', now it uses the platform default Generally this will make no difference - LockableFileWriter Improved validation and now create directories if necesssary plus these bug fixes may affect you semantically: - FileUtils.touch() (Bug fix 29821) Now creates the file if it did not previously exist - FileUtils.toFile(URL) (Bug fix 32575) Now handles escape syntax such as %20 - FileUtils.sizeOfDirectory() (Bug fix 36801) May now return a size of 0 if the directory is security restricted Deprecations from 1.0 --------------------- - CopyUtils has been deprecated. Its methods have been moved to IOUtils. The new IOUtils methods handle nulls better, and have clearer names. - IOUtils.toByteArray(String) - Use {@link String#getBytes()} - IOUtils.toString(byte[]) - Use {@link String#String(byte[])} - IOUtils.toString(byte[],String) - Use {@link String#String(byte[],String)} Bug fixes from 1.0 ------------------ - FileUtils - touch() [29821] Now creates the file if it did not previously exist - FileUtils - toFile(URL) [32575] Now handles escape syntax such as %20 - FileFilterUtils - makeCVSAware(IOFileFilter) [33023] Fixed bug that caused method to be completely broken - CountingInputStream [33336] Fixed bug that caused the count to reduce by one at the end of the stream - CountingInputStream - skip(long) [34311] Bytes from calls to this method were not previously counted - NullOutputStream [33481] Remove unnecessary synchronization - AbstractFileFilter - accept(File, String) [30992] Fixed broken implementation - FileUtils [36801] Previously threw NPE when listing files in a security restricted directory Now throw IOException with a better message - FileUtils - writeStringToFile() Null encoding now correctly uses the platform default Enhancements from 1.0 --------------------- - FilenameUtils - new class [33303,29351] A static utility class for working with filenames Seeks to ease the pain of developing on Windows and deploying on Unix - FileSystemUtils - new class [32982,36325] A static utility class for working with file systems Provides one method at present, to get the free space on the filing system - IOUtils - new public constants Constants for directory and line separators on Windows and Unix - IOUtils - toByteArray(Reader,encoding) Handles encodings when reading to a byte array - IOUtils - toCharArray(InputStream) [28979] - toCharArray(InputStream,encoding) - toCharArray(Reader) Reads a stream/reader into a charatcter array - IOUtils - readLines(InputStream) [36214] - readLines(InputStream,encoding) - readLines(Reader) Reads a stream/reader line by line into a List of Strings - IOUtils - toInputStream(String) [32958] - toInputStream(String,encoding) Creates an input stream that uses the string as a source of data - IOUtils - writeLines(Collection,lineEnding,OutputStream) [36214] - writeLines(Collection,lineEnding,OutputStream,encoding) - writeLines(Collection,lineEnding,Writer) Writes a collection to a stream/writer line by line - IOUtils - write(...) Write data to a stream/writer (moved from CopyUtils with better null handling) - IOUtils - copy(...) Copy data between streams (moved from CopyUtils with better null handling) - IOUtils - contentEquals(Reader,Reader) Method to compare the contents of two readers - FileUtils - toFiles(URL[]) Converts an array of URLs to an array of Files - FileUtils - copyDirectory() [32944] New methods to copy a directory - FileUtils - readFileToByteArray(File) Reads an entire file into a byte array - FileUtils - writeByteArrayToFile(File,byte[]) Writes a byte array to a file - FileUtils - readLines(File,encoding) [36214] Reads a file line by line into a List of Strings - FileUtils - writeLines(File,encoding,List) writeLines(File,encoding,List,lineEnding) Writes a collection to a file line by line - FileUtils - EMPTY_FILE_ARRAY Constant for an empty array of File objects - ConditionalFileFilter - new interface [30705] Defines the behavior of list based filters - AndFileFilter, OrFileFilter [30705] Now support a list of filters to and/or - WildcardFilter [31115] New filter that can match using wildcard file names - FileFilterUtils - makeSVNAware(IOFileFilter) New method, like makeCVSAware, that ignores Subversion source control directories - ClassLoaderObjectInputStream An ObjectInputStream that supports a ClassLoader - CountingInputStream,CountingOutputStream - resetCount() [28976] Adds the ability to reset the count part way through reading/writing the stream - DeferredFileOutputStream - writeTo(OutputStream) [34173] New method to allow current contents to be written to a stream - DeferredFileOutputStream [34142] Performance optimizations avoiding double buffering - LockableFileWriter - encoding support [36825] Add support for character encodings to LockableFileWriter Improve the validation Create directories if necesssary - IOUtils and EndianUtils are no longer final [28978] Allows developers to have subclasses if desired ============================================================================== Feedback ============================================================================== Open source works best when you give feedback: https://commons.apache.org/io/ Please direct all bug reports to JIRA https://issues.apache.org/jira/browse/IO Or subscribe to the commons-user mailing list (prefix emails by [io]) https://commons.apache.org/mail-lists.html The Commons-IO Team commons-io-2.11.0-src/src/main/java/org/apache/commons/io/ByteOrderMark.java0100644 0000000 0000000 00000013454 13612062727 027117 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import java.io.Serializable; import java.util.Locale; /** * Byte Order Mark (BOM) representation - see {@link org.apache.commons.io.input.BOMInputStream}. * * @see org.apache.commons.io.input.BOMInputStream * @see Wikipedia: Byte Order Mark * @see W3C: Autodetection of Character Encodings * (Non-Normative) * @since 2.0 */ public class ByteOrderMark implements Serializable { private static final long serialVersionUID = 1L; /** UTF-8 BOM. */ public static final ByteOrderMark UTF_8 = new ByteOrderMark("UTF-8", 0xEF, 0xBB, 0xBF); /** UTF-16BE BOM (Big-Endian). */ public static final ByteOrderMark UTF_16BE = new ByteOrderMark("UTF-16BE", 0xFE, 0xFF); /** UTF-16LE BOM (Little-Endian). */ public static final ByteOrderMark UTF_16LE = new ByteOrderMark("UTF-16LE", 0xFF, 0xFE); /** * UTF-32BE BOM (Big-Endian). * * @since 2.2 */ public static final ByteOrderMark UTF_32BE = new ByteOrderMark("UTF-32BE", 0x00, 0x00, 0xFE, 0xFF); /** * UTF-32LE BOM (Little-Endian). * * @since 2.2 */ public static final ByteOrderMark UTF_32LE = new ByteOrderMark("UTF-32LE", 0xFF, 0xFE, 0x00, 0x00); /** * Unicode BOM character; external form depends on the encoding. * * @see Byte Order Mark (BOM) FAQ * @since 2.5 */ public static final char UTF_BOM = '\uFEFF'; private final String charsetName; private final int[] bytes; /** * Constructs a new BOM. * * @param charsetName The name of the charset the BOM represents * @param bytes The BOM's bytes * @throws IllegalArgumentException if the charsetName is null or * zero length * @throws IllegalArgumentException if the bytes are null or zero * length */ public ByteOrderMark(final String charsetName, final int... bytes) { if (charsetName == null || charsetName.isEmpty()) { throw new IllegalArgumentException("No charsetName specified"); } if (bytes == null || bytes.length == 0) { throw new IllegalArgumentException("No bytes specified"); } this.charsetName = charsetName; this.bytes = new int[bytes.length]; System.arraycopy(bytes, 0, this.bytes, 0, bytes.length); } /** * Gets the name of the {@link java.nio.charset.Charset} the BOM represents. * * @return the character set name */ public String getCharsetName() { return charsetName; } /** * Gets the length of the BOM's bytes. * * @return the length of the BOM's bytes */ public int length() { return bytes.length; } /** * Gets the byte at the specified position. * * @param pos The position * @return The specified byte */ public int get(final int pos) { return bytes[pos]; } /** * Gets a copy of the BOM's bytes. * * @return a copy of the BOM's bytes */ public byte[] getBytes() { final byte[] copy = IOUtils.byteArray(bytes.length); for (int i = 0; i < bytes.length; i++) { copy[i] = (byte)bytes[i]; } return copy; } /** * Indicates if this BOM's bytes equals another. * * @param obj The object to compare to * @return true if the bom's bytes are equal, otherwise * false */ @Override public boolean equals(final Object obj) { if (!(obj instanceof ByteOrderMark)) { return false; } final ByteOrderMark bom = (ByteOrderMark)obj; if (bytes.length != bom.length()) { return false; } for (int i = 0; i < bytes.length; i++) { if (bytes[i] != bom.get(i)) { return false; } } return true; } /** * Computes the hashcode for this BOM. * * @return the hashcode for this BOM. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int hashCode = getClass().hashCode(); for (final int b : bytes) { hashCode += b; } return hashCode; } /** * Converts this instance to a String representation of the BOM. * * @return the length of the BOM's bytes */ @Override public String toString() { final StringBuilder builder = new StringBuilder(); builder.append(getClass().getSimpleName()); builder.append('['); builder.append(charsetName); builder.append(": "); for (int i = 0; i < bytes.length; i++) { if (i > 0) { builder.append(","); } builder.append("0x"); builder.append(Integer.toHexString(0xFF & bytes[i]).toUpperCase(Locale.ROOT)); } builder.append(']'); return builder.toString(); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/ByteOrderParser.java0100644 0000000 0000000 00000004720 13612062727 027455 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import java.nio.ByteOrder; /** * Converts Strings to {@link ByteOrder} instances. * * @since 2.6 */ public final class ByteOrderParser { /** * ByteOrderUtils is a static utility class, so prevent construction with a private constructor. */ private ByteOrderParser() { } /** * Parses the String argument as a {@link ByteOrder}. *

* Returns {@code ByteOrder.LITTLE_ENDIAN} if the given value is {@code "LITTLE_ENDIAN"}. *

*

* Returns {@code ByteOrder.BIG_ENDIAN} if the given value is {@code "BIG_ENDIAN"}. *

* Examples: *
    *
  • {@code ByteOrderParser.parseByteOrder("LITTLE_ENDIAN")} returns {@code ByteOrder.LITTLE_ENDIAN}
  • *
  • {@code ByteOrderParser.parseByteOrder("BIG_ENDIAN")} returns {@code ByteOrder.BIG_ENDIAN}
  • *
* * @param value * the {@code String} containing the ByteOrder representation to be parsed * @return the ByteOrder represented by the string argument * @throws IllegalArgumentException * if the {@code String} containing the ByteOrder representation to be parsed is unknown. */ public static ByteOrder parseByteOrder(final String value) { if (ByteOrder.BIG_ENDIAN.toString().equals(value)) { return ByteOrder.BIG_ENDIAN; } if (ByteOrder.LITTLE_ENDIAN.toString().equals(value)) { return ByteOrder.LITTLE_ENDIAN; } throw new IllegalArgumentException("Unsupported byte order setting: " + value + ", expected one of " + ByteOrder.LITTLE_ENDIAN + ", " + ByteOrder.BIG_ENDIAN); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/Charsets.java0100644 0000000 0000000 00000020050 13612062727 026147 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.nio.charset.UnsupportedCharsetException; import java.util.Collections; import java.util.SortedMap; import java.util.TreeMap; /** * Charsets required of every implementation of the Java platform. * * From the Java documentation * Standard charsets: *

* Every implementation of the Java platform is required to support the following character encodings. Consult * the release documentation for your implementation to see if any other encodings are supported. Consult the release * documentation for your implementation to see if any other encodings are supported. *

* *
    *
  • {@code US-ASCII}
    * Seven-bit ASCII, a.k.a. ISO646-US, a.k.a. the Basic Latin block of the Unicode character set.
  • *
  • {@code ISO-8859-1}
    * ISO Latin Alphabet No. 1, a.k.a. ISO-LATIN-1.
  • *
  • {@code UTF-8}
    * Eight-bit Unicode Transformation Format.
  • *
  • {@code UTF-16BE}
    * Sixteen-bit Unicode Transformation Format, big-endian byte order.
  • *
  • {@code UTF-16LE}
    * Sixteen-bit Unicode Transformation Format, little-endian byte order.
  • *
  • {@code UTF-16}
    * Sixteen-bit Unicode Transformation Format, byte order specified by a mandatory initial byte-order mark (either order * accepted on input, big-endian used on output.)
  • *
* * @see Standard charsets * @since 2.3 */ public class Charsets { // // This class should only contain Charset instances for required encodings. This guarantees that it will load // correctly and without delay on all Java platforms. // private static final SortedMap STANDARD_CHARSET_MAP; static { final SortedMap standardCharsetMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); standardCharsetMap.put(StandardCharsets.ISO_8859_1.name(), StandardCharsets.ISO_8859_1); standardCharsetMap.put(StandardCharsets.US_ASCII.name(), StandardCharsets.US_ASCII); standardCharsetMap.put(StandardCharsets.UTF_16.name(), StandardCharsets.UTF_16); standardCharsetMap.put(StandardCharsets.UTF_16BE.name(), StandardCharsets.UTF_16BE); standardCharsetMap.put(StandardCharsets.UTF_16LE.name(), StandardCharsets.UTF_16LE); standardCharsetMap.put(StandardCharsets.UTF_8.name(), StandardCharsets.UTF_8); STANDARD_CHARSET_MAP = Collections.unmodifiableSortedMap(standardCharsetMap); } /** * Constructs a sorted map from canonical charset names to charset objects required of every implementation of the * Java platform. *

* From the Java documentation * Standard charsets: *

* * @return An immutable, case-insensitive map from canonical charset names to charset objects. * @see Charset#availableCharsets() * @since 2.5 */ public static SortedMap requiredCharsets() { return STANDARD_CHARSET_MAP; } /** * Returns the given Charset or the default Charset if the given Charset is null. * * @param charset * A charset or null. * @return the given Charset or the default Charset if the given Charset is null */ public static Charset toCharset(final Charset charset) { return charset == null ? Charset.defaultCharset() : charset; } /** * Returns a Charset for the named charset. If the name is null, return the default Charset. * * @param charsetName The name of the requested charset, may be null. * @return a Charset for the named charset. * @throws UnsupportedCharsetException If the named charset is unavailable (unchecked exception). */ public static Charset toCharset(final String charsetName) throws UnsupportedCharsetException { return charsetName == null ? Charset.defaultCharset() : Charset.forName(charsetName); } /** * CharEncodingISO Latin Alphabet No. 1, a.k.a. ISO-LATIN-1. *

* Every implementation of the Java platform is required to support this character encoding. *

* * @see Standard charsets * @deprecated Use Java 7's {@link java.nio.charset.StandardCharsets} */ @Deprecated public static final Charset ISO_8859_1 = StandardCharsets.ISO_8859_1; /** *

* Seven-bit ASCII, also known as ISO646-US, also known as the Basic Latin block of the Unicode character set. *

*

* Every implementation of the Java platform is required to support this character encoding. *

* * @see Standard charsets * @deprecated Use Java 7's {@link java.nio.charset.StandardCharsets} */ @Deprecated public static final Charset US_ASCII = StandardCharsets.US_ASCII; /** *

* Sixteen-bit Unicode Transformation Format, The byte order specified by a mandatory initial byte-order mark * (either order accepted on input, big-endian used on output) *

*

* Every implementation of the Java platform is required to support this character encoding. *

* * @see Standard charsets * @deprecated Use Java 7's {@link java.nio.charset.StandardCharsets} */ @Deprecated public static final Charset UTF_16 = StandardCharsets.UTF_16; /** *

* Sixteen-bit Unicode Transformation Format, big-endian byte order. *

*

* Every implementation of the Java platform is required to support this character encoding. *

* * @see Standard charsets * @deprecated Use Java 7's {@link java.nio.charset.StandardCharsets} */ @Deprecated public static final Charset UTF_16BE = StandardCharsets.UTF_16BE; /** *

* Sixteen-bit Unicode Transformation Format, little-endian byte order. *

*

* Every implementation of the Java platform is required to support this character encoding. *

* * @see Standard charsets * @deprecated Use Java 7's {@link java.nio.charset.StandardCharsets} */ @Deprecated public static final Charset UTF_16LE = StandardCharsets.UTF_16LE; /** *

* Eight-bit Unicode Transformation Format. *

*

* Every implementation of the Java platform is required to support this character encoding. *

* * @see Standard charsets * @deprecated Use Java 7's {@link java.nio.charset.StandardCharsets} */ @Deprecated public static final Charset UTF_8 = StandardCharsets.UTF_8; } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/CopyUtils.java0100644 0000000 0000000 00000035146 13612062727 026342 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import static org.apache.commons.io.IOUtils.EOF; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Reader; import java.io.StringReader; import java.io.Writer; import java.nio.charset.Charset; /** * This class provides static utility methods for buffered * copying between sources ({@code InputStream}, {@code Reader}, * {@code String} and {@code byte[]}) and destinations * ({@code OutputStream}, {@code Writer}, {@code String} and * {@code byte[]}). *

* Unless otherwise noted, these {@code copy} methods do not * flush or close the streams. Often doing so would require making non-portable * assumptions about the streams' origin and further use. This means that both * streams' {@code close()} methods must be called after copying. if one * omits this step, then the stream resources (sockets, file descriptors) are * released when the associated Stream is garbage-collected. It is not a good * idea to rely on this mechanism. For a good overview of the distinction * between "memory management" and "resource management", see * this * UnixReview article. *

* For byte-to-char methods, a {@code copy} variant allows the encoding * to be selected (otherwise the platform default is used). We would like to * encourage you to always specify the encoding because relying on the platform * default can lead to unexpected results. *

* We don't provide special variants for the {@code copy} methods that * let you specify the buffer size because in modern VMs the impact on speed * seems to be minimal. We're using a default buffer size of 4 KB. *

* The {@code copy} methods use an internal buffer when copying. It is * therefore advisable not to deliberately wrap the stream arguments * to the {@code copy} methods in {@code Buffered*} streams. For * example, don't do the following: *

 *  copy( new BufferedInputStream( in ), new BufferedOutputStream( out ) );
 *  
* The rationale is as follows: *

* Imagine that an InputStream's read() is a very expensive operation, which * would usually suggest wrapping in a BufferedInputStream. The * BufferedInputStream works by issuing infrequent * {@link java.io.InputStream#read(byte[] b, int off, int len)} requests on the * underlying InputStream, to fill an internal buffer, from which further * {@code read} requests can inexpensively get their data (until the buffer * runs out). *

* However, the {@code copy} methods do the same thing, keeping an * internal buffer, populated by * {@link InputStream#read(byte[] b, int off, int len)} requests. Having two * buffers (or three if the destination stream is also buffered) is pointless, * and the unnecessary buffer management hurts performance slightly (about 3%, * according to some simple experiments). *

* Behold, intrepid explorers; a map of this class: *

 *       Method      Input               Output          Dependency
 *       ------      -----               ------          -------
 * 1     copy        InputStream         OutputStream    (primitive)
 * 2     copy        Reader              Writer          (primitive)
 *
 * 3     copy        InputStream         Writer          2
 *
 * 4     copy        Reader              OutputStream    2
 *
 * 5     copy        String              OutputStream    2
 * 6     copy        String              Writer          (trivial)
 *
 * 7     copy        byte[]              Writer          3
 * 8     copy        byte[]              OutputStream    (trivial)
 * 
*

* Note that only the first two methods shuffle bytes; the rest use these * two, or (if possible) copy using native Java copy methods. As there are * method variants to specify the encoding, each row may * correspond to up to 2 methods. *

* Origin of code: Excalibur. * * @deprecated Use IOUtils. Will be removed in 3.0. * Methods renamed to IOUtils.write() or IOUtils.copy(). * Null handling behavior changed in IOUtils (null data does not * throw NullPointerException). */ @Deprecated public class CopyUtils { /** * Instances should NOT be constructed in standard programming. */ public CopyUtils() { } /** * Copies bytes from a {@code byte[]} to an {@code OutputStream}. * @param input the byte array to read from * @param output the {@code OutputStream} to write to * @throws IOException In case of an I/O problem */ public static void copy(final byte[] input, final OutputStream output) throws IOException { output.write(input); } /** * Copies and convert bytes from a {@code byte[]} to chars on a * {@code Writer}. * The platform's default encoding is used for the byte-to-char conversion. * @param input the byte array to read from * @param output the {@code Writer} to write to * @throws IOException In case of an I/O problem * @deprecated 2.5 use {@link #copy(byte[], Writer, String)} instead */ @Deprecated public static void copy(final byte[] input, final Writer output) throws IOException { final ByteArrayInputStream inputStream = new ByteArrayInputStream(input); copy(inputStream, output); } /** * Copies and convert bytes from a {@code byte[]} to chars on a * {@code Writer}, using the specified encoding. * @param input the byte array to read from * @param output the {@code Writer} to write to * @param encoding The name of a supported character encoding. See the * IANA * Charset Registry for a list of valid encoding types. * @throws IOException In case of an I/O problem */ public static void copy(final byte[] input, final Writer output, final String encoding) throws IOException { final ByteArrayInputStream inputStream = new ByteArrayInputStream(input); copy(inputStream, output, encoding); } /** * Copies bytes from an {@code InputStream} to an * {@code OutputStream}. * @param input the {@code InputStream} to read from * @param output the {@code OutputStream} to write to * @return the number of bytes copied * @throws IOException In case of an I/O problem */ public static int copy(final InputStream input, final OutputStream output) throws IOException { final byte[] buffer = IOUtils.byteArray(); int count = 0; int n; while (EOF != (n = input.read(buffer))) { output.write(buffer, 0, n); count += n; } return count; } // ---------------------------------------------------------------- // Reader -> Writer // ---------------------------------------------------------------- /** * Copies chars from a {@code Reader} to a {@code Writer}. * @param input the {@code Reader} to read from * @param output the {@code Writer} to write to * @return the number of characters copied * @throws IOException In case of an I/O problem */ public static int copy( final Reader input, final Writer output) throws IOException { final char[] buffer = IOUtils.getCharArray(); int count = 0; int n; while (EOF != (n = input.read(buffer))) { output.write(buffer, 0, n); count += n; } return count; } // ---------------------------------------------------------------- // InputStream -> Writer // ---------------------------------------------------------------- /** * Copies and convert bytes from an {@code InputStream} to chars on a * {@code Writer}. * The platform's default encoding is used for the byte-to-char conversion. * @param input the {@code InputStream} to read from * @param output the {@code Writer} to write to * @throws IOException In case of an I/O problem * @deprecated 2.5 use {@link #copy(InputStream, Writer, String)} instead */ @Deprecated public static void copy( final InputStream input, final Writer output) throws IOException { // make explicit the dependency on the default encoding final InputStreamReader in = new InputStreamReader(input, Charset.defaultCharset()); copy(in, output); } /** * Copies and convert bytes from an {@code InputStream} to chars on a * {@code Writer}, using the specified encoding. * @param input the {@code InputStream} to read from * @param output the {@code Writer} to write to * @param encoding The name of a supported character encoding. See the * IANA * Charset Registry for a list of valid encoding types. * @throws IOException In case of an I/O problem */ public static void copy( final InputStream input, final Writer output, final String encoding) throws IOException { final InputStreamReader in = new InputStreamReader(input, encoding); copy(in, output); } // ---------------------------------------------------------------- // Reader -> OutputStream // ---------------------------------------------------------------- /** * Serialize chars from a {@code Reader} to bytes on an * {@code OutputStream}, and flush the {@code OutputStream}. * Uses the default platform encoding. * @param input the {@code Reader} to read from * @param output the {@code OutputStream} to write to * @throws IOException In case of an I/O problem * @deprecated 2.5 use {@link #copy(Reader, OutputStream, String)} instead */ @Deprecated public static void copy( final Reader input, final OutputStream output) throws IOException { // make explicit the dependency on the default encoding final OutputStreamWriter out = new OutputStreamWriter(output, Charset.defaultCharset()); copy(input, out); // XXX Unless anyone is planning on rewriting OutputStreamWriter, we // have to flush here. out.flush(); } /** * Serialize chars from a {@code Reader} to bytes on an * {@code OutputStream}, and flush the {@code OutputStream}. * @param input the {@code Reader} to read from * @param output the {@code OutputStream} to write to * @param encoding The name of a supported character encoding. See the * IANA * Charset Registry for a list of valid encoding types. * @throws IOException In case of an I/O problem * @since 2.5 */ public static void copy( final Reader input, final OutputStream output, final String encoding) throws IOException { final OutputStreamWriter out = new OutputStreamWriter(output, encoding); copy(input, out); // XXX Unless anyone is planning on rewriting OutputStreamWriter, we // have to flush here. out.flush(); } // ---------------------------------------------------------------- // String -> OutputStream // ---------------------------------------------------------------- /** * Serialize chars from a {@code String} to bytes on an * {@code OutputStream}, and * flush the {@code OutputStream}. * Uses the platform default encoding. * @param input the {@code String} to read from * @param output the {@code OutputStream} to write to * @throws IOException In case of an I/O problem * @deprecated 2.5 use {@link #copy(String, OutputStream, String)} instead */ @Deprecated public static void copy( final String input, final OutputStream output) throws IOException { final StringReader in = new StringReader(input); // make explicit the dependency on the default encoding final OutputStreamWriter out = new OutputStreamWriter(output, Charset.defaultCharset()); copy(in, out); // XXX Unless anyone is planning on rewriting OutputStreamWriter, we // have to flush here. out.flush(); } /** * Serialize chars from a {@code String} to bytes on an * {@code OutputStream}, and * flush the {@code OutputStream}. * @param input the {@code String} to read from * @param output the {@code OutputStream} to write to * @param encoding The name of a supported character encoding. See the * IANA * Charset Registry for a list of valid encoding types. * @throws IOException In case of an I/O problem * @since 2.5 */ public static void copy( final String input, final OutputStream output, final String encoding) throws IOException { final StringReader in = new StringReader(input); final OutputStreamWriter out = new OutputStreamWriter(output, encoding); copy(in, out); // XXX Unless anyone is planning on rewriting OutputStreamWriter, we // have to flush here. out.flush(); } // ---------------------------------------------------------------- // String -> Writer // ---------------------------------------------------------------- /** * Copies chars from a {@code String} to a {@code Writer}. * @param input the {@code String} to read from * @param output the {@code Writer} to write to * @throws IOException In case of an I/O problem */ public static void copy(final String input, final Writer output) throws IOException { output.write(input); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/DirectoryWalker.java0100644 0000000 0000000 00000064101 13612062727 027512 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import java.io.File; import java.io.FileFilter; import java.io.IOException; import java.nio.file.Files; import java.util.Collection; import java.util.Objects; import org.apache.commons.io.file.PathUtils; import org.apache.commons.io.filefilter.FileFilterUtils; import org.apache.commons.io.filefilter.IOFileFilter; import org.apache.commons.io.filefilter.TrueFileFilter; /** * Abstract class that walks through a directory hierarchy and provides subclasses with convenient hooks to add specific * behavior. *

* This class operates with a {@link FileFilter} and maximum depth to limit the files and directories visited. Commons * IO supplies many common filter implementations in the filefilter * package. *

*

* The following sections describe: *

* * *

1. Example Implementation

* * There are many possible extensions, for example, to delete all files and '.svn' directories, and return a list of * deleted files: * *
 * public class FileCleaner extends DirectoryWalker {
 *
 *     public FileCleaner() {
 *         super();
 *     }
 *
 *     public List clean(File startDirectory) {
 *         List results = new ArrayList();
 *         walk(startDirectory, results);
 *         return results;
 *     }
 *
 *     protected boolean handleDirectory(File directory, int depth, Collection results) {
 *         // delete svn directories and then skip
 *         if (".svn".equals(directory.getName())) {
 *             directory.delete();
 *             return false;
 *         } else {
 *             return true;
 *         }
 *
 *     }
 *
 *     protected void handleFile(File file, int depth, Collection results) {
 *         // delete file and add to list of deleted
 *         file.delete();
 *         results.add(file);
 *     }
 * }
 * 
* *

2. Filter Example

* *

* Choosing which directories and files to process can be a key aspect of using this class. This information can be * setup in three ways, via three different constructors. *

*

* The first option is to visit all directories and files. This is achieved via the no-args constructor. *

*

* The second constructor option is to supply a single {@link FileFilter} that describes the files and directories to * visit. Care must be taken with this option as the same filter is used for both directories and files. *

*

* For example, if you wanted all directories which are not hidden and files which end in ".txt": *

* *
 * public class FooDirectoryWalker extends DirectoryWalker {
 *     public FooDirectoryWalker(FileFilter filter) {
 *         super(filter, -1);
 *     }
 * }
 *
 * // Build up the filters and create the walker
 * // Create a filter for Non-hidden directories
 * IOFileFilter fooDirFilter = FileFilterUtils.andFileFilter(FileFilterUtils.directoryFileFilter,
 *     HiddenFileFilter.VISIBLE);
 *
 * // Create a filter for Files ending in ".txt"
 * IOFileFilter fooFileFilter = FileFilterUtils.andFileFilter(FileFilterUtils.fileFileFilter,
 *     FileFilterUtils.suffixFileFilter(".txt"));
 *
 * // Combine the directory and file filters using an OR condition
 * java.io.FileFilter fooFilter = FileFilterUtils.orFileFilter(fooDirFilter, fooFileFilter);
 *
 * // Use the filter to construct a DirectoryWalker implementation
 * FooDirectoryWalker walker = new FooDirectoryWalker(fooFilter);
 * 
*

* The third constructor option is to specify separate filters, one for directories and one for files. These are * combined internally to form the correct {@code FileFilter}, something which is very easy to get wrong when * attempted manually, particularly when trying to express constructs like 'any file in directories named docs'. *

*

* For example, if you wanted all directories which are not hidden and files which end in ".txt": *

* *
 *  public class FooDirectoryWalker extends DirectoryWalker {
 *    public FooDirectoryWalker(IOFileFilter dirFilter, IOFileFilter fileFilter) {
 *      super(dirFilter, fileFilter, -1);
 *    }
 *  }
 *
 *  // Use the filters to construct the walker
 *  FooDirectoryWalker walker = new FooDirectoryWalker(
 *    HiddenFileFilter.VISIBLE,
 *    FileFilterUtils.suffixFileFilter(".txt"),
 *  );
 * 
*

* This is much simpler than the previous example, and is why it is the preferred option for filtering. *

* *

3. Cancellation

* *

* The DirectoryWalker contains some of the logic required for cancel processing. Subclasses must complete the * implementation. *

*

* What {@code DirectoryWalker} does provide for cancellation is: *

*
    *
  • {@link CancelException} which can be thrown in any of the lifecycle methods to stop processing.
  • *
  • The {@code walk()} method traps thrown {@link CancelException} and calls the {@code handleCancelled()} * method, providing a place for custom cancel processing.
  • *
*

* Implementations need to provide: *

*
    *
  • The decision logic on whether to cancel processing or not.
  • *
  • Constructing and throwing a {@link CancelException}.
  • *
  • Custom cancel processing in the {@code handleCancelled()} method. *
*

* Two possible scenarios are envisaged for cancellation: *

* *

* The following sections provide example implementations for these two different scenarios. *

* *

3.1 External / Multi-threaded

* *

* This example provides a public {@code cancel()} method that can be called by another thread to stop the * processing. A typical example use-case would be a cancel button on a GUI. Calling this method sets a * volatile flag to ensure * it will work properly in a multi-threaded environment. The flag is returned by the {@code handleIsCancelled()} * method, which will cause the walk to stop immediately. The {@code handleCancelled()} method will be the next, * and last, callback method received once cancellation has occurred. *

* *
 * public class FooDirectoryWalker extends DirectoryWalker {
 *
 *     private volatile boolean cancelled = false;
 *
 *     public void cancel() {
 *         cancelled = true;
 *     }
 *
 *     protected boolean handleIsCancelled(File file, int depth, Collection results) {
 *         return cancelled;
 *     }
 *
 *     protected void handleCancelled(File startDirectory, Collection results, CancelException cancel) {
 *         // implement processing required when a cancellation occurs
 *     }
 * }
 * 
* *

3.2 Internal

* *

* This shows an example of how internal cancellation processing could be implemented. Note the decision logic * and throwing a {@link CancelException} could be implemented in any of the lifecycle methods. *

* *
 * public class BarDirectoryWalker extends DirectoryWalker {
 *
 *     protected boolean handleDirectory(File directory, int depth, Collection results) throws IOException {
 *         // cancel if hidden directory
 *         if (directory.isHidden()) {
 *             throw new CancelException(file, depth);
 *         }
 *         return true;
 *     }
 *
 *     protected void handleFile(File file, int depth, Collection results) throws IOException {
 *         // cancel if read-only file
 *         if (!file.canWrite()) {
 *             throw new CancelException(file, depth);
 *         }
 *         results.add(file);
 *     }
 *
 *     protected void handleCancelled(File startDirectory, Collection results, CancelException cancel) {
 *         // implement processing required when a cancellation occurs
 *     }
 * }
 * 
* * @param The result type, like {@link File}. * @since 1.3 * @deprecated Apache Commons IO no longer uses this class. Instead, use * {@link PathUtils#walk(java.nio.file.Path, org.apache.commons.io.file.PathFilter, int, boolean, java.nio.file.FileVisitOption...)} * or {@link Files#walkFileTree(java.nio.file.Path, java.util.Set, int, java.nio.file.FileVisitor)}, and * friends. */ @Deprecated public abstract class DirectoryWalker { /** * The file filter to use to filter files and directories. */ private final FileFilter filter; /** * The limit on the directory depth to walk. */ private final int depthLimit; /** * Construct an instance with no filtering and unlimited depth. */ protected DirectoryWalker() { this(null, -1); } /** * Constructs an instance with a filter and limit the depth navigated to. *

* The filter controls which files and directories will be navigated to as * part of the walk. The {@link FileFilterUtils} class is useful for combining * various filters together. A {@code null} filter means that no * filtering should occur and all files and directories will be visited. *

* * @param filter the filter to apply, null means visit all files * @param depthLimit controls how deep the hierarchy is * navigated to (less than 0 means unlimited) */ protected DirectoryWalker(final FileFilter filter, final int depthLimit) { this.filter = filter; this.depthLimit = depthLimit; } /** * Constructs an instance with a directory and a file filter and an optional * limit on the depth navigated to. *

* The filters control which files and directories will be navigated to as part * of the walk. This constructor uses {@link FileFilterUtils#makeDirectoryOnly(IOFileFilter)} * and {@link FileFilterUtils#makeFileOnly(IOFileFilter)} internally to combine the filters. * A {@code null} filter means that no filtering should occur. *

* * @param directoryFilter the filter to apply to directories, null means visit all directories * @param fileFilter the filter to apply to files, null means visit all files * @param depthLimit controls how deep the hierarchy is * navigated to (less than 0 means unlimited) */ protected DirectoryWalker(IOFileFilter directoryFilter, IOFileFilter fileFilter, final int depthLimit) { if (directoryFilter == null && fileFilter == null) { this.filter = null; } else { directoryFilter = directoryFilter != null ? directoryFilter : TrueFileFilter.TRUE; fileFilter = fileFilter != null ? fileFilter : TrueFileFilter.TRUE; directoryFilter = FileFilterUtils.makeDirectoryOnly(directoryFilter); fileFilter = FileFilterUtils.makeFileOnly(fileFilter); this.filter = directoryFilter.or(fileFilter); } this.depthLimit = depthLimit; } /** * Internal method that walks the directory hierarchy in a depth-first manner. *

* Users of this class do not need to call this method. This method will * be called automatically by another (public) method on the specific subclass. *

*

* Writers of subclasses should call this method to start the directory walk. * Once called, this method will emit events as it walks the hierarchy. * The event methods have the prefix {@code handle}. *

* * @param startDirectory the directory to start from, not null * @param results the collection of result objects, may be updated * @throws NullPointerException if the start directory is null * @throws IOException if an I/O Error occurs */ protected final void walk(final File startDirectory, final Collection results) throws IOException { Objects.requireNonNull(startDirectory, "startDirectory"); try { handleStart(startDirectory, results); walk(startDirectory, 0, results); handleEnd(results); } catch(final CancelException cancel) { handleCancelled(startDirectory, results, cancel); } } /** * Main recursive method to examine the directory hierarchy. * * @param directory the directory to examine, not null * @param depth the directory level (starting directory = 0) * @param results the collection of result objects, may be updated * @throws IOException if an I/O Error occurs */ private void walk(final File directory, final int depth, final Collection results) throws IOException { checkIfCancelled(directory, depth, results); if (handleDirectory(directory, depth, results)) { handleDirectoryStart(directory, depth, results); final int childDepth = depth + 1; if (depthLimit < 0 || childDepth <= depthLimit) { checkIfCancelled(directory, depth, results); File[] childFiles = filter == null ? directory.listFiles() : directory.listFiles(filter); childFiles = filterDirectoryContents(directory, depth, childFiles); if (childFiles == null) { handleRestricted(directory, childDepth, results); } else { for (final File childFile : childFiles) { if (childFile.isDirectory()) { walk(childFile, childDepth, results); } else { checkIfCancelled(childFile, childDepth, results); handleFile(childFile, childDepth, results); checkIfCancelled(childFile, childDepth, results); } } } } handleDirectoryEnd(directory, depth, results); } checkIfCancelled(directory, depth, results); } /** * Checks whether the walk has been cancelled by calling {@link #handleIsCancelled}, * throwing a {@code CancelException} if it has. *

* Writers of subclasses should not normally call this method as it is called * automatically by the walk of the tree. However, sometimes a single method, * typically {@link #handleFile}, may take a long time to run. In that case, * you may wish to check for cancellation by calling this method. *

* * @param file the current file being processed * @param depth the current file level (starting directory = 0) * @param results the collection of result objects, may be updated * @throws IOException if an I/O Error occurs */ protected final void checkIfCancelled(final File file, final int depth, final Collection results) throws IOException { if (handleIsCancelled(file, depth, results)) { throw new CancelException(file, depth); } } /** * Overridable callback method invoked to determine if the entire walk * operation should be immediately cancelled. *

* This method should be implemented by those subclasses that want to * provide a public {@code cancel()} method available from another * thread. The design pattern for the subclass should be as follows: *

*
     *  public class FooDirectoryWalker extends DirectoryWalker {
     *    private volatile boolean cancelled = false;
     *
     *    public void cancel() {
     *        cancelled = true;
     *    }
     *    private void handleIsCancelled(File file, int depth, Collection results) {
     *        return cancelled;
     *    }
     *    protected void handleCancelled(File startDirectory,
     *              Collection results, CancelException cancel) {
     *        // implement processing required when a cancellation occurs
     *    }
     *  }
     * 
*

* If this method returns true, then the directory walk is immediately * cancelled. The next callback method will be {@link #handleCancelled}. *

*

* This implementation returns false. *

* * @param file the file or directory being processed * @param depth the current directory level (starting directory = 0) * @param results the collection of result objects, may be updated * @return true if the walk has been cancelled * @throws IOException if an I/O Error occurs */ @SuppressWarnings("unused") // Possibly thrown from subclasses. protected boolean handleIsCancelled( final File file, final int depth, final Collection results) throws IOException { // do nothing - overridable by subclass return false; // not cancelled } /** * Overridable callback method invoked when the operation is cancelled. * The file being processed when the cancellation occurred can be * obtained from the exception. *

* This implementation just re-throws the {@link CancelException}. *

* * @param startDirectory the directory that the walk started from * @param results the collection of result objects, may be updated * @param cancel the exception throw to cancel further processing * containing details at the point of cancellation. * @throws IOException if an I/O Error occurs */ protected void handleCancelled(final File startDirectory, final Collection results, final CancelException cancel) throws IOException { // re-throw exception - overridable by subclass throw cancel; } /** * Overridable callback method invoked at the start of processing. *

* This implementation does nothing. *

* * @param startDirectory the directory to start from * @param results the collection of result objects, may be updated * @throws IOException if an I/O Error occurs */ @SuppressWarnings("unused") // Possibly thrown from subclasses. protected void handleStart(final File startDirectory, final Collection results) throws IOException { // do nothing - overridable by subclass } /** * Overridable callback method invoked to determine if a directory should be processed. *

* This method returns a boolean to indicate if the directory should be examined or not. * If you return false, the entire directory and any subdirectories will be skipped. * Note that this functionality is in addition to the filtering by file filter. *

*

* This implementation does nothing and returns true. *

* * @param directory the current directory being processed * @param depth the current directory level (starting directory = 0) * @param results the collection of result objects, may be updated * @return true to process this directory, false to skip this directory * @throws IOException if an I/O Error occurs */ @SuppressWarnings("unused") // Possibly thrown from subclasses. protected boolean handleDirectory(final File directory, final int depth, final Collection results) throws IOException { // do nothing - overridable by subclass return true; // process directory } /** * Overridable callback method invoked at the start of processing each directory. *

* This implementation does nothing. *

* * @param directory the current directory being processed * @param depth the current directory level (starting directory = 0) * @param results the collection of result objects, may be updated * @throws IOException if an I/O Error occurs */ @SuppressWarnings("unused") // Possibly thrown from subclasses. protected void handleDirectoryStart(final File directory, final int depth, final Collection results) throws IOException { // do nothing - overridable by subclass } /** * Overridable callback method invoked with the contents of each directory. *

* This implementation returns the files unchanged *

* * @param directory the current directory being processed * @param depth the current directory level (starting directory = 0) * @param files the files (possibly filtered) in the directory, may be {@code null} * @return the filtered list of files * @throws IOException if an I/O Error occurs * @since 2.0 */ @SuppressWarnings("unused") // Possibly thrown from subclasses. protected File[] filterDirectoryContents(final File directory, final int depth, final File... files) throws IOException { return files; } /** * Overridable callback method invoked for each (non-directory) file. *

* This implementation does nothing. *

* * @param file the current file being processed * @param depth the current directory level (starting directory = 0) * @param results the collection of result objects, may be updated * @throws IOException if an I/O Error occurs */ @SuppressWarnings("unused") // Possibly thrown from subclasses. protected void handleFile(final File file, final int depth, final Collection results) throws IOException { // do nothing - overridable by subclass } /** * Overridable callback method invoked for each restricted directory. *

* This implementation does nothing. *

* * @param directory the restricted directory * @param depth the current directory level (starting directory = 0) * @param results the collection of result objects, may be updated * @throws IOException if an I/O Error occurs */ @SuppressWarnings("unused") // Possibly thrown from subclasses. protected void handleRestricted(final File directory, final int depth, final Collection results) throws IOException { // do nothing - overridable by subclass } /** * Overridable callback method invoked at the end of processing each directory. *

* This implementation does nothing. *

* * @param directory the directory being processed * @param depth the current directory level (starting directory = 0) * @param results the collection of result objects, may be updated * @throws IOException if an I/O Error occurs */ @SuppressWarnings("unused") // Possibly thrown from subclasses. protected void handleDirectoryEnd(final File directory, final int depth, final Collection results) throws IOException { // do nothing - overridable by subclass } /** * Overridable callback method invoked at the end of processing. *

* This implementation does nothing. *

* * @param results the collection of result objects, may be updated * @throws IOException if an I/O Error occurs */ @SuppressWarnings("unused") // Possibly thrown from subclasses. protected void handleEnd(final Collection results) throws IOException { // do nothing - overridable by subclass } /** * CancelException is thrown in DirectoryWalker to cancel the current * processing. */ public static class CancelException extends IOException { /** Serialization id. */ private static final long serialVersionUID = 1347339620135041008L; /** The file being processed when the exception was thrown. */ private final File file; /** The file depth when the exception was thrown. */ private final int depth; /** * Constructs a {@code CancelException} with * the file and depth when cancellation occurred. * * @param file the file when the operation was cancelled, may be null * @param depth the depth when the operation was cancelled, may be null */ public CancelException(final File file, final int depth) { this("Operation Cancelled", file, depth); } /** * Constructs a {@code CancelException} with * an appropriate message and the file and depth when * cancellation occurred. * * @param message the detail message * @param file the file when the operation was cancelled * @param depth the depth when the operation was cancelled */ public CancelException(final String message, final File file, final int depth) { super(message); this.file = file; this.depth = depth; } /** * Returns the file when the operation was cancelled. * * @return the file when the operation was cancelled */ public File getFile() { return file; } /** * Returns the depth when the operation was cancelled. * * @return the depth when the operation was cancelled */ public int getDepth() { return depth; } } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/EndianUtils.java0100644 0000000 0000000 00000041755 13612062727 026631 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import static org.apache.commons.io.IOUtils.EOF; import java.io.EOFException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; /** * Utility code for dealing with different endian systems. *

* Different computer architectures adopt different conventions for * byte ordering. In so-called "Little Endian" architectures (eg Intel), * the low-order byte is stored in memory at the lowest address, and * subsequent bytes at higher addresses. For "Big Endian" architectures * (eg Motorola), the situation is reversed. * This class helps you solve this incompatibility. *

* Origin of code: Excalibur * * @see org.apache.commons.io.input.SwappedDataInputStream */ public class EndianUtils { /** * Instances should NOT be constructed in standard programming. */ public EndianUtils() { } // ========================================== Swapping routines /** * Converts a "short" value between endian systems. * @param value value to convert * @return the converted value */ public static short swapShort(final short value) { return (short) ( ( ( ( value >> 0 ) & 0xff ) << 8 ) + ( ( ( value >> 8 ) & 0xff ) << 0 ) ); } /** * Converts a "int" value between endian systems. * @param value value to convert * @return the converted value */ public static int swapInteger(final int value) { return ( ( ( value >> 0 ) & 0xff ) << 24 ) + ( ( ( value >> 8 ) & 0xff ) << 16 ) + ( ( ( value >> 16 ) & 0xff ) << 8 ) + ( ( ( value >> 24 ) & 0xff ) << 0 ); } /** * Converts a "long" value between endian systems. * @param value value to convert * @return the converted value */ public static long swapLong(final long value) { return ( ( ( value >> 0 ) & 0xff ) << 56 ) + ( ( ( value >> 8 ) & 0xff ) << 48 ) + ( ( ( value >> 16 ) & 0xff ) << 40 ) + ( ( ( value >> 24 ) & 0xff ) << 32 ) + ( ( ( value >> 32 ) & 0xff ) << 24 ) + ( ( ( value >> 40 ) & 0xff ) << 16 ) + ( ( ( value >> 48 ) & 0xff ) << 8 ) + ( ( ( value >> 56 ) & 0xff ) << 0 ); } /** * Converts a "float" value between endian systems. * @param value value to convert * @return the converted value */ public static float swapFloat(final float value) { return Float.intBitsToFloat( swapInteger( Float.floatToIntBits( value ) ) ); } /** * Converts a "double" value between endian systems. * @param value value to convert * @return the converted value */ public static double swapDouble(final double value) { return Double.longBitsToDouble( swapLong( Double.doubleToLongBits( value ) ) ); } // ========================================== Swapping read/write routines /** * Writes a "short" value to a byte array at a given offset. The value is * converted to the opposed endian system while writing. * @param data target byte array * @param offset starting offset in the byte array * @param value value to write */ public static void writeSwappedShort(final byte[] data, final int offset, final short value) { data[ offset + 0 ] = (byte)( ( value >> 0 ) & 0xff ); data[ offset + 1 ] = (byte)( ( value >> 8 ) & 0xff ); } /** * Reads a "short" value from a byte array at a given offset. The value is * converted to the opposed endian system while reading. * @param data source byte array * @param offset starting offset in the byte array * @return the value read */ public static short readSwappedShort(final byte[] data, final int offset) { return (short)( ( ( data[ offset + 0 ] & 0xff ) << 0 ) + ( ( data[ offset + 1 ] & 0xff ) << 8 ) ); } /** * Reads an unsigned short (16-bit) value from a byte array at a given * offset. The value is converted to the opposed endian system while * reading. * @param data source byte array * @param offset starting offset in the byte array * @return the value read */ public static int readSwappedUnsignedShort(final byte[] data, final int offset) { return ( ( ( data[ offset + 0 ] & 0xff ) << 0 ) + ( ( data[ offset + 1 ] & 0xff ) << 8 ) ); } /** * Writes a "int" value to a byte array at a given offset. The value is * converted to the opposed endian system while writing. * @param data target byte array * @param offset starting offset in the byte array * @param value value to write */ public static void writeSwappedInteger(final byte[] data, final int offset, final int value) { data[ offset + 0 ] = (byte)( ( value >> 0 ) & 0xff ); data[ offset + 1 ] = (byte)( ( value >> 8 ) & 0xff ); data[ offset + 2 ] = (byte)( ( value >> 16 ) & 0xff ); data[ offset + 3 ] = (byte)( ( value >> 24 ) & 0xff ); } /** * Reads a "int" value from a byte array at a given offset. The value is * converted to the opposed endian system while reading. * @param data source byte array * @param offset starting offset in the byte array * @return the value read */ public static int readSwappedInteger(final byte[] data, final int offset) { return ( ( ( data[ offset + 0 ] & 0xff ) << 0 ) + ( ( data[ offset + 1 ] & 0xff ) << 8 ) + ( ( data[ offset + 2 ] & 0xff ) << 16 ) + ( ( data[ offset + 3 ] & 0xff ) << 24 ) ); } /** * Reads an unsigned integer (32-bit) value from a byte array at a given * offset. The value is converted to the opposed endian system while * reading. * @param data source byte array * @param offset starting offset in the byte array * @return the value read */ public static long readSwappedUnsignedInteger(final byte[] data, final int offset) { final long low = ( ( ( data[ offset + 0 ] & 0xff ) << 0 ) + ( ( data[ offset + 1 ] & 0xff ) << 8 ) + ( ( data[ offset + 2 ] & 0xff ) << 16 ) ); final long high = data[ offset + 3 ] & 0xff; return (high << 24) + (0xffffffffL & low); } /** * Writes a "long" value to a byte array at a given offset. The value is * converted to the opposed endian system while writing. * @param data target byte array * @param offset starting offset in the byte array * @param value value to write */ public static void writeSwappedLong(final byte[] data, final int offset, final long value) { data[ offset + 0 ] = (byte)( ( value >> 0 ) & 0xff ); data[ offset + 1 ] = (byte)( ( value >> 8 ) & 0xff ); data[ offset + 2 ] = (byte)( ( value >> 16 ) & 0xff ); data[ offset + 3 ] = (byte)( ( value >> 24 ) & 0xff ); data[ offset + 4 ] = (byte)( ( value >> 32 ) & 0xff ); data[ offset + 5 ] = (byte)( ( value >> 40 ) & 0xff ); data[ offset + 6 ] = (byte)( ( value >> 48 ) & 0xff ); data[ offset + 7 ] = (byte)( ( value >> 56 ) & 0xff ); } /** * Reads a "long" value from a byte array at a given offset. The value is * converted to the opposed endian system while reading. * @param data source byte array * @param offset starting offset in the byte array * @return the value read */ public static long readSwappedLong(final byte[] data, final int offset) { final long low = readSwappedInteger(data, offset); final long high = readSwappedInteger(data, offset + 4); return (high << 32) + (0xffffffffL & low); } /** * Writes a "float" value to a byte array at a given offset. The value is * converted to the opposed endian system while writing. * @param data target byte array * @param offset starting offset in the byte array * @param value value to write */ public static void writeSwappedFloat(final byte[] data, final int offset, final float value) { writeSwappedInteger( data, offset, Float.floatToIntBits( value ) ); } /** * Reads a "float" value from a byte array at a given offset. The value is * converted to the opposed endian system while reading. * @param data source byte array * @param offset starting offset in the byte array * @return the value read */ public static float readSwappedFloat(final byte[] data, final int offset) { return Float.intBitsToFloat( readSwappedInteger( data, offset ) ); } /** * Writes a "double" value to a byte array at a given offset. The value is * converted to the opposed endian system while writing. * @param data target byte array * @param offset starting offset in the byte array * @param value value to write */ public static void writeSwappedDouble(final byte[] data, final int offset, final double value) { writeSwappedLong( data, offset, Double.doubleToLongBits( value ) ); } /** * Reads a "double" value from a byte array at a given offset. The value is * converted to the opposed endian system while reading. * @param data source byte array * @param offset starting offset in the byte array * @return the value read */ public static double readSwappedDouble(final byte[] data, final int offset) { return Double.longBitsToDouble( readSwappedLong( data, offset ) ); } /** * Writes a "short" value to an OutputStream. The value is * converted to the opposed endian system while writing. * @param output target OutputStream * @param value value to write * @throws IOException in case of an I/O problem */ public static void writeSwappedShort(final OutputStream output, final short value) throws IOException { output.write((byte) ((value >> 0) & 0xff)); output.write((byte) ((value >> 8) & 0xff)); } /** * Reads a "short" value from an InputStream. The value is * converted to the opposed endian system while reading. * @param input source InputStream * @return the value just read * @throws IOException in case of an I/O problem */ public static short readSwappedShort(final InputStream input) throws IOException { return (short) (((read(input) & 0xff) << 0) + ((read(input) & 0xff) << 8)); } /** * Reads a unsigned short (16-bit) from an InputStream. The value is * converted to the opposed endian system while reading. * @param input source InputStream * @return the value just read * @throws IOException in case of an I/O problem */ public static int readSwappedUnsignedShort(final InputStream input) throws IOException { final int value1 = read(input); final int value2 = read(input); return (((value1 & 0xff) << 0) + ((value2 & 0xff) << 8)); } /** * Writes a "int" value to an OutputStream. The value is converted to the opposed endian system while writing. * * @param output target OutputStream * @param value value to write * @throws IOException in case of an I/O problem */ public static void writeSwappedInteger(final OutputStream output, final int value) throws IOException { output.write((byte) ((value >> 0) & 0xff)); output.write((byte) ((value >> 8) & 0xff)); output.write((byte) ((value >> 16) & 0xff)); output.write((byte) ((value >> 24) & 0xff)); } /** * Reads a "int" value from an InputStream. The value is * converted to the opposed endian system while reading. * @param input source InputStream * @return the value just read * @throws IOException in case of an I/O problem */ public static int readSwappedInteger(final InputStream input) throws IOException { final int value1 = read(input); final int value2 = read(input); final int value3 = read(input); final int value4 = read(input); return ((value1 & 0xff) << 0) + ((value2 & 0xff) << 8) + ((value3 & 0xff) << 16) + ((value4 & 0xff) << 24); } /** * Reads a unsigned integer (32-bit) from an InputStream. The value is * converted to the opposed endian system while reading. * @param input source InputStream * @return the value just read * @throws IOException in case of an I/O problem */ public static long readSwappedUnsignedInteger(final InputStream input) throws IOException { final int value1 = read(input); final int value2 = read(input); final int value3 = read(input); final int value4 = read(input); final long low = (((value1 & 0xff) << 0) + ((value2 & 0xff) << 8) + ((value3 & 0xff) << 16)); final long high = value4 & 0xff; return (high << 24) + (0xffffffffL & low); } /** * Writes a "long" value to an OutputStream. The value is * converted to the opposed endian system while writing. * @param output target OutputStream * @param value value to write * @throws IOException in case of an I/O problem */ public static void writeSwappedLong(final OutputStream output, final long value) throws IOException { output.write((byte) ((value >> 0) & 0xff)); output.write((byte) ((value >> 8) & 0xff)); output.write((byte) ((value >> 16) & 0xff)); output.write((byte) ((value >> 24) & 0xff)); output.write((byte) ((value >> 32) & 0xff)); output.write((byte) ((value >> 40) & 0xff)); output.write((byte) ((value >> 48) & 0xff)); output.write((byte) ((value >> 56) & 0xff)); } /** * Reads a "long" value from an InputStream. The value is * converted to the opposed endian system while reading. * @param input source InputStream * @return the value just read * @throws IOException in case of an I/O problem */ public static long readSwappedLong(final InputStream input) throws IOException { final byte[] bytes = new byte[8]; for (int i = 0; i < 8; i++) { bytes[i] = (byte) read(input); } return readSwappedLong(bytes, 0); } /** * Writes a "float" value to an OutputStream. The value is * converted to the opposed endian system while writing. * @param output target OutputStream * @param value value to write * @throws IOException in case of an I/O problem */ public static void writeSwappedFloat(final OutputStream output, final float value) throws IOException { writeSwappedInteger(output, Float.floatToIntBits(value)); } /** * Reads a "float" value from an InputStream. The value is * converted to the opposed endian system while reading. * @param input source InputStream * @return the value just read * @throws IOException in case of an I/O problem */ public static float readSwappedFloat(final InputStream input) throws IOException { return Float.intBitsToFloat(readSwappedInteger(input)); } /** * Writes a "double" value to an OutputStream. The value is * converted to the opposed endian system while writing. * @param output target OutputStream * @param value value to write * @throws IOException in case of an I/O problem */ public static void writeSwappedDouble(final OutputStream output, final double value) throws IOException { writeSwappedLong(output, Double.doubleToLongBits(value)); } /** * Reads a "double" value from an InputStream. The value is * converted to the opposed endian system while reading. * @param input source InputStream * @return the value just read * @throws IOException in case of an I/O problem */ public static double readSwappedDouble(final InputStream input) throws IOException { return Double.longBitsToDouble(readSwappedLong(input)); } /** * Reads the next byte from the input stream. * @param input the stream * @return the byte * @throws IOException if the end of file is reached */ private static int read(final InputStream input) throws IOException { final int value = input.read(); if (EOF == value) { throw new EOFException("Unexpected EOF reached"); } return value; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/FileCleaner.java0100644 0000000 0000000 00000015357 13612062727 026562 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import java.io.File; /** * Keeps track of files awaiting deletion, and deletes them when an associated * marker object is reclaimed by the garbage collector. *

* This utility creates a background thread to handle file deletion. * Each file to be deleted is registered with a handler object. * When the handler object is garbage collected, the file is deleted. *

* In an environment with multiple class loaders (a servlet container, for * example), you should consider stopping the background thread if it is no * longer needed. This is done by invoking the method * {@link #exitWhenFinished}, typically in * {@code javax.servlet.ServletContextListener.contextDestroyed(javax.servlet.ServletContextEvent)} or similar. * * @deprecated Use {@link FileCleaningTracker} */ @Deprecated public class FileCleaner { /** * The instance to use for the deprecated, static methods. */ static final FileCleaningTracker theInstance = new FileCleaningTracker(); /** * Track the specified file, using the provided marker, deleting the file * when the marker instance is garbage collected. * The {@link FileDeleteStrategy#NORMAL normal} deletion strategy will be used. * * @param file the file to be tracked, not null * @param marker the marker object used to track the file, not null * @throws NullPointerException if the file is null * @deprecated Use {@link FileCleaningTracker#track(File, Object)}. */ @Deprecated public static void track(final File file, final Object marker) { theInstance.track(file, marker); } /** * Track the specified file, using the provided marker, deleting the file * when the marker instance is garbage collected. * The specified deletion strategy is used. * * @param file the file to be tracked, not null * @param marker the marker object used to track the file, not null * @param deleteStrategy the strategy to delete the file, null means normal * @throws NullPointerException if the file is null * @deprecated Use {@link FileCleaningTracker#track(File, Object, FileDeleteStrategy)}. */ @Deprecated public static void track(final File file, final Object marker, final FileDeleteStrategy deleteStrategy) { theInstance.track(file, marker, deleteStrategy); } /** * Track the specified file, using the provided marker, deleting the file * when the marker instance is garbage collected. * The {@link FileDeleteStrategy#NORMAL normal} deletion strategy will be used. * * @param path the full path to the file to be tracked, not null * @param marker the marker object used to track the file, not null * @throws NullPointerException if the path is null * @deprecated Use {@link FileCleaningTracker#track(String, Object)}. */ @Deprecated public static void track(final String path, final Object marker) { theInstance.track(path, marker); } /** * Track the specified file, using the provided marker, deleting the file * when the marker instance is garbage collected. * The specified deletion strategy is used. * * @param path the full path to the file to be tracked, not null * @param marker the marker object used to track the file, not null * @param deleteStrategy the strategy to delete the file, null means normal * @throws NullPointerException if the path is null * @deprecated Use {@link FileCleaningTracker#track(String, Object, FileDeleteStrategy)}. */ @Deprecated public static void track(final String path, final Object marker, final FileDeleteStrategy deleteStrategy) { theInstance.track(path, marker, deleteStrategy); } /** * Retrieve the number of files currently being tracked, and therefore * awaiting deletion. * * @return the number of files being tracked * @deprecated Use {@link FileCleaningTracker#getTrackCount()}. */ @Deprecated public static int getTrackCount() { return theInstance.getTrackCount(); } /** * Call this method to cause the file cleaner thread to terminate when * there are no more objects being tracked for deletion. *

* In a simple environment, you don't need this method as the file cleaner * thread will simply exit when the JVM exits. In a more complex environment, * with multiple class loaders (such as an application server), you should be * aware that the file cleaner thread will continue running even if the class * loader it was started from terminates. This can constitute a memory leak. *

* For example, suppose that you have developed a web application, which * contains the commons-io jar file in your WEB-INF/lib directory. In other * words, the FileCleaner class is loaded through the class loader of your * web application. If the web application is terminated, but the servlet * container is still running, then the file cleaner thread will still exist, * posing a memory leak. *

* This method allows the thread to be terminated. Simply call this method * in the resource cleanup code, such as * {@code javax.servlet.ServletContextListener.contextDestroyed(javax.servlet.ServletContextEvent)}. * One called, no new objects can be tracked by the file cleaner. * @deprecated Use {@link FileCleaningTracker#exitWhenFinished()}. */ @Deprecated public static synchronized void exitWhenFinished() { theInstance.exitWhenFinished(); } /** * Returns the singleton instance, which is used by the deprecated, static methods. * This is mainly useful for code, which wants to support the new * {@link FileCleaningTracker} class while maintain compatibility with the * deprecated {@link FileCleaner}. * * @return the singleton instance */ public static FileCleaningTracker getInstance() { return theInstance; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/FileCleaningTracker.java0100644 0000000 0000000 00000024750 13612062727 030242 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import java.io.File; import java.lang.ref.PhantomReference; import java.lang.ref.ReferenceQueue; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Objects; /** * Keeps track of files awaiting deletion, and deletes them when an associated * marker object is reclaimed by the garbage collector. *

* This utility creates a background thread to handle file deletion. * Each file to be deleted is registered with a handler object. * When the handler object is garbage collected, the file is deleted. *

* In an environment with multiple class loaders (a servlet container, for * example), you should consider stopping the background thread if it is no * longer needed. This is done by invoking the method * {@link #exitWhenFinished}, typically in * {@code javax.servlet.ServletContextListener.contextDestroyed(javax.servlet.ServletContextEvent)} or similar. * */ public class FileCleaningTracker { // Note: fields are package protected to allow use by test cases /** * Queue of {@code Tracker} instances being watched. */ ReferenceQueue q = new ReferenceQueue<>(); /** * Collection of {@code Tracker} instances in existence. */ final Collection trackers = Collections.synchronizedSet(new HashSet<>()); // synchronized /** * Collection of File paths that failed to delete. */ final List deleteFailures = Collections.synchronizedList(new ArrayList<>()); /** * Whether to terminate the thread when the tracking is complete. */ volatile boolean exitWhenFinished; /** * The thread that will clean up registered files. */ Thread reaper; /** * Track the specified file, using the provided marker, deleting the file * when the marker instance is garbage collected. * The {@link FileDeleteStrategy#NORMAL normal} deletion strategy will be used. * * @param file the file to be tracked, not null * @param marker the marker object used to track the file, not null * @throws NullPointerException if the file is null */ public void track(final File file, final Object marker) { track(file, marker, null); } /** * Track the specified file, using the provided marker, deleting the file * when the marker instance is garbage collected. * The specified deletion strategy is used. * * @param file the file to be tracked, not null * @param marker the marker object used to track the file, not null * @param deleteStrategy the strategy to delete the file, null means normal * @throws NullPointerException if the file is null */ public void track(final File file, final Object marker, final FileDeleteStrategy deleteStrategy) { Objects.requireNonNull(file, "file"); addTracker(file.getPath(), marker, deleteStrategy); } /** * Track the specified file, using the provided marker, deleting the file * when the marker instance is garbage collected. * The {@link FileDeleteStrategy#NORMAL normal} deletion strategy will be used. * * @param path the full path to the file to be tracked, not null * @param marker the marker object used to track the file, not null * @throws NullPointerException if the path is null */ public void track(final String path, final Object marker) { track(path, marker, null); } /** * Track the specified file, using the provided marker, deleting the file * when the marker instance is garbage collected. * The specified deletion strategy is used. * * @param path the full path to the file to be tracked, not null * @param marker the marker object used to track the file, not null * @param deleteStrategy the strategy to delete the file, null means normal * @throws NullPointerException if the path is null */ public void track(final String path, final Object marker, final FileDeleteStrategy deleteStrategy) { Objects.requireNonNull(path, "path"); addTracker(path, marker, deleteStrategy); } /** * Adds a tracker to the list of trackers. * * @param path the full path to the file to be tracked, not null * @param marker the marker object used to track the file, not null * @param deleteStrategy the strategy to delete the file, null means normal */ private synchronized void addTracker(final String path, final Object marker, final FileDeleteStrategy deleteStrategy) { // synchronized block protects reaper if (exitWhenFinished) { throw new IllegalStateException("No new trackers can be added once exitWhenFinished() is called"); } if (reaper == null) { reaper = new Reaper(); reaper.start(); } trackers.add(new Tracker(path, deleteStrategy, marker, q)); } /** * Retrieve the number of files currently being tracked, and therefore * awaiting deletion. * * @return the number of files being tracked */ public int getTrackCount() { return trackers.size(); } /** * Return the file paths that failed to delete. * * @return the file paths that failed to delete * @since 2.0 */ public List getDeleteFailures() { return deleteFailures; } /** * Call this method to cause the file cleaner thread to terminate when * there are no more objects being tracked for deletion. *

* In a simple environment, you don't need this method as the file cleaner * thread will simply exit when the JVM exits. In a more complex environment, * with multiple class loaders (such as an application server), you should be * aware that the file cleaner thread will continue running even if the class * loader it was started from terminates. This can constitute a memory leak. *

* For example, suppose that you have developed a web application, which * contains the commons-io jar file in your WEB-INF/lib directory. In other * words, the FileCleaner class is loaded through the class loader of your * web application. If the web application is terminated, but the servlet * container is still running, then the file cleaner thread will still exist, * posing a memory leak. *

* This method allows the thread to be terminated. Simply call this method * in the resource cleanup code, such as * {@code javax.servlet.ServletContextListener.contextDestroyed(javax.servlet.ServletContextEvent)}. * Once called, no new objects can be tracked by the file cleaner. */ public synchronized void exitWhenFinished() { // synchronized block protects reaper exitWhenFinished = true; if (reaper != null) { synchronized (reaper) { reaper.interrupt(); } } } /** * The reaper thread. */ private final class Reaper extends Thread { /** Construct a new Reaper */ Reaper() { super("File Reaper"); setPriority(Thread.MAX_PRIORITY); setDaemon(true); } /** * Run the reaper thread that will delete files as their associated * marker objects are reclaimed by the garbage collector. */ @Override public void run() { // thread exits when exitWhenFinished is true and there are no more tracked objects while (!exitWhenFinished || !trackers.isEmpty()) { try { // Wait for a tracker to remove. final Tracker tracker = (Tracker) q.remove(); // cannot return null trackers.remove(tracker); if (!tracker.delete()) { deleteFailures.add(tracker.getPath()); } tracker.clear(); } catch (final InterruptedException e) { continue; } } } } /** * Inner class which acts as the reference for a file pending deletion. */ private static final class Tracker extends PhantomReference { /** * The full path to the file being tracked. */ private final String path; /** * The strategy for deleting files. */ private final FileDeleteStrategy deleteStrategy; /** * Constructs an instance of this class from the supplied parameters. * * @param path the full path to the file to be tracked, not null * @param deleteStrategy the strategy to delete the file, null means normal * @param marker the marker object used to track the file, not null * @param queue the queue on to which the tracker will be pushed, not null */ Tracker(final String path, final FileDeleteStrategy deleteStrategy, final Object marker, final ReferenceQueue queue) { super(marker, queue); this.path = path; this.deleteStrategy = deleteStrategy == null ? FileDeleteStrategy.NORMAL : deleteStrategy; } /** * Return the path. * * @return the path */ public String getPath() { return path; } /** * Deletes the file associated with this tracker instance. * * @return {@code true} if the file was deleted successfully; * {@code false} otherwise. */ public boolean delete() { return deleteStrategy.deleteQuietly(new File(path)); } } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/FileDeleteStrategy.java0100644 0000000 0000000 00000012500 13612062727 030121 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import java.io.File; import java.io.IOException; /** * Strategy for deleting files. *

* There is more than one way to delete a file. * You may want to limit access to certain directories, to only delete * directories if they are empty, or maybe to force deletion. *

*

* This class captures the strategy to use and is designed for user subclassing. *

* * @since 1.3 */ public class FileDeleteStrategy { /** * Force file deletion strategy. */ static class ForceFileDeleteStrategy extends FileDeleteStrategy { /** Default Constructor */ ForceFileDeleteStrategy() { super("Force"); } /** * Deletes the file object. *

* This implementation uses {@code FileUtils.forceDelete()} * if the file exists. *

* * @param fileToDelete the file to delete, not null * @return Always returns {@code true} * @throws NullPointerException if the file is null * @throws IOException if an error occurs during file deletion */ @Override protected boolean doDelete(final File fileToDelete) throws IOException { FileUtils.forceDelete(fileToDelete); return true; } } /** * The singleton instance for normal file deletion, which does not permit * the deletion of directories that are not empty. */ public static final FileDeleteStrategy NORMAL = new FileDeleteStrategy("Normal"); /** * The singleton instance for forced file deletion, which always deletes, * even if the file represents a non-empty directory. */ public static final FileDeleteStrategy FORCE = new ForceFileDeleteStrategy(); /** The name of the strategy. */ private final String name; /** * Restricted constructor. * * @param name the name by which the strategy is known */ protected FileDeleteStrategy(final String name) { this.name = name; } /** * Deletes the file object, which may be a file or a directory. * If the file does not exist, the method just returns. *

* Subclass writers should override {@link #doDelete(File)}, not this method. *

* * @param fileToDelete the file to delete, not null * @throws NullPointerException if the file is null * @throws IOException if an error occurs during file deletion */ public void delete(final File fileToDelete) throws IOException { if (fileToDelete.exists() && !doDelete(fileToDelete)) { throw new IOException("Deletion failed: " + fileToDelete); } } /** * Deletes the file object, which may be a file or a directory. * All {@code IOException}s are caught and false returned instead. * If the file does not exist or is null, true is returned. *

* Subclass writers should override {@link #doDelete(File)}, not this method. *

* * @param fileToDelete the file to delete, null returns true * @return true if the file was deleted, or there was no such file */ public boolean deleteQuietly(final File fileToDelete) { if (fileToDelete == null || !fileToDelete.exists()) { return true; } try { return doDelete(fileToDelete); } catch (final IOException ex) { return false; } } /** * Actually deletes the file object, which may be a file or a directory. *

* This method is designed for subclasses to override. * The implementation may return either false or an {@code IOException} * when deletion fails. The {@link #delete(File)} and {@link #deleteQuietly(File)} * methods will handle either response appropriately. * A check has been made to ensure that the file will exist. *

*

* This implementation uses {@link FileUtils#delete(File)}. *

* * @param file the file to delete, exists, not null * @return true if the file was deleted * @throws NullPointerException if the file is null * @throws IOException if an error occurs during file deletion */ protected boolean doDelete(final File file) throws IOException { FileUtils.delete(file); return true; } /** * Gets a string describing the delete strategy. * * @return a string describing the delete strategy */ @Override public String toString() { return "FileDeleteStrategy[" + name + "]"; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/FileExistsException.java0100644 0000000 0000000 00000003133 13612062727 030334 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import java.io.File; import java.io.IOException; /** * Indicates that a file already exists. * * @since 2.0 */ public class FileExistsException extends IOException { /** * Defines the serial version UID. */ private static final long serialVersionUID = 1L; /** * Default Constructor. */ public FileExistsException() { } /** * Construct an instance with the specified message. * * @param message The error message */ public FileExistsException(final String message) { super(message); } /** * Construct an instance with the specified file. * * @param file The file that exists */ public FileExistsException(final File file) { super("File " + file + " exists"); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/FileSystem.java0100644 0000000 0000000 00000032240 13612062727 026463 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import java.util.Arrays; import java.util.Locale; import java.util.Objects; /** * Abstracts an OS' file system details, currently supporting the single use case of converting a file name String to a * legal file name with {@link #toLegalFileName(String, char)}. *

* The starting point of any operation is {@link #getCurrent()} which gets you the enum for the file system that matches * the OS hosting the running JVM. *

* * @since 2.7 */ public enum FileSystem { /** * Generic file system. */ GENERIC(false, false, Integer.MAX_VALUE, Integer.MAX_VALUE, new char[] { 0 }, new String[] {}, false), /** * Linux file system. */ LINUX(true, true, 255, 4096, new char[] { // KEEP THIS ARRAY SORTED! // @formatter:off // ASCII NUL 0, '/' // @formatter:on }, new String[] {}, false), /** * MacOS file system. */ MAC_OSX(true, true, 255, 1024, new char[] { // KEEP THIS ARRAY SORTED! // @formatter:off // ASCII NUL 0, '/', ':' // @formatter:on }, new String[] {}, false), /** * Windows file system. *

* The reserved characters are defined in the * Naming Conventions * (microsoft.com). *

* * @see Naming Conventions * (microsoft.com) */ WINDOWS(false, true, 255, 32000, new char[] { // KEEP THIS ARRAY SORTED! // @formatter:off // ASCII NUL 0, // 1-31 may be allowed in file streams 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, '"', '*', '/', ':', '<', '>', '?', '\\', '|' // @formatter:on }, // KEEP THIS ARRAY SORTED! new String[] { "AUX", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9", "CON", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9", "NUL", "PRN" }, true); /** *

* Is {@code true} if this is Linux. *

*

* The field will return {@code false} if {@code OS_NAME} is {@code null}. *

*/ private static final boolean IS_OS_LINUX = getOsMatchesName("Linux"); /** *

* Is {@code true} if this is Mac. *

*

* The field will return {@code false} if {@code OS_NAME} is {@code null}. *

*/ private static final boolean IS_OS_MAC = getOsMatchesName("Mac"); /** * The prefix String for all Windows OS. */ private static final String OS_NAME_WINDOWS_PREFIX = "Windows"; /** *

* Is {@code true} if this is Windows. *

*

* The field will return {@code false} if {@code OS_NAME} is {@code null}. *

*/ private static final boolean IS_OS_WINDOWS = getOsMatchesName(OS_NAME_WINDOWS_PREFIX); /** * Gets the current file system. * * @return the current file system */ public static FileSystem getCurrent() { if (IS_OS_LINUX) { return LINUX; } if (IS_OS_MAC) { return FileSystem.MAC_OSX; } if (IS_OS_WINDOWS) { return FileSystem.WINDOWS; } return GENERIC; } /** * Decides if the operating system matches. * * @param osNamePrefix * the prefix for the os name * @return true if matches, or false if not or can't determine */ private static boolean getOsMatchesName(final String osNamePrefix) { return isOsNameMatch(getSystemProperty("os.name"), osNamePrefix); } /** *

* Gets a System property, defaulting to {@code null} if the property cannot be read. *

*

* If a {@code SecurityException} is caught, the return value is {@code null} and a message is written to * {@code System.err}. *

* * @param property * the system property name * @return the system property value or {@code null} if a security problem occurs */ private static String getSystemProperty(final String property) { try { return System.getProperty(property); } catch (final SecurityException ex) { // we are not allowed to look at this property System.err.println("Caught a SecurityException reading the system property '" + property + "'; the SystemUtils property value will default to null."); return null; } } /** * Decides if the operating system matches. *

* This method is package private instead of private to support unit test invocation. *

* * @param osName * the actual OS name * @param osNamePrefix * the prefix for the expected OS name * @return true if matches, or false if not or can't determine */ private static boolean isOsNameMatch(final String osName, final String osNamePrefix) { if (osName == null) { return false; } return osName.toUpperCase(Locale.ROOT).startsWith(osNamePrefix.toUpperCase(Locale.ROOT)); } private final boolean casePreserving; private final boolean caseSensitive; private final char[] illegalFileNameChars; private final int maxFileNameLength; private final int maxPathLength; private final String[] reservedFileNames; private final boolean supportsDriveLetter; /** * Constructs a new instance. * * @param caseSensitive Whether this file system is case sensitive. * @param casePreserving Whether this file system is case preserving. * @param maxFileLength The maximum length for file names. The file name does not include folders. * @param maxPathLength The maximum length of the path to a file. This can include folders. * @param illegalFileNameChars Illegal characters for this file system. * @param reservedFileNames The reserved file names. * @param supportsDriveLetter Whether this file system support driver letters. */ FileSystem(final boolean caseSensitive, final boolean casePreserving, final int maxFileLength, final int maxPathLength, final char[] illegalFileNameChars, final String[] reservedFileNames, final boolean supportsDriveLetter) { this.maxFileNameLength = maxFileLength; this.maxPathLength = maxPathLength; this.illegalFileNameChars = Objects.requireNonNull(illegalFileNameChars, "illegalFileNameChars"); this.reservedFileNames = Objects.requireNonNull(reservedFileNames, "reservedFileNames"); this.caseSensitive = caseSensitive; this.casePreserving = casePreserving; this.supportsDriveLetter = supportsDriveLetter; } /** * Gets a cloned copy of the illegal characters for this file system. * * @return the illegal characters for this file system. */ public char[] getIllegalFileNameChars() { return this.illegalFileNameChars.clone(); } /** * Gets the maximum length for file names. The file name does not include folders. * * @return the maximum length for file names. */ public int getMaxFileNameLength() { return maxFileNameLength; } /** * Gets the maximum length of the path to a file. This can include folders. * * @return the maximum length of the path to a file. */ public int getMaxPathLength() { return maxPathLength; } /** * Gets a cloned copy of the reserved file names. * * @return the reserved file names. */ public String[] getReservedFileNames() { return reservedFileNames.clone(); } /** * Whether this file system preserves case. * * @return Whether this file system preserves case. */ public boolean isCasePreserving() { return casePreserving; } /** * Whether this file system is case-sensitive. * * @return Whether this file system is case-sensitive. */ public boolean isCaseSensitive() { return caseSensitive; } /** * Returns {@code true} if the given character is illegal in a file name, {@code false} otherwise. * * @param c * the character to test * @return {@code true} if the given character is illegal in a file name, {@code false} otherwise. */ private boolean isIllegalFileNameChar(final char c) { return Arrays.binarySearch(illegalFileNameChars, c) >= 0; } /** * Checks if a candidate file name (without a path) such as {@code "filename.ext"} or {@code "filename"} is a * potentially legal file name. If the file name length exceeds {@link #getMaxFileNameLength()}, or if it contains * an illegal character then the check fails. * * @param candidate * a candidate file name (without a path) like {@code "filename.ext"} or {@code "filename"} * @return {@code true} if the candidate name is legal */ public boolean isLegalFileName(final CharSequence candidate) { if (candidate == null || candidate.length() == 0 || candidate.length() > maxFileNameLength) { return false; } if (isReservedFileName(candidate)) { return false; } for (int i = 0; i < candidate.length(); i++) { if (isIllegalFileNameChar(candidate.charAt(i))) { return false; } } return true; } /** * Returns whether the given string is a reserved file name. * * @param candidate * the string to test * @return {@code true} if the given string is a reserved file name. */ public boolean isReservedFileName(final CharSequence candidate) { return Arrays.binarySearch(reservedFileNames, candidate) >= 0; } /** * Tests whether this file system support driver letters. *

* Windows supports driver letters as do other operating systems. Whether these other OS's still support Java like * OS/2, is a different matter. *

* * @return whether this file system support driver letters. * @since 2.9.0 * @see Operating systems that use drive letter * assignment */ public boolean supportsDriveLetter() { return supportsDriveLetter; } /** * Converts a candidate file name (without a path) like {@code "filename.ext"} or {@code "filename"} to a legal file * name. Illegal characters in the candidate name are replaced by the {@code replacement} character. If the file * name length exceeds {@link #getMaxFileNameLength()}, then the name is truncated to * {@link #getMaxFileNameLength()}. * * @param candidate * a candidate file name (without a path) like {@code "filename.ext"} or {@code "filename"} * @param replacement * Illegal characters in the candidate name are replaced by this character * @return a String without illegal characters */ public String toLegalFileName(final String candidate, final char replacement) { if (isIllegalFileNameChar(replacement)) { throw new IllegalArgumentException( String.format("The replacement character '%s' cannot be one of the %s illegal characters: %s", // %s does not work properly with NUL replacement == '\0' ? "\\0" : replacement, name(), Arrays.toString(illegalFileNameChars))); } final String truncated = candidate.length() > maxFileNameLength ? candidate.substring(0, maxFileNameLength) : candidate; boolean changed = false; final char[] charArray = truncated.toCharArray(); for (int i = 0; i < charArray.length; i++) { if (isIllegalFileNameChar(charArray[i])) { charArray[i] = replacement; changed = true; } } return changed ? String.valueOf(charArray) : truncated; } }commons-io-2.11.0-src/src/main/java/org/apache/commons/io/FileSystemUtils.java0100644 0000000 0000000 00000055030 13612062727 027506 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.nio.charset.Charset; import java.time.Duration; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Locale; import java.util.StringTokenizer; /** * General File System utilities. *

* This class provides static utility methods for general file system * functions not provided via the JDK {@link java.io.File File} class. *

* The current functions provided are: *

    *
  • Get the free space on a drive *
* * @since 1.1 * @deprecated As of 2.6 deprecated without replacement. Use equivalent * methods in {@link java.nio.file.FileStore} instead, e.g. * {@code Files.getFileStore(Paths.get("/home")).getUsableSpace()} * or iterate over {@code FileSystems.getDefault().getFileStores()} */ @Deprecated public class FileSystemUtils { /** Singleton instance, used mainly for testing. */ private static final FileSystemUtils INSTANCE = new FileSystemUtils(); /** Operating system state flag for error. */ private static final int INIT_PROBLEM = -1; /** Operating system state flag for neither Unix nor Windows. */ private static final int OTHER = 0; /** Operating system state flag for Windows. */ private static final int WINDOWS = 1; /** Operating system state flag for Unix. */ private static final int UNIX = 2; /** Operating system state flag for Posix flavour Unix. */ private static final int POSIX_UNIX = 3; /** The operating system flag. */ private static final int OS; /** The path to df */ private static final String DF; static { int os = OTHER; String dfPath = "df"; try { String osName = System.getProperty("os.name"); if (osName == null) { throw new IOException("os.name not found"); } osName = osName.toLowerCase(Locale.ENGLISH); // match if (osName.contains("windows")) { os = WINDOWS; } else if (osName.contains("linux") || osName.contains("mpe/ix") || osName.contains("freebsd") || osName.contains("openbsd") || osName.contains("irix") || osName.contains("digital unix") || osName.contains("unix") || osName.contains("mac os x")) { os = UNIX; } else if (osName.contains("sun os") || osName.contains("sunos") || osName.contains("solaris")) { os = POSIX_UNIX; dfPath = "/usr/xpg4/bin/df"; } else if (osName.contains("hp-ux") || osName.contains("aix")) { os = POSIX_UNIX; } } catch (final Exception ex) { os = INIT_PROBLEM; } OS = os; DF = dfPath; } /** * Instances should NOT be constructed in standard programming. */ public FileSystemUtils() { } /** * Returns the free space on a drive or volume by invoking * the command line. * This method does not normalize the result, and typically returns * bytes on Windows, 512 byte units on OS X and kilobytes on Unix. * As this is not very useful, this method is deprecated in favour * of {@link #freeSpaceKb(String)} which returns a result in kilobytes. *

* Note that some OS's are NOT currently supported, including OS/390, * OpenVMS. *

     * FileSystemUtils.freeSpace("C:");       // Windows
     * FileSystemUtils.freeSpace("/volume");  // *nix
     * 
* The free space is calculated via the command line. * It uses 'dir /-c' on Windows and 'df' on *nix. * * @param path the path to get free space for, not null, not empty on Unix * @return the amount of free drive space on the drive or volume * @throws IllegalArgumentException if the path is invalid * @throws IllegalStateException if an error occurred in initialisation * @throws IOException if an error occurs when finding the free space * @since 1.1, enhanced OS support in 1.2 and 1.3 * @deprecated Use freeSpaceKb(String) * Deprecated from 1.3, may be removed in 2.0 */ @Deprecated public static long freeSpace(final String path) throws IOException { return INSTANCE.freeSpaceOS(path, OS, false, Duration.ofMillis(-1)); } /** * Returns the free space on a drive or volume in kibibytes (1024 bytes) * by invoking the command line. *
     * FileSystemUtils.freeSpaceKb("C:");       // Windows
     * FileSystemUtils.freeSpaceKb("/volume");  // *nix
     * 
* The free space is calculated via the command line. * It uses 'dir /-c' on Windows, 'df -kP' on AIX/HP-UX and 'df -k' on other Unix. *

* In order to work, you must be running Windows, or have a implementation of * Unix df that supports GNU format when passed -k (or -kP). If you are going * to rely on this code, please check that it works on your OS by running * some simple tests to compare the command line with the output from this class. * If your operating system isn't supported, please raise a JIRA call detailing * the exact result from df -k and as much other detail as possible, thanks. * * @param path the path to get free space for, not null, not empty on Unix * @return the amount of free drive space on the drive or volume in kilobytes * @throws IllegalArgumentException if the path is invalid * @throws IllegalStateException if an error occurred in initialisation * @throws IOException if an error occurs when finding the free space * @since 1.2, enhanced OS support in 1.3 * @deprecated As of 2.6 deprecated without replacement. Please use {@link java.nio.file.FileStore#getUsableSpace()}. */ @Deprecated public static long freeSpaceKb(final String path) throws IOException { return freeSpaceKb(path, -1); } /** * Returns the free space on a drive or volume in kibibytes (1024 bytes) * by invoking the command line. *

     * FileSystemUtils.freeSpaceKb("C:");       // Windows
     * FileSystemUtils.freeSpaceKb("/volume");  // *nix
     * 
* The free space is calculated via the command line. * It uses 'dir /-c' on Windows, 'df -kP' on AIX/HP-UX and 'df -k' on other Unix. *

* In order to work, you must be running Windows, or have a implementation of * Unix df that supports GNU format when passed -k (or -kP). If you are going * to rely on this code, please check that it works on your OS by running * some simple tests to compare the command line with the output from this class. * If your operating system isn't supported, please raise a JIRA call detailing * the exact result from df -k and as much other detail as possible, thanks. * * @param path the path to get free space for, not null, not empty on Unix * @param timeout The timeout amount in milliseconds or no timeout if the value * is zero or less * @return the amount of free drive space on the drive or volume in kilobytes * @throws IllegalArgumentException if the path is invalid * @throws IllegalStateException if an error occurred in initialisation * @throws IOException if an error occurs when finding the free space * @since 2.0 * @deprecated As of 2.6 deprecated without replacement. Please use {@link java.nio.file.FileStore#getUsableSpace()}. */ @Deprecated public static long freeSpaceKb(final String path, final long timeout) throws IOException { return INSTANCE.freeSpaceOS(path, OS, true, Duration.ofMillis(timeout)); } /** * Returns the free space for the working directory * in kibibytes (1024 bytes) by invoking the command line. *

* Identical to: *

     * freeSpaceKb(new File(".").getAbsolutePath())
     * 
* @return the amount of free drive space on the drive or volume in kilobytes * @throws IllegalStateException if an error occurred in initialisation * @throws IOException if an error occurs when finding the free space * @since 2.0 * @deprecated As of 2.6 deprecated without replacement. Please use {@link java.nio.file.FileStore#getUsableSpace()}. */ @Deprecated public static long freeSpaceKb() throws IOException { return freeSpaceKb(-1); } /** * Returns the free space for the working directory * in kibibytes (1024 bytes) by invoking the command line. *

* Identical to: *

     * freeSpaceKb(new File(".").getAbsolutePath())
     * 
* @param timeout The timeout amount in milliseconds or no timeout if the value * is zero or less * @return the amount of free drive space on the drive or volume in kilobytes * @throws IllegalStateException if an error occurred in initialisation * @throws IOException if an error occurs when finding the free space * @since 2.0 * @deprecated As of 2.6 deprecated without replacement. Please use {@link java.nio.file.FileStore#getUsableSpace()}. */ @Deprecated public static long freeSpaceKb(final long timeout) throws IOException { return freeSpaceKb(new File(".").getAbsolutePath(), timeout); } /** * Returns the free space on a drive or volume in a cross-platform manner. * Note that some OS's are NOT currently supported, including OS/390. *
     * FileSystemUtils.freeSpace("C:");  // Windows
     * FileSystemUtils.freeSpace("/volume");  // *nix
     * 
* The free space is calculated via the command line. * It uses 'dir /-c' on Windows and 'df' on *nix. * * @param path the path to get free space for, not null, not empty on Unix * @param os the operating system code * @param kb whether to normalize to kilobytes * @param timeout The timeout amount in milliseconds or no timeout if the value * is zero or less * @return the amount of free drive space on the drive or volume * @throws IllegalArgumentException if the path is invalid * @throws IllegalStateException if an error occurred in initialisation * @throws IOException if an error occurs when finding the free space */ long freeSpaceOS(final String path, final int os, final boolean kb, final Duration timeout) throws IOException { if (path == null) { throw new IllegalArgumentException("Path must not be null"); } switch (os) { case WINDOWS: return kb ? freeSpaceWindows(path, timeout) / FileUtils.ONE_KB : freeSpaceWindows(path, timeout); case UNIX: return freeSpaceUnix(path, kb, false, timeout); case POSIX_UNIX: return freeSpaceUnix(path, kb, true, timeout); case OTHER: throw new IllegalStateException("Unsupported operating system"); default: throw new IllegalStateException( "Exception caught when determining operating system"); } } /** * Find free space on the Windows platform using the 'dir' command. * * @param path the path to get free space for, including the colon * @param timeout The timeout amount in milliseconds or no timeout if the value * is zero or less * @return the amount of free drive space on the drive * @throws IOException if an error occurs */ long freeSpaceWindows(final String path, final Duration timeout) throws IOException { String normPath = FilenameUtils.normalize(path, false); if (normPath == null) { throw new IllegalArgumentException(path); } if (!normPath.isEmpty() && normPath.charAt(0) != '"') { normPath = "\"" + normPath + "\""; } // build and run the 'dir' command final String[] cmdAttribs = {"cmd.exe", "/C", "dir /a /-c " + normPath}; // read in the output of the command to an ArrayList final List lines = performCommand(cmdAttribs, Integer.MAX_VALUE, timeout); // now iterate over the lines we just read and find the LAST // non-empty line (the free space bytes should be in the last element // of the ArrayList anyway, but this will ensure it works even if it's // not, still assuming it is on the last non-blank line) for (int i = lines.size() - 1; i >= 0; i--) { final String line = lines.get(i); if (!line.isEmpty()) { return parseDir(line, normPath); } } // all lines are blank throw new IOException( "Command line 'dir /-c' did not return any info " + "for path '" + normPath + "'"); } /** * Parses the Windows dir response last line * * @param line the line to parse * @param path the path that was sent * @return the number of bytes * @throws IOException if an error occurs */ long parseDir(final String line, final String path) throws IOException { // read from the end of the line to find the last numeric // character on the line, then continue until we find the first // non-numeric character, and everything between that and the last // numeric character inclusive is our free space bytes count int bytesStart = 0; int bytesEnd = 0; int j = line.length() - 1; innerLoop1: while (j >= 0) { final char c = line.charAt(j); if (Character.isDigit(c)) { // found the last numeric character, this is the end of // the free space bytes count bytesEnd = j + 1; break innerLoop1; } j--; } innerLoop2: while (j >= 0) { final char c = line.charAt(j); if (!Character.isDigit(c) && c != ',' && c != '.') { // found the next non-numeric character, this is the // beginning of the free space bytes count bytesStart = j + 1; break innerLoop2; } j--; } if (j < 0) { throw new IOException( "Command line 'dir /-c' did not return valid info " + "for path '" + path + "'"); } // remove commas and dots in the bytes count final StringBuilder buf = new StringBuilder(line.substring(bytesStart, bytesEnd)); for (int k = 0; k < buf.length(); k++) { if (buf.charAt(k) == ',' || buf.charAt(k) == '.') { buf.deleteCharAt(k--); } } return parseBytes(buf.toString(), path); } /** * Find free space on the *nix platform using the 'df' command. * * @param path the path to get free space for * @param kb whether to normalize to kilobytes * @param posix whether to use the POSIX standard format flag * @param timeout The timeout amount in milliseconds or no timeout if the value * is zero or less * @return the amount of free drive space on the volume * @throws IOException if an error occurs */ long freeSpaceUnix(final String path, final boolean kb, final boolean posix, final Duration timeout) throws IOException { if (path.isEmpty()) { throw new IllegalArgumentException("Path must not be empty"); } // build and run the 'dir' command String flags = "-"; if (kb) { flags += "k"; } if (posix) { flags += "P"; } final String[] cmdAttribs = flags.length() > 1 ? new String[] {DF, flags, path} : new String[] {DF, path}; // perform the command, asking for up to 3 lines (header, interesting, overflow) final List lines = performCommand(cmdAttribs, 3, timeout); if (lines.size() < 2) { // unknown problem, throw exception throw new IOException( "Command line '" + DF + "' did not return info as expected " + "for path '" + path + "'- response was " + lines); } final String line2 = lines.get(1); // the line we're interested in // Now, we tokenize the string. The fourth element is what we want. StringTokenizer tok = new StringTokenizer(line2, " "); if (tok.countTokens() < 4) { // could be long Filesystem, thus data on third line if ((tok.countTokens() != 1) || (lines.size() < 3)) { throw new IOException( "Command line '" + DF + "' did not return data as expected " + "for path '" + path + "'- check path is valid"); } final String line3 = lines.get(2); // the line may be interested in tok = new StringTokenizer(line3, " "); } else { tok.nextToken(); // Ignore Filesystem } tok.nextToken(); // Ignore 1K-blocks tok.nextToken(); // Ignore Used final String freeSpace = tok.nextToken(); return parseBytes(freeSpace, path); } /** * Parses the bytes from a string. * * @param freeSpace the free space string * @param path the path * @return the number of bytes * @throws IOException if an error occurs */ long parseBytes(final String freeSpace, final String path) throws IOException { try { final long bytes = Long.parseLong(freeSpace); if (bytes < 0) { throw new IOException( "Command line '" + DF + "' did not find free space in response " + "for path '" + path + "'- check path is valid"); } return bytes; } catch (final NumberFormatException ex) { throw new IOException( "Command line '" + DF + "' did not return numeric data as expected " + "for path '" + path + "'- check path is valid", ex); } } /** * Performs an OS command. * * @param cmdAttribs the command line parameters * @param max The maximum limit for the lines returned * @param timeout The timeout amount in milliseconds or no timeout if the value * is zero or less * @return the lines returned by the command, converted to lower-case * @throws IOException if an error occurs */ List performCommand(final String[] cmdAttribs, final int max, final Duration timeout) throws IOException { // this method does what it can to avoid the 'Too many open files' error // based on trial and error and these links: // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4784692 // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4801027 // http://forum.java.sun.com/thread.jspa?threadID=533029&messageID=2572018 // however, its still not perfect as the JDK support is so poor // (see commons-exec or Ant for a better multi-threaded multi-os solution) final List lines = new ArrayList<>(20); Process proc = null; InputStream in = null; OutputStream out = null; InputStream err = null; BufferedReader inr = null; try { final Thread monitor = ThreadMonitor.start(timeout); proc = openProcess(cmdAttribs); in = proc.getInputStream(); out = proc.getOutputStream(); err = proc.getErrorStream(); // default charset is most likely appropriate here inr = new BufferedReader(new InputStreamReader(in, Charset.defaultCharset())); String line = inr.readLine(); while (line != null && lines.size() < max) { line = line.toLowerCase(Locale.ENGLISH).trim(); lines.add(line); line = inr.readLine(); } proc.waitFor(); ThreadMonitor.stop(monitor); if (proc.exitValue() != 0) { // os command problem, throw exception throw new IOException( "Command line returned OS error code '" + proc.exitValue() + "' for command " + Arrays.asList(cmdAttribs)); } if (lines.isEmpty()) { // unknown problem, throw exception throw new IOException( "Command line did not return any info " + "for command " + Arrays.asList(cmdAttribs)); } inr.close(); inr = null; in.close(); in = null; if (out != null) { out.close(); out = null; } if (err != null) { err.close(); err = null; } return lines; } catch (final InterruptedException ex) { throw new IOException( "Command line threw an InterruptedException " + "for command " + Arrays.asList(cmdAttribs) + " timeout=" + timeout, ex); } finally { IOUtils.closeQuietly(in); IOUtils.closeQuietly(out); IOUtils.closeQuietly(err); IOUtils.closeQuietly(inr); if (proc != null) { proc.destroy(); } } } /** * Opens the process to the operating system. * * @param cmdAttribs the command line parameters * @return the process * @throws IOException if an error occurs */ Process openProcess(final String[] cmdAttribs) throws IOException { return Runtime.getRuntime().exec(cmdAttribs); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/FileUtils.java0100644 0000000 0000000 00000471210 13612062727 026303 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileFilter; 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.OutputStream; import java.io.Reader; import java.io.UncheckedIOException; import java.math.BigInteger; import java.net.URL; import java.net.URLConnection; import java.nio.ByteBuffer; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.nio.charset.UnsupportedCharsetException; import java.nio.file.CopyOption; import java.nio.file.FileVisitOption; import java.nio.file.Files; import java.nio.file.LinkOption; import java.nio.file.NotDirectoryException; import java.nio.file.Path; import java.nio.file.StandardCopyOption; import java.time.Instant; import java.time.LocalTime; import java.time.ZoneId; import java.time.chrono.ChronoLocalDate; import java.time.chrono.ChronoLocalDateTime; import java.time.chrono.ChronoZonedDateTime; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.Iterator; import java.util.List; import java.util.Objects; import java.util.stream.Collectors; import java.util.stream.Stream; import java.util.zip.CRC32; import java.util.zip.CheckedInputStream; import java.util.zip.Checksum; import org.apache.commons.io.file.AccumulatorPathVisitor; import org.apache.commons.io.file.Counters; import org.apache.commons.io.file.PathFilter; import org.apache.commons.io.file.PathUtils; import org.apache.commons.io.file.StandardDeleteOption; import org.apache.commons.io.filefilter.FileEqualsFileFilter; import org.apache.commons.io.filefilter.FileFileFilter; import org.apache.commons.io.filefilter.IOFileFilter; import org.apache.commons.io.filefilter.SuffixFileFilter; import org.apache.commons.io.filefilter.TrueFileFilter; /** * General file manipulation utilities. *

* Facilities are provided in the following areas: *

*
    *
  • writing to a file *
  • reading from a file *
  • make a directory including parent directories *
  • copying files and directories *
  • deleting files and directories *
  • converting to and from a URL *
  • listing files and directories by filter and extension *
  • comparing file content *
  • file last changed date *
  • calculating a checksum *
*

* Note that a specific charset should be specified whenever possible. Relying on the platform default means that the * code is Locale-dependent. Only use the default if the files are known to always use the platform default. *

*

* {@link SecurityException} are not documented in the Javadoc. *

*

* Origin of code: Excalibur, Alexandria, Commons-Utils *

*/ public class FileUtils { /** * The number of bytes in a kilobyte. */ public static final long ONE_KB = 1024; /** * The number of bytes in a kilobyte. * * @since 2.4 */ public static final BigInteger ONE_KB_BI = BigInteger.valueOf(ONE_KB); /** * The number of bytes in a megabyte. */ public static final long ONE_MB = ONE_KB * ONE_KB; /** * The number of bytes in a megabyte. * * @since 2.4 */ public static final BigInteger ONE_MB_BI = ONE_KB_BI.multiply(ONE_KB_BI); /** * The number of bytes in a gigabyte. */ public static final long ONE_GB = ONE_KB * ONE_MB; /** * The number of bytes in a gigabyte. * * @since 2.4 */ public static final BigInteger ONE_GB_BI = ONE_KB_BI.multiply(ONE_MB_BI); /** * The number of bytes in a terabyte. */ public static final long ONE_TB = ONE_KB * ONE_GB; /** * The number of bytes in a terabyte. * * @since 2.4 */ public static final BigInteger ONE_TB_BI = ONE_KB_BI.multiply(ONE_GB_BI); /** * The number of bytes in a petabyte. */ public static final long ONE_PB = ONE_KB * ONE_TB; /** * The number of bytes in a petabyte. * * @since 2.4 */ public static final BigInteger ONE_PB_BI = ONE_KB_BI.multiply(ONE_TB_BI); /** * The number of bytes in an exabyte. */ public static final long ONE_EB = ONE_KB * ONE_PB; /** * The number of bytes in an exabyte. * * @since 2.4 */ public static final BigInteger ONE_EB_BI = ONE_KB_BI.multiply(ONE_PB_BI); /** * The number of bytes in a zettabyte. */ public static final BigInteger ONE_ZB = BigInteger.valueOf(ONE_KB).multiply(BigInteger.valueOf(ONE_EB)); /** * The number of bytes in a yottabyte. */ public static final BigInteger ONE_YB = ONE_KB_BI.multiply(ONE_ZB); /** * An empty array of type {@code File}. */ public static final File[] EMPTY_FILE_ARRAY = {}; /** * Copies the given array and adds StandardCopyOption.COPY_ATTRIBUTES. * * @param copyOptions sorted copy options. * @return a new array. */ private static CopyOption[] addCopyAttributes(final CopyOption... copyOptions) { // Make a copy first since we don't want to sort the call site's version. final CopyOption[] actual = Arrays.copyOf(copyOptions, copyOptions.length + 1); Arrays.sort(actual, 0, copyOptions.length); if (Arrays.binarySearch(copyOptions, 0, copyOptions.length, StandardCopyOption.COPY_ATTRIBUTES) >= 0) { return copyOptions; } actual[actual.length - 1] = StandardCopyOption.COPY_ATTRIBUTES; return actual; } /** * Returns a human-readable version of the file size, where the input represents a specific number of bytes. *

* If the size is over 1GB, the size is returned as the number of whole GB, i.e. the size is rounded down to the * nearest GB boundary. *

*

* Similarly for the 1MB and 1KB boundaries. *

* * @param size the number of bytes * @return a human-readable display value (includes units - EB, PB, TB, GB, MB, KB or bytes) * @throws NullPointerException if the given {@code BigInteger} is {@code null}. * @see IO-226 - should the rounding be changed? * @since 2.4 */ // See https://issues.apache.org/jira/browse/IO-226 - should the rounding be changed? public static String byteCountToDisplaySize(final BigInteger size) { Objects.requireNonNull(size, "size"); final String displaySize; if (size.divide(ONE_EB_BI).compareTo(BigInteger.ZERO) > 0) { displaySize = size.divide(ONE_EB_BI) + " EB"; } else if (size.divide(ONE_PB_BI).compareTo(BigInteger.ZERO) > 0) { displaySize = size.divide(ONE_PB_BI) + " PB"; } else if (size.divide(ONE_TB_BI).compareTo(BigInteger.ZERO) > 0) { displaySize = size.divide(ONE_TB_BI) + " TB"; } else if (size.divide(ONE_GB_BI).compareTo(BigInteger.ZERO) > 0) { displaySize = size.divide(ONE_GB_BI) + " GB"; } else if (size.divide(ONE_MB_BI).compareTo(BigInteger.ZERO) > 0) { displaySize = size.divide(ONE_MB_BI) + " MB"; } else if (size.divide(ONE_KB_BI).compareTo(BigInteger.ZERO) > 0) { displaySize = size.divide(ONE_KB_BI) + " KB"; } else { displaySize = size + " bytes"; } return displaySize; } /** * Returns a human-readable version of the file size, where the input represents a specific number of bytes. *

* If the size is over 1GB, the size is returned as the number of whole GB, i.e. the size is rounded down to the * nearest GB boundary. *

*

* Similarly for the 1MB and 1KB boundaries. *

* * @param size the number of bytes * @return a human-readable display value (includes units - EB, PB, TB, GB, MB, KB or bytes) * @see IO-226 - should the rounding be changed? */ // See https://issues.apache.org/jira/browse/IO-226 - should the rounding be changed? public static String byteCountToDisplaySize(final long size) { return byteCountToDisplaySize(BigInteger.valueOf(size)); } /** * Computes the checksum of a file using the specified checksum object. Multiple files may be checked using one * {@code Checksum} instance if desired simply by reusing the same checksum object. For example: * *
     * long checksum = FileUtils.checksum(file, new CRC32()).getValue();
     * 
* * @param file the file to checksum, must not be {@code null} * @param checksum the checksum object to be used, must not be {@code null} * @return the checksum specified, updated with the content of the file * @throws NullPointerException if the given {@code File} is {@code null}. * @throws NullPointerException if the given {@code Checksum} is {@code null}. * @throws IllegalArgumentException if the given {@code File} does not exist or is not a file. * @throws IOException if an IO error occurs reading the file. * @since 1.3 */ public static Checksum checksum(final File file, final Checksum checksum) throws IOException { requireExistsChecked(file, "file"); requireFile(file, "file"); Objects.requireNonNull(checksum, "checksum"); try (InputStream inputStream = new CheckedInputStream(Files.newInputStream(file.toPath()), checksum)) { IOUtils.consume(inputStream); } return checksum; } /** * Computes the checksum of a file using the CRC32 checksum routine. * The value of the checksum is returned. * * @param file the file to checksum, must not be {@code null} * @return the checksum value * @throws NullPointerException if the given {@code File} is {@code null}. * @throws IllegalArgumentException if the given {@code File} does not exist or is not a file. * @throws IOException if an IO error occurs reading the file. * @since 1.3 */ public static long checksumCRC32(final File file) throws IOException { return checksum(file, new CRC32()).getValue(); } /** * Cleans a directory without deleting it. * * @param directory directory to clean * @throws NullPointerException if the given {@code File} is {@code null}. * @throws IllegalArgumentException if directory does not exist or is not a directory. * @throws IOException if an I/O error occurs. * @see #forceDelete(File) */ public static void cleanDirectory(final File directory) throws IOException { final File[] files = listFiles(directory, null); final List causeList = new ArrayList<>(); for (final File file : files) { try { forceDelete(file); } catch (final IOException ioe) { causeList.add(ioe); } } if (!causeList.isEmpty()) { throw new IOExceptionList(directory.toString(), causeList); } } /** * Cleans a directory without deleting it. * * @param directory directory to clean, must not be {@code null} * @throws NullPointerException if the given {@code File} is {@code null}. * @throws IllegalArgumentException if directory does not exist or is not a directory. * @throws IOException if an I/O error occurs. * @see #forceDeleteOnExit(File) */ private static void cleanDirectoryOnExit(final File directory) throws IOException { final File[] files = listFiles(directory, null); final List causeList = new ArrayList<>(); for (final File file : files) { try { forceDeleteOnExit(file); } catch (final IOException ioe) { causeList.add(ioe); } } if (!causeList.isEmpty()) { throw new IOExceptionList(causeList); } } /** * Tests whether the contents of two files are equal. *

* This method checks to see if the two files are different lengths or if they point to the same file, before * resorting to byte-by-byte comparison of the contents. *

*

* Code origin: Avalon *

* * @param file1 the first file * @param file2 the second file * @return true if the content of the files are equal or they both don't exist, false otherwise * @throws IllegalArgumentException when an input is not a file. * @throws IOException If an I/O error occurs. * @see org.apache.commons.io.file.PathUtils#fileContentEquals(Path,Path,java.nio.file.LinkOption[],java.nio.file.OpenOption...) */ public static boolean contentEquals(final File file1, final File file2) throws IOException { if (file1 == null && file2 == null) { return true; } if (file1 == null || file2 == null) { return false; } final boolean file1Exists = file1.exists(); if (file1Exists != file2.exists()) { return false; } if (!file1Exists) { // two not existing files are equal return true; } requireFile(file1, "file1"); requireFile(file2, "file2"); if (file1.length() != file2.length()) { // lengths differ, cannot be equal return false; } if (file1.getCanonicalFile().equals(file2.getCanonicalFile())) { // same file return true; } try (InputStream input1 = Files.newInputStream(file1.toPath()); InputStream input2 = Files.newInputStream(file2.toPath())) { return IOUtils.contentEquals(input1, input2); } } /** * Compares the contents of two files to determine if they are equal or not. *

* This method checks to see if the two files point to the same file, * before resorting to line-by-line comparison of the contents. *

* * @param file1 the first file * @param file2 the second file * @param charsetName the name of the requested charset. * May be null, in which case the platform default is used * @return true if the content of the files are equal or neither exists, * false otherwise * @throws IllegalArgumentException when an input is not a file. * @throws IOException in case of an I/O error. * @throws UnsupportedCharsetException If the named charset is unavailable (unchecked exception). * @see IOUtils#contentEqualsIgnoreEOL(Reader, Reader) * @since 2.2 */ public static boolean contentEqualsIgnoreEOL(final File file1, final File file2, final String charsetName) throws IOException { if (file1 == null && file2 == null) { return true; } if (file1 == null || file2 == null) { return false; } final boolean file1Exists = file1.exists(); if (file1Exists != file2.exists()) { return false; } if (!file1Exists) { // two not existing files are equal return true; } requireFile(file1, "file1"); requireFile(file2, "file2"); if (file1.getCanonicalFile().equals(file2.getCanonicalFile())) { // same file return true; } final Charset charset = Charsets.toCharset(charsetName); try (Reader input1 = new InputStreamReader(Files.newInputStream(file1.toPath()), charset); Reader input2 = new InputStreamReader(Files.newInputStream(file2.toPath()), charset)) { return IOUtils.contentEqualsIgnoreEOL(input1, input2); } } /** * Converts a Collection containing java.io.File instanced into array * representation. This is to account for the difference between * File.listFiles() and FileUtils.listFiles(). * * @param files a Collection containing java.io.File instances * @return an array of java.io.File */ public static File[] convertFileCollectionToFileArray(final Collection files) { return files.toArray(EMPTY_FILE_ARRAY); } /** * Copies a whole directory to a new location preserving the file dates. *

* This method copies the specified directory and all its child directories and files to the specified destination. * The destination is the new location and name of the directory. *

*

* The destination directory is created if it does not exist. If the destination directory did exist, then this * method merges the source with the destination, with the source taking precedence. *

*

* Note: This method tries to preserve the files' last modified date/times using * {@link File#setLastModified(long)}, however it is not guaranteed that those operations will succeed. If the * modification operation fails, the methods throws IOException. *

* * @param srcDir an existing directory to copy, must not be {@code null}. * @param destDir the new directory, must not be {@code null}. * @throws NullPointerException if any of the given {@code File}s are {@code null}. * @throws IllegalArgumentException if the source or destination is invalid. * @throws FileNotFoundException if the source does not exist. * @throws IOException if an error occurs or setting the last-modified time didn't succeeded. * @since 1.1 */ public static void copyDirectory(final File srcDir, final File destDir) throws IOException { copyDirectory(srcDir, destDir, true); } /** * Copies a whole directory to a new location. *

* This method copies the contents of the specified source directory to within the specified destination directory. *

*

* The destination directory is created if it does not exist. If the destination directory did exist, then this * method merges the source with the destination, with the source taking precedence. *

*

* Note: Setting {@code preserveFileDate} to {@code true} tries to preserve the files' last * modified date/times using {@link File#setLastModified(long)}, however it is not guaranteed that those operations * will succeed. If the modification operation fails, the methods throws IOException. *

* * @param srcDir an existing directory to copy, must not be {@code null}. * @param destDir the new directory, must not be {@code null}. * @param preserveFileDate true if the file date of the copy should be the same as the original. * @throws NullPointerException if any of the given {@code File}s are {@code null}. * @throws IllegalArgumentException if the source or destination is invalid. * @throws FileNotFoundException if the source does not exist. * @throws IOException if an error occurs or setting the last-modified time didn't succeeded. * @since 1.1 */ public static void copyDirectory(final File srcDir, final File destDir, final boolean preserveFileDate) throws IOException { copyDirectory(srcDir, destDir, null, preserveFileDate); } /** * Copies a filtered directory to a new location preserving the file dates. *

* This method copies the contents of the specified source directory to within the specified destination directory. *

*

* The destination directory is created if it does not exist. If the destination directory did exist, then this * method merges the source with the destination, with the source taking precedence. *

*

* Note: This method tries to preserve the files' last modified date/times using * {@link File#setLastModified(long)}, however it is not guaranteed that those operations will succeed. If the * modification operation fails, the methods throws IOException. *

* Example: Copy directories only * *
     * // only copy the directory structure
     * FileUtils.copyDirectory(srcDir, destDir, DirectoryFileFilter.DIRECTORY);
     * 
* * Example: Copy directories and txt files * *
     * // Create a filter for ".txt" files
     * IOFileFilter txtSuffixFilter = FileFilterUtils.suffixFileFilter(".txt");
     * IOFileFilter txtFiles = FileFilterUtils.andFileFilter(FileFileFilter.FILE, txtSuffixFilter);
     *
     * // Create a filter for either directories or ".txt" files
     * FileFilter filter = FileFilterUtils.orFileFilter(DirectoryFileFilter.DIRECTORY, txtFiles);
     *
     * // Copy using the filter
     * FileUtils.copyDirectory(srcDir, destDir, filter);
     * 
* * @param srcDir an existing directory to copy, must not be {@code null}. * @param destDir the new directory, must not be {@code null}. * @param filter the filter to apply, null means copy all directories and files should be the same as the original. * @throws NullPointerException if any of the given {@code File}s are {@code null}. * @throws IllegalArgumentException if the source or destination is invalid. * @throws FileNotFoundException if the source does not exist. * @throws IOException if an error occurs or setting the last-modified time didn't succeeded. * @since 1.4 */ public static void copyDirectory(final File srcDir, final File destDir, final FileFilter filter) throws IOException { copyDirectory(srcDir, destDir, filter, true); } /** * Copies a filtered directory to a new location. *

* This method copies the contents of the specified source directory to within the specified destination directory. *

*

* The destination directory is created if it does not exist. If the destination directory did exist, then this * method merges the source with the destination, with the source taking precedence. *

*

* Note: Setting {@code preserveFileDate} to {@code true} tries to preserve the files' last * modified date/times using {@link File#setLastModified(long)}, however it is not guaranteed that those operations * will succeed. If the modification operation fails, the methods throws IOException. *

* Example: Copy directories only * *
     * // only copy the directory structure
     * FileUtils.copyDirectory(srcDir, destDir, DirectoryFileFilter.DIRECTORY, false);
     * 
* * Example: Copy directories and txt files * *
     * // Create a filter for ".txt" files
     * IOFileFilter txtSuffixFilter = FileFilterUtils.suffixFileFilter(".txt");
     * IOFileFilter txtFiles = FileFilterUtils.andFileFilter(FileFileFilter.FILE, txtSuffixFilter);
     *
     * // Create a filter for either directories or ".txt" files
     * FileFilter filter = FileFilterUtils.orFileFilter(DirectoryFileFilter.DIRECTORY, txtFiles);
     *
     * // Copy using the filter
     * FileUtils.copyDirectory(srcDir, destDir, filter, false);
     * 
* * @param srcDir an existing directory to copy, must not be {@code null}. * @param destDir the new directory, must not be {@code null}. * @param filter the filter to apply, null means copy all directories and files. * @param preserveFileDate true if the file date of the copy should be the same as the original. * @throws NullPointerException if any of the given {@code File}s are {@code null}. * @throws IllegalArgumentException if the source or destination is invalid. * @throws FileNotFoundException if the source does not exist. * @throws IOException if an error occurs or setting the last-modified time didn't succeeded. * @since 1.4 */ public static void copyDirectory(final File srcDir, final File destDir, final FileFilter filter, final boolean preserveFileDate) throws IOException { copyDirectory(srcDir, destDir, filter, preserveFileDate, StandardCopyOption.REPLACE_EXISTING); } /** * Copies a filtered directory to a new location. *

* This method copies the contents of the specified source directory to within the specified destination directory. *

*

* The destination directory is created if it does not exist. If the destination directory did exist, then this * method merges the source with the destination, with the source taking precedence. *

*

* Note: Setting {@code preserveFileDate} to {@code true} tries to preserve the files' last * modified date/times using {@link File#setLastModified(long)}, however it is not guaranteed that those operations * will succeed. If the modification operation fails, the methods throws IOException. *

* Example: Copy directories only * *
     * // only copy the directory structure
     * FileUtils.copyDirectory(srcDir, destDir, DirectoryFileFilter.DIRECTORY, false);
     * 
* * Example: Copy directories and txt files * *
     * // Create a filter for ".txt" files
     * IOFileFilter txtSuffixFilter = FileFilterUtils.suffixFileFilter(".txt");
     * IOFileFilter txtFiles = FileFilterUtils.andFileFilter(FileFileFilter.FILE, txtSuffixFilter);
     *
     * // Create a filter for either directories or ".txt" files
     * FileFilter filter = FileFilterUtils.orFileFilter(DirectoryFileFilter.DIRECTORY, txtFiles);
     *
     * // Copy using the filter
     * FileUtils.copyDirectory(srcDir, destDir, filter, false);
     * 
* * @param srcDir an existing directory to copy, must not be {@code null} * @param destDir the new directory, must not be {@code null} * @param fileFilter the filter to apply, null means copy all directories and files * @param preserveFileDate true if the file date of the copy should be the same as the original * @param copyOptions options specifying how the copy should be done, for example {@link StandardCopyOption}. * @throws NullPointerException if any of the given {@code File}s are {@code null}. * @throws IllegalArgumentException if the source or destination is invalid. * @throws FileNotFoundException if the source does not exist. * @throws IOException if an error occurs or setting the last-modified time didn't succeeded. * @since 2.8.0 */ public static void copyDirectory(final File srcDir, final File destDir, final FileFilter fileFilter, final boolean preserveFileDate, final CopyOption... copyOptions) throws IOException { requireFileCopy(srcDir, destDir); requireDirectory(srcDir, "srcDir"); requireCanonicalPathsNotEquals(srcDir, destDir); // Cater for destination being directory within the source directory (see IO-141) List exclusionList = null; final String srcDirCanonicalPath = srcDir.getCanonicalPath(); final String destDirCanonicalPath = destDir.getCanonicalPath(); if (destDirCanonicalPath.startsWith(srcDirCanonicalPath)) { final File[] srcFiles = listFiles(srcDir, fileFilter); if (srcFiles.length > 0) { exclusionList = new ArrayList<>(srcFiles.length); for (final File srcFile : srcFiles) { final File copiedFile = new File(destDir, srcFile.getName()); exclusionList.add(copiedFile.getCanonicalPath()); } } } doCopyDirectory(srcDir, destDir, fileFilter, exclusionList, preserveFileDate, preserveFileDate ? addCopyAttributes(copyOptions) : copyOptions); } /** * Copies a directory to within another directory preserving the file dates. *

* This method copies the source directory and all its contents to a directory of the same name in the specified * destination directory. *

*

* The destination directory is created if it does not exist. If the destination directory did exist, then this * method merges the source with the destination, with the source taking precedence. *

*

* Note: This method tries to preserve the files' last modified date/times using * {@link File#setLastModified(long)}, however it is not guaranteed that those operations will succeed. If the * modification operation fails, the methods throws IOException. *

* * @param sourceDir an existing directory to copy, must not be {@code null}. * @param destinationDir the directory to place the copy in, must not be {@code null}. * @throws NullPointerException if any of the given {@code File}s are {@code null}. * @throws IllegalArgumentException if the source or destination is invalid. * @throws FileNotFoundException if the source does not exist. * @throws IOException if an error occurs or setting the last-modified time didn't succeeded. * @since 1.2 */ public static void copyDirectoryToDirectory(final File sourceDir, final File destinationDir) throws IOException { requireDirectoryIfExists(sourceDir, "sourceDir"); requireDirectoryIfExists(destinationDir, "destinationDir"); copyDirectory(sourceDir, new File(destinationDir, sourceDir.getName()), true); } /** * Copies a file to a new location preserving the file date. *

* This method copies the contents of the specified source file to the specified destination file. The directory * holding the destination file is created if it does not exist. If the destination file exists, then this method * will overwrite it. *

*

* Note: This method tries to preserve the file's last modified date/times using * {@link File#setLastModified(long)}, however it is not guaranteed that the operation will succeed. If the * modification operation fails, the methods throws IOException. *

* * @param srcFile an existing file to copy, must not be {@code null}. * @param destFile the new file, must not be {@code null}. * @throws NullPointerException if any of the given {@code File}s are {@code null}. * @throws IOException if source or destination is invalid. * @throws IOException if an error occurs or setting the last-modified time didn't succeeded. * @throws IOException if the output file length is not the same as the input file length after the copy completes. * @see #copyFileToDirectory(File, File) * @see #copyFile(File, File, boolean) */ public static void copyFile(final File srcFile, final File destFile) throws IOException { copyFile(srcFile, destFile, StandardCopyOption.COPY_ATTRIBUTES, StandardCopyOption.REPLACE_EXISTING); } /** * Copies an existing file to a new file location. *

* This method copies the contents of the specified source file to the specified destination file. The directory * holding the destination file is created if it does not exist. If the destination file exists, then this method * will overwrite it. *

*

* Note: Setting {@code preserveFileDate} to {@code true} tries to preserve the file's last * modified date/times using {@link File#setLastModified(long)}, however it is not guaranteed that the operation * will succeed. If the modification operation fails, the methods throws IOException. *

* * @param srcFile an existing file to copy, must not be {@code null}. * @param destFile the new file, must not be {@code null}. * @param preserveFileDate true if the file date of the copy should be the same as the original. * @throws NullPointerException if any of the given {@code File}s are {@code null}. * @throws IOException if source or destination is invalid. * @throws IOException if an error occurs or setting the last-modified time didn't succeeded. * @throws IOException if the output file length is not the same as the input file length after the copy completes * @see #copyFile(File, File, boolean, CopyOption...) */ public static void copyFile(final File srcFile, final File destFile, final boolean preserveFileDate) throws IOException { copyFile(srcFile, destFile, preserveFileDate ? new CopyOption[] {StandardCopyOption.COPY_ATTRIBUTES, StandardCopyOption.REPLACE_EXISTING} : new CopyOption[] {StandardCopyOption.REPLACE_EXISTING}); } /** * Copies a file to a new location. *

* This method copies the contents of the specified source file to the specified destination file. The directory * holding the destination file is created if it does not exist. If the destination file exists, you can overwrite * it with {@link StandardCopyOption#REPLACE_EXISTING}. *

*

* Note: Setting {@code preserveFileDate} to {@code true} tries to preserve the file's last * modified date/times using {@link File#setLastModified(long)}, however it is not guaranteed that the operation * will succeed. If the modification operation fails, the methods throws IOException. *

* * @param srcFile an existing file to copy, must not be {@code null}. * @param destFile the new file, must not be {@code null}. * @param preserveFileDate true if the file date of the copy should be the same as the original. * @param copyOptions options specifying how the copy should be done, for example {@link StandardCopyOption}.. * @throws NullPointerException if any of the given {@code File}s are {@code null}. * @throws FileNotFoundException if the source does not exist. * @throws IllegalArgumentException if source is not a file. * @throws IOException if the output file length is not the same as the input file length after the copy completes. * @throws IOException if an I/O error occurs, or setting the last-modified time didn't succeeded. * @see #copyFileToDirectory(File, File, boolean) * @since 2.8.0 */ public static void copyFile(final File srcFile, final File destFile, final boolean preserveFileDate, final CopyOption... copyOptions) throws IOException { copyFile(srcFile, destFile, preserveFileDate ? addCopyAttributes(copyOptions) : copyOptions); } /** * Copies a file to a new location. *

* This method copies the contents of the specified source file to the specified destination file. The directory * holding the destination file is created if it does not exist. If the destination file exists, you can overwrite * it if you use {@link StandardCopyOption#REPLACE_EXISTING}. *

* * @param srcFile an existing file to copy, must not be {@code null}. * @param destFile the new file, must not be {@code null}. * @param copyOptions options specifying how the copy should be done, for example {@link StandardCopyOption}.. * @throws NullPointerException if any of the given {@code File}s are {@code null}. * @throws FileNotFoundException if the source does not exist. * @throws IllegalArgumentException if source is not a file. * @throws IOException if the output file length is not the same as the input file length after the copy completes. * @throws IOException if an I/O error occurs. * @see StandardCopyOption * @since 2.9.0 */ public static void copyFile(final File srcFile, final File destFile, final CopyOption... copyOptions) throws IOException { requireFileCopy(srcFile, destFile); requireFile(srcFile, "srcFile"); requireCanonicalPathsNotEquals(srcFile, destFile); createParentDirectories(destFile); requireFileIfExists(destFile, "destFile"); if (destFile.exists()) { requireCanWrite(destFile, "destFile"); } // On Windows, the last modified time is copied by default. Files.copy(srcFile.toPath(), destFile.toPath(), copyOptions); // TODO IO-386: Do we still need this check? requireEqualSizes(srcFile, destFile, srcFile.length(), destFile.length()); } /** * Copies bytes from a {@code File} to an {@code OutputStream}. *

* This method buffers the input internally, so there is no need to use a {@code BufferedInputStream}. *

* * @param input the {@code File} to read. * @param output the {@code OutputStream} to write. * @return the number of bytes copied * @throws NullPointerException if the File is {@code null}. * @throws NullPointerException if the OutputStream is {@code null}. * @throws IOException if an I/O error occurs. * @since 2.1 */ public static long copyFile(final File input, final OutputStream output) throws IOException { try (InputStream fis = Files.newInputStream(input.toPath())) { return IOUtils.copyLarge(fis, output); } } /** * Copies a file to a directory preserving the file date. *

* This method copies the contents of the specified source file to a file of the same name in the specified * destination directory. The destination directory is created if it does not exist. If the destination file exists, * then this method will overwrite it. *

*

* Note: This method tries to preserve the file's last modified date/times using * {@link File#setLastModified(long)}, however it is not guaranteed that the operation will succeed. If the * modification operation fails, the methods throws IOException. *

* * @param srcFile an existing file to copy, must not be {@code null}. * @param destDir the directory to place the copy in, must not be {@code null}. * @throws NullPointerException if any of the given {@code File}s are {@code null}. * @throws IllegalArgumentException if source or destination is invalid. * @throws IOException if an error occurs or setting the last-modified time didn't succeeded. * @see #copyFile(File, File, boolean) */ public static void copyFileToDirectory(final File srcFile, final File destDir) throws IOException { copyFileToDirectory(srcFile, destDir, true); } /** * Copies a file to a directory optionally preserving the file date. *

* This method copies the contents of the specified source file to a file of the same name in the specified * destination directory. The destination directory is created if it does not exist. If the destination file exists, * then this method will overwrite it. *

*

* Note: Setting {@code preserveFileDate} to {@code true} tries to preserve the file's last * modified date/times using {@link File#setLastModified(long)}, however it is not guaranteed that the operation * will succeed. If the modification operation fails, the methods throws IOException. *

* * @param sourceFile an existing file to copy, must not be {@code null}. * @param destinationDir the directory to place the copy in, must not be {@code null}. * @param preserveFileDate true if the file date of the copy should be the same as the original. * @throws NullPointerException if any of the given {@code File}s are {@code null}. * @throws IOException if an error occurs or setting the last-modified time didn't succeeded. * @throws IOException if the output file length is not the same as the input file length after the copy completes. * @see #copyFile(File, File, CopyOption...) * @since 1.3 */ public static void copyFileToDirectory(final File sourceFile, final File destinationDir, final boolean preserveFileDate) throws IOException { Objects.requireNonNull(sourceFile, "sourceFile"); requireDirectoryIfExists(destinationDir, "destinationDir"); copyFile(sourceFile, new File(destinationDir, sourceFile.getName()), preserveFileDate); } /** * Copies bytes from an {@link InputStream} {@code source} to a file * {@code destination}. The directories up to {@code destination} * will be created if they don't already exist. {@code destination} * will be overwritten if it already exists. *

* The {@code source} stream is closed. *

*

* See {@link #copyToFile(InputStream, File)} for a method that does not close the input stream. *

* * @param source the {@code InputStream} to copy bytes from, must not be {@code null}, will be closed * @param destination the non-directory {@code File} to write bytes to * (possibly overwriting), must not be {@code null} * @throws IOException if {@code destination} is a directory * @throws IOException if {@code destination} cannot be written * @throws IOException if {@code destination} needs creating but can't be * @throws IOException if an IO error occurs during copying * @since 2.0 */ public static void copyInputStreamToFile(final InputStream source, final File destination) throws IOException { try (InputStream inputStream = source) { copyToFile(inputStream, destination); } } /** * Copies a file or directory to within another directory preserving the file dates. *

* This method copies the source file or directory, along all its contents, to a directory of the same name in the * specified destination directory. *

*

* The destination directory is created if it does not exist. If the destination directory did exist, then this * method merges the source with the destination, with the source taking precedence. *

*

* Note: This method tries to preserve the files' last modified date/times using * {@link File#setLastModified(long)}, however it is not guaranteed that those operations will succeed. If the * modification operation fails, the methods throws IOException. *

* * @param sourceFile an existing file or directory to copy, must not be {@code null}. * @param destinationDir the directory to place the copy in, must not be {@code null}. * @throws NullPointerException if any of the given {@code File}s are {@code null}. * @throws IllegalArgumentException if the source or destination is invalid. * @throws FileNotFoundException if the source does not exist. * @throws IOException if an error occurs or setting the last-modified time didn't succeeded. * @see #copyDirectoryToDirectory(File, File) * @see #copyFileToDirectory(File, File) * @since 2.6 */ public static void copyToDirectory(final File sourceFile, final File destinationDir) throws IOException { Objects.requireNonNull(sourceFile, "sourceFile"); if (sourceFile.isFile()) { copyFileToDirectory(sourceFile, destinationDir); } else if (sourceFile.isDirectory()) { copyDirectoryToDirectory(sourceFile, destinationDir); } else { throw new FileNotFoundException("The source " + sourceFile + " does not exist"); } } /** * Copies a files to a directory preserving each file's date. *

* This method copies the contents of the specified source files * to a file of the same name in the specified destination directory. * The destination directory is created if it does not exist. * If the destination file exists, then this method will overwrite it. *

*

* Note: This method tries to preserve the file's last * modified date/times using {@link File#setLastModified(long)}, however * it is not guaranteed that the operation will succeed. * If the modification operation fails, the methods throws IOException. *

* * @param sourceIterable a existing files to copy, must not be {@code null}. * @param destinationDir the directory to place the copy in, must not be {@code null}. * @throws NullPointerException if any of the given {@code File}s are {@code null}. * @throws IOException if source or destination is invalid. * @throws IOException if an error occurs or setting the last-modified time didn't succeeded. * @see #copyFileToDirectory(File, File) * @since 2.6 */ public static void copyToDirectory(final Iterable sourceIterable, final File destinationDir) throws IOException { Objects.requireNonNull(sourceIterable, "sourceIterable"); for (final File src : sourceIterable) { copyFileToDirectory(src, destinationDir); } } /** * Copies bytes from an {@link InputStream} source to a {@link File} destination. The directories * up to {@code destination} will be created if they don't already exist. {@code destination} will be * overwritten if it already exists. The {@code source} stream is left open, e.g. for use with * {@link java.util.zip.ZipInputStream ZipInputStream}. See {@link #copyInputStreamToFile(InputStream, File)} for a * method that closes the input stream. * * @param inputStream the {@code InputStream} to copy bytes from, must not be {@code null} * @param file the non-directory {@code File} to write bytes to (possibly overwriting), must not be * {@code null} * @throws NullPointerException if the InputStream is {@code null}. * @throws NullPointerException if the File is {@code null}. * @throws IllegalArgumentException if the file object is a directory. * @throws IllegalArgumentException if the file is not writable. * @throws IOException if the directories could not be created. * @throws IOException if an IO error occurs during copying. * @since 2.5 */ public static void copyToFile(final InputStream inputStream, final File file) throws IOException { try (OutputStream out = openOutputStream(file)) { IOUtils.copy(inputStream, out); } } /** * Copies bytes from the URL {@code source} to a file * {@code destination}. The directories up to {@code destination} * will be created if they don't already exist. {@code destination} * will be overwritten if it already exists. *

* Warning: this method does not set a connection or read timeout and thus * might block forever. Use {@link #copyURLToFile(URL, File, int, int)} * with reasonable timeouts to prevent this. *

* * @param source the {@code URL} to copy bytes from, must not be {@code null} * @param destination the non-directory {@code File} to write bytes to * (possibly overwriting), must not be {@code null} * @throws IOException if {@code source} URL cannot be opened * @throws IOException if {@code destination} is a directory * @throws IOException if {@code destination} cannot be written * @throws IOException if {@code destination} needs creating but can't be * @throws IOException if an IO error occurs during copying */ public static void copyURLToFile(final URL source, final File destination) throws IOException { try (final InputStream stream = source.openStream()) { copyInputStreamToFile(stream, destination); } } /** * Copies bytes from the URL {@code source} to a file {@code destination}. The directories up to * {@code destination} will be created if they don't already exist. {@code destination} will be * overwritten if it already exists. * * @param source the {@code URL} to copy bytes from, must not be {@code null} * @param destination the non-directory {@code File} to write bytes to (possibly overwriting), must not be * {@code null} * @param connectionTimeoutMillis the number of milliseconds until this method will timeout if no connection could * be established to the {@code source} * @param readTimeoutMillis the number of milliseconds until this method will timeout if no data could be read from * the {@code source} * @throws IOException if {@code source} URL cannot be opened * @throws IOException if {@code destination} is a directory * @throws IOException if {@code destination} cannot be written * @throws IOException if {@code destination} needs creating but can't be * @throws IOException if an IO error occurs during copying * @since 2.0 */ public static void copyURLToFile(final URL source, final File destination, final int connectionTimeoutMillis, final int readTimeoutMillis) throws IOException { final URLConnection connection = source.openConnection(); connection.setConnectTimeout(connectionTimeoutMillis); connection.setReadTimeout(readTimeoutMillis); try (final InputStream stream = connection.getInputStream()) { copyInputStreamToFile(stream, destination); } } /** * Creates all parent directories for a File object. * * @param file the File that may need parents, may be null. * @return The parent directory, or {@code null} if the given file does not name a parent * @throws IOException if the directory was not created along with all its parent directories. * @throws IOException if the given file object is not null and not a directory. * @since 2.9.0 */ public static File createParentDirectories(final File file) throws IOException { return mkdirs(getParentFile(file)); } /** * Decodes the specified URL as per RFC 3986, i.e. transforms * percent-encoded octets to characters by decoding with the UTF-8 character * set. This function is primarily intended for usage with * {@link java.net.URL} which unfortunately does not enforce proper URLs. As * such, this method will leniently accept invalid characters or malformed * percent-encoded octets and simply pass them literally through to the * result string. Except for rare edge cases, this will make unencoded URLs * pass through unaltered. * * @param url The URL to decode, may be {@code null}. * @return The decoded URL or {@code null} if the input was * {@code null}. */ static String decodeUrl(final String url) { String decoded = url; if (url != null && url.indexOf('%') >= 0) { final int n = url.length(); final StringBuilder buffer = new StringBuilder(); final ByteBuffer bytes = ByteBuffer.allocate(n); for (int i = 0; i < n; ) { if (url.charAt(i) == '%') { try { do { final byte octet = (byte) Integer.parseInt(url.substring(i + 1, i + 3), 16); bytes.put(octet); i += 3; } while (i < n && url.charAt(i) == '%'); continue; } catch (final RuntimeException e) { // malformed percent-encoded octet, fall through and // append characters literally } finally { if (bytes.position() > 0) { bytes.flip(); buffer.append(StandardCharsets.UTF_8.decode(bytes).toString()); bytes.clear(); } } } buffer.append(url.charAt(i++)); } decoded = buffer.toString(); } return decoded; } /** * Deletes the given File but throws an IOException if it cannot, unlike {@link File#delete()} which returns a * boolean. * * @param file The file to delete. * @return the given file. * @throws IOException if the file cannot be deleted. * @see File#delete() * @since 2.9.0 */ public static File delete(final File file) throws IOException { Objects.requireNonNull(file, "file"); Files.delete(file.toPath()); return file; } /** * Deletes a directory recursively. * * @param directory directory to delete * @throws IOException in case deletion is unsuccessful * @throws IllegalArgumentException if {@code directory} is not a directory */ public static void deleteDirectory(final File directory) throws IOException { Objects.requireNonNull(directory, "directory"); if (!directory.exists()) { return; } if (!isSymlink(directory)) { cleanDirectory(directory); } delete(directory); } /** * Schedules a directory recursively for deletion on JVM exit. * * @param directory directory to delete, must not be {@code null} * @throws NullPointerException if the directory is {@code null} * @throws IOException in case deletion is unsuccessful */ private static void deleteDirectoryOnExit(final File directory) throws IOException { if (!directory.exists()) { return; } directory.deleteOnExit(); if (!isSymlink(directory)) { cleanDirectoryOnExit(directory); } } /** * Deletes a file, never throwing an exception. If file is a directory, delete it and all sub-directories. *

* The difference between File.delete() and this method are: *

*
    *
  • A directory to be deleted does not have to be empty.
  • *
  • No exceptions are thrown when a file or directory cannot be deleted.
  • *
* * @param file file or directory to delete, can be {@code null} * @return {@code true} if the file or directory was deleted, otherwise * {@code false} * * @since 1.4 */ public static boolean deleteQuietly(final File file) { if (file == null) { return false; } try { if (file.isDirectory()) { cleanDirectory(file); } } catch (final Exception ignored) { // ignore } try { return file.delete(); } catch (final Exception ignored) { return false; } } /** * Determines whether the {@code parent} directory contains the {@code child} element (a file or directory). *

* Files are normalized before comparison. *

* * Edge cases: *
    *
  • A {@code directory} must not be null: if null, throw IllegalArgumentException
  • *
  • A {@code directory} must be a directory: if not a directory, throw IllegalArgumentException
  • *
  • A directory does not contain itself: return false
  • *
  • A null child file is not contained in any parent: return false
  • *
* * @param directory the file to consider as the parent. * @param child the file to consider as the child. * @return true is the candidate leaf is under by the specified composite. False otherwise. * @throws IOException if an IO error occurs while checking the files. * @throws NullPointerException if the given {@code File} is {@code null}. * @throws IllegalArgumentException if the given {@code File} does not exist or is not a directory. * @see FilenameUtils#directoryContains(String, String) * @since 2.2 */ public static boolean directoryContains(final File directory, final File child) throws IOException { requireDirectoryExists(directory, "directory"); if (child == null) { return false; } if (!directory.exists() || !child.exists()) { return false; } // Canonicalize paths (normalizes relative paths) return FilenameUtils.directoryContains(directory.getCanonicalPath(), child.getCanonicalPath()); } /** * Internal copy directory method. * * @param srcDir the validated source directory, must not be {@code null}. * @param destDir the validated destination directory, must not be {@code null}. * @param fileFilter the filter to apply, null means copy all directories and files. * @param exclusionList List of files and directories to exclude from the copy, may be null. * @param preserveDirDate preserve the directories last modified dates. * @param copyOptions options specifying how the copy should be done, see {@link StandardCopyOption}. * @throws IOException if the directory was not created along with all its parent directories. * @throws IOException if the given file object is not a directory. */ private static void doCopyDirectory(final File srcDir, final File destDir, final FileFilter fileFilter, final List exclusionList, final boolean preserveDirDate, final CopyOption... copyOptions) throws IOException { // recurse dirs, copy files. final File[] srcFiles = listFiles(srcDir, fileFilter); requireDirectoryIfExists(destDir, "destDir"); mkdirs(destDir); requireCanWrite(destDir, "destDir"); for (final File srcFile : srcFiles) { final File dstFile = new File(destDir, srcFile.getName()); if (exclusionList == null || !exclusionList.contains(srcFile.getCanonicalPath())) { if (srcFile.isDirectory()) { doCopyDirectory(srcFile, dstFile, fileFilter, exclusionList, preserveDirDate, copyOptions); } else { copyFile(srcFile, dstFile, copyOptions); } } } // Do this last, as the above has probably affected directory metadata if (preserveDirDate) { setLastModified(srcDir, destDir); } } /** * Deletes a file or directory. For a directory, delete it and all sub-directories. *

* The difference between File.delete() and this method are: *

*
    *
  • The directory does not have to be empty.
  • *
  • You get an exception when a file or directory cannot be deleted.
  • *
* * @param file file or directory to delete, must not be {@code null}. * @throws NullPointerException if the file is {@code null}. * @throws FileNotFoundException if the file was not found. * @throws IOException in case deletion is unsuccessful. */ public static void forceDelete(final File file) throws IOException { Objects.requireNonNull(file, "file"); final Counters.PathCounters deleteCounters; try { deleteCounters = PathUtils.delete(file.toPath(), PathUtils.EMPTY_LINK_OPTION_ARRAY, StandardDeleteOption.OVERRIDE_READ_ONLY); } catch (final IOException e) { throw new IOException("Cannot delete file: " + file, e); } if (deleteCounters.getFileCounter().get() < 1 && deleteCounters.getDirectoryCounter().get() < 1) { // didn't find a file to delete. throw new FileNotFoundException("File does not exist: " + file); } } /** * Schedules a file to be deleted when JVM exits. * If file is directory delete it and all sub-directories. * * @param file file or directory to delete, must not be {@code null}. * @throws NullPointerException if the file is {@code null}. * @throws IOException in case deletion is unsuccessful. */ public static void forceDeleteOnExit(final File file) throws IOException { Objects.requireNonNull(file, "file"); if (file.isDirectory()) { deleteDirectoryOnExit(file); } else { file.deleteOnExit(); } } /** * Makes a directory, including any necessary but nonexistent parent * directories. If a file already exists with specified name but it is * not a directory then an IOException is thrown. * If the directory cannot be created (or the file already exists but is not a directory) * then an IOException is thrown. * * @param directory directory to create, must not be {@code null}. * @throws IOException if the directory was not created along with all its parent directories. * @throws IOException if the given file object is not a directory. * @throws SecurityException See {@link File#mkdirs()}. */ public static void forceMkdir(final File directory) throws IOException { mkdirs(directory); } /** * Makes any necessary but nonexistent parent directories for a given File. If the parent directory cannot be * created then an IOException is thrown. * * @param file file with parent to create, must not be {@code null}. * @throws NullPointerException if the file is {@code null}. * @throws IOException if the parent directory cannot be created. * @since 2.5 */ public static void forceMkdirParent(final File file) throws IOException { Objects.requireNonNull(file, "file"); final File parent = getParentFile(file); if (parent == null) { return; } forceMkdir(parent); } /** * Construct a file from the set of name elements. * * @param directory the parent directory. * @param names the name elements. * @return the new file. * @since 2.1 */ public static File getFile(final File directory, final String... names) { Objects.requireNonNull(directory, "directory"); Objects.requireNonNull(names, "names"); File file = directory; for (final String name : names) { file = new File(file, name); } return file; } /** * Construct a file from the set of name elements. * * @param names the name elements. * @return the file. * @since 2.1 */ public static File getFile(final String... names) { Objects.requireNonNull(names, "names"); File file = null; for (final String name : names) { if (file == null) { file = new File(name); } else { file = new File(file, name); } } return file; } /** * Gets the parent of the given file. The given file may be bull and a file's parent may as well be null. * * @param file The file to query. * @return The parent file or {@code null}. */ private static File getParentFile(final File file) { return file == null ? null : file.getParentFile(); } /** * Returns a {@link File} representing the system temporary directory. * * @return the system temporary directory. * * @since 2.0 */ public static File getTempDirectory() { return new File(getTempDirectoryPath()); } /** * Returns the path to the system temporary directory. * * @return the path to the system temporary directory. * * @since 2.0 */ public static String getTempDirectoryPath() { return System.getProperty("java.io.tmpdir"); } /** * Returns a {@link File} representing the user's home directory. * * @return the user's home directory. * * @since 2.0 */ public static File getUserDirectory() { return new File(getUserDirectoryPath()); } /** * Returns the path to the user's home directory. * * @return the path to the user's home directory. * * @since 2.0 */ public static String getUserDirectoryPath() { return System.getProperty("user.home"); } /** * Tests whether the specified {@code File} is a directory or not. Implemented as a * null-safe delegate to {@code Files.isDirectory(Path path, LinkOption... options)}. * * @param file the path to the file. * @param options options indicating how symbolic links are handled * @return {@code true} if the file is a directory; {@code false} if * the path is null, the file does not exist, is not a directory, or it cannot * be determined if the file is a directory or not. * @throws SecurityException In the case of the default provider, and a security manager is installed, the * {@link SecurityManager#checkRead(String) checkRead} method is invoked to check read * access to the directory. * @since 2.9.0 */ public static boolean isDirectory(final File file, final LinkOption... options) { return file != null && Files.isDirectory(file.toPath(), options); } /** * Tests whether the directory is empty. * * @param directory the directory to query. * @return whether the directory is empty. * @throws IOException if an I/O error occurs. * @throws NotDirectoryException if the file could not otherwise be opened because it is not a directory * (optional specific exception). * @since 2.9.0 */ public static boolean isEmptyDirectory(final File directory) throws IOException { return PathUtils.isEmptyDirectory(directory.toPath()); } /** * Tests if the specified {@code File} is newer than the specified {@code ChronoLocalDate} * at the current time. * *

Note: The input date is assumed to be in the system default time-zone with the time * part set to the current time. To use a non-default time-zone use the method * {@link #isFileNewer(File, ChronoLocalDateTime, ZoneId) * isFileNewer(file, chronoLocalDate.atTime(LocalTime.now(zoneId)), zoneId)} where * {@code zoneId} is a valid {@link ZoneId}. * * @param file the {@code File} of which the modification date must be compared. * @param chronoLocalDate the date reference. * @return true if the {@code File} exists and has been modified after the given * {@code ChronoLocalDate} at the current time. * @throws NullPointerException if the file or local date is {@code null}. * * @since 2.8.0 */ public static boolean isFileNewer(final File file, final ChronoLocalDate chronoLocalDate) { return isFileNewer(file, chronoLocalDate, LocalTime.now()); } /** * Tests if the specified {@code File} is newer than the specified {@code ChronoLocalDate} * at the specified time. * *

Note: The input date and time are assumed to be in the system default time-zone. To use a * non-default time-zone use the method {@link #isFileNewer(File, ChronoLocalDateTime, ZoneId) * isFileNewer(file, chronoLocalDate.atTime(localTime), zoneId)} where {@code zoneId} is a valid * {@link ZoneId}. * * @param file the {@code File} of which the modification date must be compared. * @param chronoLocalDate the date reference. * @param localTime the time reference. * @return true if the {@code File} exists and has been modified after the given * {@code ChronoLocalDate} at the given time. * @throws NullPointerException if the file, local date or zone ID is {@code null}. * * @since 2.8.0 */ public static boolean isFileNewer(final File file, final ChronoLocalDate chronoLocalDate, final LocalTime localTime) { Objects.requireNonNull(chronoLocalDate, "chronoLocalDate"); Objects.requireNonNull(localTime, "localTime"); return isFileNewer(file, chronoLocalDate.atTime(localTime)); } /** * Tests if the specified {@code File} is newer than the specified {@code ChronoLocalDateTime} * at the system-default time zone. * *

Note: The input date and time is assumed to be in the system default time-zone. To use a * non-default time-zone use the method {@link #isFileNewer(File, ChronoLocalDateTime, ZoneId) * isFileNewer(file, chronoLocalDateTime, zoneId)} where {@code zoneId} is a valid * {@link ZoneId}. * * @param file the {@code File} of which the modification date must be compared. * @param chronoLocalDateTime the date reference. * @return true if the {@code File} exists and has been modified after the given * {@code ChronoLocalDateTime} at the system-default time zone. * @throws NullPointerException if the file or local date time is {@code null}. * * @since 2.8.0 */ public static boolean isFileNewer(final File file, final ChronoLocalDateTime chronoLocalDateTime) { return isFileNewer(file, chronoLocalDateTime, ZoneId.systemDefault()); } /** * Tests if the specified {@code File} is newer than the specified {@code ChronoLocalDateTime} * at the specified {@code ZoneId}. * * @param file the {@code File} of which the modification date must be compared. * @param chronoLocalDateTime the date reference. * @param zoneId the time zone. * @return true if the {@code File} exists and has been modified after the given * {@code ChronoLocalDateTime} at the given {@code ZoneId}. * @throws NullPointerException if the file, local date time or zone ID is {@code null}. * * @since 2.8.0 */ public static boolean isFileNewer(final File file, final ChronoLocalDateTime chronoLocalDateTime, final ZoneId zoneId) { Objects.requireNonNull(chronoLocalDateTime, "chronoLocalDateTime"); Objects.requireNonNull(zoneId, "zoneId"); return isFileNewer(file, chronoLocalDateTime.atZone(zoneId)); } /** * Tests if the specified {@code File} is newer than the specified {@code ChronoZonedDateTime}. * * @param file the {@code File} of which the modification date must be compared. * @param chronoZonedDateTime the date reference. * @return true if the {@code File} exists and has been modified after the given * {@code ChronoZonedDateTime}. * @throws NullPointerException if the file or zoned date time is {@code null}. * * @since 2.8.0 */ public static boolean isFileNewer(final File file, final ChronoZonedDateTime chronoZonedDateTime) { Objects.requireNonNull(chronoZonedDateTime, "chronoZonedDateTime"); return isFileNewer(file, chronoZonedDateTime.toInstant()); } /** * Tests if the specified {@code File} is newer than the specified {@code Date}. * * @param file the {@code File} of which the modification date must be compared. * @param date the date reference. * @return true if the {@code File} exists and has been modified * after the given {@code Date}. * @throws NullPointerException if the file or date is {@code null}. */ public static boolean isFileNewer(final File file, final Date date) { Objects.requireNonNull(date, "date"); return isFileNewer(file, date.getTime()); } /** * Tests if the specified {@code File} is newer than the reference {@code File}. * * @param file the {@code File} of which the modification date must be compared. * @param reference the {@code File} of which the modification date is used. * @return true if the {@code File} exists and has been modified more * recently than the reference {@code File}. * @throws NullPointerException if the file or reference file is {@code null}. * @throws IllegalArgumentException if the reference file doesn't exist. */ public static boolean isFileNewer(final File file, final File reference) { requireExists(reference, "reference"); return isFileNewer(file, lastModifiedUnchecked(reference)); } /** * Tests if the specified {@code File} is newer than the specified {@code Instant}. * * @param file the {@code File} of which the modification date must be compared. * @param instant the date reference. * @return true if the {@code File} exists and has been modified after the given {@code Instant}. * @throws NullPointerException if the file or instant is {@code null}. * * @since 2.8.0 */ public static boolean isFileNewer(final File file, final Instant instant) { Objects.requireNonNull(instant, "instant"); return isFileNewer(file, instant.toEpochMilli()); } /** * Tests if the specified {@code File} is newer than the specified time reference. * * @param file the {@code File} of which the modification date must be compared. * @param timeMillis the time reference measured in milliseconds since the * epoch (00:00:00 GMT, January 1, 1970). * @return true if the {@code File} exists and has been modified after the given time reference. * @throws NullPointerException if the file is {@code null}. */ public static boolean isFileNewer(final File file, final long timeMillis) { Objects.requireNonNull(file, "file"); return file.exists() && lastModifiedUnchecked(file) > timeMillis; } /** * Tests if the specified {@code File} is older than the specified {@code ChronoLocalDate} * at the current time. * *

Note: The input date is assumed to be in the system default time-zone with the time * part set to the current time. To use a non-default time-zone use the method * {@link #isFileOlder(File, ChronoLocalDateTime, ZoneId) * isFileOlder(file, chronoLocalDate.atTime(LocalTime.now(zoneId)), zoneId)} where * {@code zoneId} is a valid {@link ZoneId}. * * @param file the {@code File} of which the modification date must be compared. * @param chronoLocalDate the date reference. * @return true if the {@code File} exists and has been modified before the given * {@code ChronoLocalDate} at the current time. * @throws NullPointerException if the file or local date is {@code null}. * @see ZoneId#systemDefault() * @see LocalTime#now() * * @since 2.8.0 */ public static boolean isFileOlder(final File file, final ChronoLocalDate chronoLocalDate) { return isFileOlder(file, chronoLocalDate, LocalTime.now()); } /** * Tests if the specified {@code File} is older than the specified {@code ChronoLocalDate} * at the specified {@code LocalTime}. * *

Note: The input date and time are assumed to be in the system default time-zone. To use a * non-default time-zone use the method {@link #isFileOlder(File, ChronoLocalDateTime, ZoneId) * isFileOlder(file, chronoLocalDate.atTime(localTime), zoneId)} where {@code zoneId} is a valid * {@link ZoneId}. * * @param file the {@code File} of which the modification date must be compared. * @param chronoLocalDate the date reference. * @param localTime the time reference. * @return true if the {@code File} exists and has been modified before the * given {@code ChronoLocalDate} at the specified time. * @throws NullPointerException if the file, local date or local time is {@code null}. * @see ZoneId#systemDefault() * * @since 2.8.0 */ public static boolean isFileOlder(final File file, final ChronoLocalDate chronoLocalDate, final LocalTime localTime) { Objects.requireNonNull(chronoLocalDate, "chronoLocalDate"); Objects.requireNonNull(localTime, "localTime"); return isFileOlder(file, chronoLocalDate.atTime(localTime)); } /** * Tests if the specified {@code File} is older than the specified {@code ChronoLocalDateTime} * at the system-default time zone. * *

Note: The input date and time is assumed to be in the system default time-zone. To use a * non-default time-zone use the method {@link #isFileOlder(File, ChronoLocalDateTime, ZoneId) * isFileOlder(file, chronoLocalDateTime, zoneId)} where {@code zoneId} is a valid * {@link ZoneId}. * * @param file the {@code File} of which the modification date must be compared. * @param chronoLocalDateTime the date reference. * @return true if the {@code File} exists and has been modified before the given * {@code ChronoLocalDateTime} at the system-default time zone. * @throws NullPointerException if the file or local date time is {@code null}. * @see ZoneId#systemDefault() * * @since 2.8.0 */ public static boolean isFileOlder(final File file, final ChronoLocalDateTime chronoLocalDateTime) { return isFileOlder(file, chronoLocalDateTime, ZoneId.systemDefault()); } /** * Tests if the specified {@code File} is older than the specified {@code ChronoLocalDateTime} * at the specified {@code ZoneId}. * * @param file the {@code File} of which the modification date must be compared. * @param chronoLocalDateTime the date reference. * @param zoneId the time zone. * @return true if the {@code File} exists and has been modified before the given * {@code ChronoLocalDateTime} at the given {@code ZoneId}. * @throws NullPointerException if the file, local date time or zone ID is {@code null}. * * @since 2.8.0 */ public static boolean isFileOlder(final File file, final ChronoLocalDateTime chronoLocalDateTime, final ZoneId zoneId) { Objects.requireNonNull(chronoLocalDateTime, "chronoLocalDateTime"); Objects.requireNonNull(zoneId, "zoneId"); return isFileOlder(file, chronoLocalDateTime.atZone(zoneId)); } /** * Tests if the specified {@code File} is older than the specified {@code ChronoZonedDateTime}. * * @param file the {@code File} of which the modification date must be compared. * @param chronoZonedDateTime the date reference. * @return true if the {@code File} exists and has been modified before the given * {@code ChronoZonedDateTime}. * @throws NullPointerException if the file or zoned date time is {@code null}. * * @since 2.8.0 */ public static boolean isFileOlder(final File file, final ChronoZonedDateTime chronoZonedDateTime) { Objects.requireNonNull(chronoZonedDateTime, "chronoZonedDateTime"); return isFileOlder(file, chronoZonedDateTime.toInstant()); } /** * Tests if the specified {@code File} is older than the specified {@code Date}. * * @param file the {@code File} of which the modification date must be compared. * @param date the date reference. * @return true if the {@code File} exists and has been modified before the given {@code Date}. * @throws NullPointerException if the file or date is {@code null}. */ public static boolean isFileOlder(final File file, final Date date) { Objects.requireNonNull(date, "date"); return isFileOlder(file, date.getTime()); } /** * Tests if the specified {@code File} is older than the reference {@code File}. * * @param file the {@code File} of which the modification date must be compared. * @param reference the {@code File} of which the modification date is used. * @return true if the {@code File} exists and has been modified before the reference {@code File}. * @throws NullPointerException if the file or reference file is {@code null}. * @throws IllegalArgumentException if the reference file doesn't exist. */ public static boolean isFileOlder(final File file, final File reference) { requireExists(reference, "reference"); return isFileOlder(file, lastModifiedUnchecked(reference)); } /** * Tests if the specified {@code File} is older than the specified {@code Instant}. * * @param file the {@code File} of which the modification date must be compared. * @param instant the date reference. * @return true if the {@code File} exists and has been modified before the given {@code Instant}. * @throws NullPointerException if the file or instant is {@code null}. * @since 2.8.0 */ public static boolean isFileOlder(final File file, final Instant instant) { Objects.requireNonNull(instant, "instant"); return isFileOlder(file, instant.toEpochMilli()); } /** * Tests if the specified {@code File} is older than the specified time reference. * * @param file the {@code File} of which the modification date must be compared. * @param timeMillis the time reference measured in milliseconds since the * epoch (00:00:00 GMT, January 1, 1970). * @return true if the {@code File} exists and has been modified before the given time reference. * @throws NullPointerException if the file is {@code null}. */ public static boolean isFileOlder(final File file, final long timeMillis) { Objects.requireNonNull(file, "file"); return file.exists() && lastModifiedUnchecked(file) < timeMillis; } /** * Tests whether the specified {@code File} is a regular file or not. Implemented as a * null-safe delegate to {@code Files.isRegularFile(Path path, LinkOption... options)}. * * @param file the path to the file. * @param options options indicating how symbolic links are handled * @return {@code true} if the file is a regular file; {@code false} if * the path is null, the file does not exist, is not a directory, or it cannot * be determined if the file is a regular file or not. * @throws SecurityException In the case of the default provider, and a security manager is installed, the * {@link SecurityManager#checkRead(String) checkRead} method is invoked to check read * access to the directory. * @since 2.9.0 */ public static boolean isRegularFile(final File file, final LinkOption... options) { return file != null && Files.isRegularFile(file.toPath(), options); } /** * Tests whether the specified file is a symbolic link rather than an actual file. *

* This method delegates to {@link Files#isSymbolicLink(Path path)} *

* * @param file the file to test. * @return true if the file is a symbolic link, see {@link Files#isSymbolicLink(Path path)}. * @since 2.0 * @see Files#isSymbolicLink(Path) */ public static boolean isSymlink(final File file) { return file != null && Files.isSymbolicLink(file.toPath()); } /** * Iterates over the files in given directory (and optionally * its subdirectories). *

* The resulting iterator MUST be consumed in its entirety in order to close its underlying stream. *

*

* All files found are filtered by an IOFileFilter. *

* * @param directory the directory to search in * @param fileFilter filter to apply when finding files. * @param dirFilter optional filter to apply when finding subdirectories. * If this parameter is {@code null}, subdirectories will not be included in the * search. Use TrueFileFilter.INSTANCE to match all directories. * @return an iterator of java.io.File for the matching files * @see org.apache.commons.io.filefilter.FileFilterUtils * @see org.apache.commons.io.filefilter.NameFileFilter * @since 1.2 */ public static Iterator iterateFiles(final File directory, final IOFileFilter fileFilter, final IOFileFilter dirFilter) { return listFiles(directory, fileFilter, dirFilter).iterator(); } /** * Iterates over the files in a given directory (and optionally * its subdirectories) which match an array of extensions. *

* The resulting iterator MUST be consumed in its entirety in order to close its underlying stream. *

*

* * @param directory the directory to search in * @param extensions an array of extensions, ex. {"java","xml"}. If this * parameter is {@code null}, all files are returned. * @param recursive if true all subdirectories are searched as well * @return an iterator of java.io.File with the matching files * @since 1.2 */ public static Iterator iterateFiles(final File directory, final String[] extensions, final boolean recursive) { try { return StreamIterator.iterator(streamFiles(directory, recursive, extensions)); } catch (final IOException e) { throw new UncheckedIOException(directory.toString(), e); } } /** * Iterates over the files in given directory (and optionally * its subdirectories). *

* The resulting iterator MUST be consumed in its entirety in order to close its underlying stream. *

*

* All files found are filtered by an IOFileFilter. *

*

* The resulting iterator includes the subdirectories themselves. *

* * @param directory the directory to search in * @param fileFilter filter to apply when finding files. * @param dirFilter optional filter to apply when finding subdirectories. * If this parameter is {@code null}, subdirectories will not be included in the * search. Use TrueFileFilter.INSTANCE to match all directories. * @return an iterator of java.io.File for the matching files * @see org.apache.commons.io.filefilter.FileFilterUtils * @see org.apache.commons.io.filefilter.NameFileFilter * @since 2.2 */ public static Iterator iterateFilesAndDirs(final File directory, final IOFileFilter fileFilter, final IOFileFilter dirFilter) { return listFilesAndDirs(directory, fileFilter, dirFilter).iterator(); } /** * Returns the last modification time in milliseconds via * {@link java.nio.file.Files#getLastModifiedTime(Path, LinkOption...)}. *

* Use this method to avoid issues with {@link File#lastModified()} like * JDK-8177809 where {@link File#lastModified()} is * losing milliseconds (always ends in 000). This bug exists in OpenJDK 8 and 9, and is fixed in 10. *

* * @param file The File to query. * @return See {@link java.nio.file.attribute.FileTime#toMillis()}. * @throws IOException if an I/O error occurs. * @since 2.9.0 */ public static long lastModified(final File file) throws IOException { // https://bugs.openjdk.java.net/browse/JDK-8177809 // File.lastModified() is losing milliseconds (always ends in 000) // This bug is in OpenJDK 8 and 9, and fixed in 10. return Files.getLastModifiedTime(Objects.requireNonNull(file.toPath(), "file")).toMillis(); } /** * Returns the last modification time in milliseconds via * {@link java.nio.file.Files#getLastModifiedTime(Path, LinkOption...)}. *

* Use this method to avoid issues with {@link File#lastModified()} like * JDK-8177809 where {@link File#lastModified()} is * losing milliseconds (always ends in 000). This bug exists in OpenJDK 8 and 9, and is fixed in 10. *

* * @param file The File to query. * @return See {@link java.nio.file.attribute.FileTime#toMillis()}. * @throws UncheckedIOException if an I/O error occurs. * @since 2.9.0 */ public static long lastModifiedUnchecked(final File file) { // https://bugs.openjdk.java.net/browse/JDK-8177809 // File.lastModified() is losing milliseconds (always ends in 000) // This bug is in OpenJDK 8 and 9, and fixed in 10. try { return lastModified(file); } catch (final IOException e) { throw new UncheckedIOException(file.toString(), e); } } /** * Returns an Iterator for the lines in a {@code File} using the default encoding for the VM. * * @param file the file to open for input, must not be {@code null} * @return an Iterator of the lines in the file, never {@code null} * @throws NullPointerException if file is {@code null}. * @throws FileNotFoundException if the file does not exist, is a directory rather than a regular file, or for some * other reason cannot be opened for reading. * @throws IOException if an I/O error occurs. * @see #lineIterator(File, String) * @since 1.3 */ public static LineIterator lineIterator(final File file) throws IOException { return lineIterator(file, null); } /** * Returns an Iterator for the lines in a {@code File}. *

* This method opens an {@code InputStream} for the file. * When you have finished with the iterator you should close the stream * to free internal resources. This can be done by calling the * {@link LineIterator#close()} or * {@link LineIterator#closeQuietly(LineIterator)} method. *

*

* The recommended usage pattern is: *

*
     * LineIterator it = FileUtils.lineIterator(file, "UTF-8");
     * try {
     *   while (it.hasNext()) {
     *     String line = it.nextLine();
     *     /// do something with line
     *   }
     * } finally {
     *   LineIterator.closeQuietly(iterator);
     * }
     * 
*

* If an exception occurs during the creation of the iterator, the * underlying stream is closed. *

* * @param file the file to open for input, must not be {@code null} * @param charsetName the name of the requested charset, {@code null} means platform default * @return an Iterator of the lines in the file, never {@code null} * @throws NullPointerException if file is {@code null}. * @throws FileNotFoundException if the file does not exist, is a directory rather than a regular file, or for some * other reason cannot be opened for reading. * @throws IOException if an I/O error occurs. * @since 1.2 */ public static LineIterator lineIterator(final File file, final String charsetName) throws IOException { InputStream inputStream = null; try { inputStream = openInputStream(file); return IOUtils.lineIterator(inputStream, charsetName); } catch (final IOException | RuntimeException ex) { IOUtils.closeQuietly(inputStream, ex::addSuppressed); throw ex; } } private static AccumulatorPathVisitor listAccumulate(final File directory, final IOFileFilter fileFilter, final IOFileFilter dirFilter) throws IOException { final boolean isDirFilterSet = dirFilter != null; final FileEqualsFileFilter rootDirFilter = new FileEqualsFileFilter(directory); final PathFilter dirPathFilter = isDirFilterSet ? rootDirFilter.or(dirFilter) : rootDirFilter; final AccumulatorPathVisitor visitor = new AccumulatorPathVisitor(Counters.noopPathCounters(), fileFilter, dirPathFilter); Files.walkFileTree(directory.toPath(), Collections.emptySet(), toMaxDepth(isDirFilterSet), visitor); return visitor; } /** * Lists files in a directory, asserting that the supplied directory exists and is a directory. * * @param directory The directory to list * @param fileFilter Optional file filter, may be null. * @return The files in the directory, never {@code null}. * @throws NullPointerException if directory is {@code null}. * @throws IllegalArgumentException if directory does not exist or is not a directory. * @throws IOException if an I/O error occurs. */ private static File[] listFiles(final File directory, final FileFilter fileFilter) throws IOException { requireDirectoryExists(directory, "directory"); final File[] files = fileFilter == null ? directory.listFiles() : directory.listFiles(fileFilter); if (files == null) { // null if the directory does not denote a directory, or if an I/O error occurs. throw new IOException("Unknown I/O error listing contents of directory: " + directory); } return files; } /** * Finds files within a given directory (and optionally its * subdirectories). All files found are filtered by an IOFileFilter. *

* If your search should recurse into subdirectories you can pass in * an IOFileFilter for directories. You don't need to bind a * DirectoryFileFilter (via logical AND) to this filter. This method does * that for you. *

*

* An example: If you want to search through all directories called * "temp" you pass in {@code FileFilterUtils.NameFileFilter("temp")} *

*

* Another common usage of this method is find files in a directory * tree but ignoring the directories generated CVS. You can simply pass * in {@code FileFilterUtils.makeCVSAware(null)}. *

* * @param directory the directory to search in * @param fileFilter filter to apply when finding files. Must not be {@code null}, * use {@link TrueFileFilter#INSTANCE} to match all files in selected directories. * @param dirFilter optional filter to apply when finding subdirectories. * If this parameter is {@code null}, subdirectories will not be included in the * search. Use {@link TrueFileFilter#INSTANCE} to match all directories. * @return a collection of java.io.File with the matching files * @see org.apache.commons.io.filefilter.FileFilterUtils * @see org.apache.commons.io.filefilter.NameFileFilter */ public static Collection listFiles( final File directory, final IOFileFilter fileFilter, final IOFileFilter dirFilter) { try { final AccumulatorPathVisitor visitor = listAccumulate(directory, fileFilter, dirFilter); return visitor.getFileList().stream().map(Path::toFile).collect(Collectors.toList()); } catch (final IOException e) { throw new UncheckedIOException(directory.toString(), e); } } /** * Finds files within a given directory (and optionally its subdirectories) * which match an array of extensions. * * @param directory the directory to search in * @param extensions an array of extensions, ex. {"java","xml"}. If this * parameter is {@code null}, all files are returned. * @param recursive if true all subdirectories are searched as well * @return a collection of java.io.File with the matching files */ public static Collection listFiles(final File directory, final String[] extensions, final boolean recursive) { try { return toList(streamFiles(directory, recursive, extensions)); } catch (final IOException e) { throw new UncheckedIOException(directory.toString(), e); } } /** * Finds files within a given directory (and optionally its * subdirectories). All files found are filtered by an IOFileFilter. *

* The resulting collection includes the starting directory and * any subdirectories that match the directory filter. *

* * @param directory the directory to search in * @param fileFilter filter to apply when finding files. * @param dirFilter optional filter to apply when finding subdirectories. * If this parameter is {@code null}, subdirectories will not be included in the * search. Use TrueFileFilter.INSTANCE to match all directories. * @return a collection of java.io.File with the matching files * @see org.apache.commons.io.FileUtils#listFiles * @see org.apache.commons.io.filefilter.FileFilterUtils * @see org.apache.commons.io.filefilter.NameFileFilter * @since 2.2 */ public static Collection listFilesAndDirs( final File directory, final IOFileFilter fileFilter, final IOFileFilter dirFilter) { try { final AccumulatorPathVisitor visitor = listAccumulate(directory, fileFilter, dirFilter); final List list = visitor.getFileList(); list.addAll(visitor.getDirList()); return list.stream().map(Path::toFile).collect(Collectors.toList()); } catch (final IOException e) { throw new UncheckedIOException(directory.toString(), e); } } /** * Calls {@link File#mkdirs()} and throws an exception on failure. * * @param directory the receiver for {@code mkdirs()}, may be null. * @return the given file, may be null. * @throws IOException if the directory was not created along with all its parent directories. * @throws IOException if the given file object is not a directory. * @throws SecurityException See {@link File#mkdirs()}. * @see File#mkdirs() */ private static File mkdirs(final File directory) throws IOException { if ((directory != null) && (!directory.mkdirs() && !directory.isDirectory())) { throw new IOException("Cannot create directory '" + directory + "'."); } return directory; } /** * Moves a directory. *

* When the destination directory is on another file system, do a "copy and delete". *

* * @param srcDir the directory to be moved. * @param destDir the destination directory. * @throws NullPointerException if any of the given {@code File}s are {@code null}. * @throws IllegalArgumentException if the source or destination is invalid. * @throws FileNotFoundException if the source does not exist. * @throws IOException if an error occurs or setting the last-modified time didn't succeeded. * @since 1.4 */ public static void moveDirectory(final File srcDir, final File destDir) throws IOException { validateMoveParameters(srcDir, destDir); requireDirectory(srcDir, "srcDir"); requireAbsent(destDir, "destDir"); if (!srcDir.renameTo(destDir)) { if (destDir.getCanonicalPath().startsWith(srcDir.getCanonicalPath() + File.separator)) { throw new IOException("Cannot move directory: " + srcDir + " to a subdirectory of itself: " + destDir); } copyDirectory(srcDir, destDir); deleteDirectory(srcDir); if (srcDir.exists()) { throw new IOException("Failed to delete original directory '" + srcDir + "' after copy to '" + destDir + "'"); } } } /** * Moves a directory to another directory. * * @param src the file to be moved. * @param destDir the destination file. * @param createDestDir If {@code true} create the destination directory, otherwise if {@code false} throw an * IOException. * @throws NullPointerException if any of the given {@code File}s are {@code null}. * @throws IllegalArgumentException if the source or destination is invalid. * @throws FileNotFoundException if the source does not exist. * @throws IOException if an error occurs or setting the last-modified time didn't succeeded. * @since 1.4 */ public static void moveDirectoryToDirectory(final File src, final File destDir, final boolean createDestDir) throws IOException { validateMoveParameters(src, destDir); if (!destDir.isDirectory()) { if (destDir.exists()) { throw new IOException("Destination '" + destDir + "' is not a directory"); } if (!createDestDir) { throw new FileNotFoundException("Destination directory '" + destDir + "' does not exist [createDestDir=" + false + "]"); } mkdirs(destDir); } moveDirectory(src, new File(destDir, src.getName())); } /** * Moves a file preserving attributes. *

* Shorthand for {@code moveFile(srcFile, destFile, StandardCopyOption.COPY_ATTRIBUTES)}. *

*

* When the destination file is on another file system, do a "copy and delete". *

* * @param srcFile the file to be moved. * @param destFile the destination file. * @throws NullPointerException if any of the given {@code File}s are {@code null}. * @throws FileExistsException if the destination file exists. * @throws IOException if source or destination is invalid. * @throws IOException if an error occurs. * @since 1.4 */ public static void moveFile(final File srcFile, final File destFile) throws IOException { moveFile(srcFile, destFile, StandardCopyOption.COPY_ATTRIBUTES); } /** * Moves a file. *

* When the destination file is on another file system, do a "copy and delete". *

* * @param srcFile the file to be moved. * @param destFile the destination file. * @param copyOptions Copy options. * @throws NullPointerException if any of the given {@code File}s are {@code null}. * @throws FileExistsException if the destination file exists. * @throws IOException if source or destination is invalid. * @throws IOException if an error occurs or setting the last-modified time didn't succeeded. * @since 2.9.0 */ public static void moveFile(final File srcFile, final File destFile, final CopyOption... copyOptions) throws IOException { validateMoveParameters(srcFile, destFile); requireFile(srcFile, "srcFile"); requireAbsent(destFile, null); final boolean rename = srcFile.renameTo(destFile); if (!rename) { copyFile(srcFile, destFile, copyOptions); if (!srcFile.delete()) { FileUtils.deleteQuietly(destFile); throw new IOException("Failed to delete original file '" + srcFile + "' after copy to '" + destFile + "'"); } } } /** * Moves a file to a directory. * * @param srcFile the file to be moved. * @param destDir the destination file. * @param createDestDir If {@code true} create the destination directory, otherwise if {@code false} throw an * IOException. * @throws NullPointerException if any of the given {@code File}s are {@code null}. * @throws FileExistsException if the destination file exists. * @throws IOException if source or destination is invalid. * @throws IOException if an error occurs or setting the last-modified time didn't succeeded. * @since 1.4 */ public static void moveFileToDirectory(final File srcFile, final File destDir, final boolean createDestDir) throws IOException { validateMoveParameters(srcFile, destDir); if (!destDir.exists() && createDestDir) { mkdirs(destDir); } requireExistsChecked(destDir, "destDir"); requireDirectory(destDir, "destDir"); moveFile(srcFile, new File(destDir, srcFile.getName())); } /** * Moves a file or directory to the destination directory. *

* When the destination is on another file system, do a "copy and delete". *

* * @param src the file or directory to be moved. * @param destDir the destination directory. * @param createDestDir If {@code true} create the destination directory, otherwise if {@code false} throw an * IOException. * @throws NullPointerException if any of the given {@code File}s are {@code null}. * @throws FileExistsException if the directory or file exists in the destination directory. * @throws IOException if source or destination is invalid. * @throws IOException if an error occurs or setting the last-modified time didn't succeeded. * @since 1.4 */ public static void moveToDirectory(final File src, final File destDir, final boolean createDestDir) throws IOException { validateMoveParameters(src, destDir); if (src.isDirectory()) { moveDirectoryToDirectory(src, destDir, createDestDir); } else { moveFileToDirectory(src, destDir, createDestDir); } } /** * Opens a {@link FileInputStream} for the specified file, providing better error messages than simply calling * {@code new FileInputStream(file)}. *

* At the end of the method either the stream will be successfully opened, or an exception will have been thrown. *

*

* An exception is thrown if the file does not exist. An exception is thrown if the file object exists but is a * directory. An exception is thrown if the file exists but cannot be read. *

* * @param file the file to open for input, must not be {@code null} * @return a new {@link FileInputStream} for the specified file * @throws NullPointerException if file is {@code null}. * @throws FileNotFoundException if the file does not exist, is a directory rather than a regular file, or for some * other reason cannot be opened for reading. * @throws IOException See FileNotFoundException above, FileNotFoundException is a subclass of IOException. * @since 1.3 */ public static FileInputStream openInputStream(final File file) throws IOException { Objects.requireNonNull(file, "file"); return new FileInputStream(file); } /** * Opens a {@link FileOutputStream} for the specified file, checking and * creating the parent directory if it does not exist. *

* At the end of the method either the stream will be successfully opened, * or an exception will have been thrown. *

*

* The parent directory will be created if it does not exist. * The file will be created if it does not exist. * An exception is thrown if the file object exists but is a directory. * An exception is thrown if the file exists but cannot be written to. * An exception is thrown if the parent directory cannot be created. *

* * @param file the file to open for output, must not be {@code null} * @return a new {@link FileOutputStream} for the specified file * @throws NullPointerException if the file object is {@code null}. * @throws IllegalArgumentException if the file object is a directory * @throws IllegalArgumentException if the file is not writable. * @throws IOException if the directories could not be created. * @since 1.3 */ public static FileOutputStream openOutputStream(final File file) throws IOException { return openOutputStream(file, false); } /** * Opens a {@link FileOutputStream} for the specified file, checking and * creating the parent directory if it does not exist. *

* At the end of the method either the stream will be successfully opened, * or an exception will have been thrown. *

*

* The parent directory will be created if it does not exist. * The file will be created if it does not exist. * An exception is thrown if the file object exists but is a directory. * An exception is thrown if the file exists but cannot be written to. * An exception is thrown if the parent directory cannot be created. *

* * @param file the file to open for output, must not be {@code null} * @param append if {@code true}, then bytes will be added to the * end of the file rather than overwriting * @return a new {@link FileOutputStream} for the specified file * @throws NullPointerException if the file object is {@code null}. * @throws IllegalArgumentException if the file object is a directory * @throws IllegalArgumentException if the file is not writable. * @throws IOException if the directories could not be created. * @since 2.1 */ public static FileOutputStream openOutputStream(final File file, final boolean append) throws IOException { Objects.requireNonNull(file, "file"); if (file.exists()) { requireFile(file, "file"); requireCanWrite(file, "file"); } else { createParentDirectories(file); } return new FileOutputStream(file, append); } /** * Reads the contents of a file into a byte array. * The file is always closed. * * @param file the file to read, must not be {@code null} * @return the file contents, never {@code null} * @throws NullPointerException if file is {@code null}. * @throws FileNotFoundException if the file does not exist, is a directory rather than a regular file, or for some * other reason cannot be opened for reading. * @throws IOException if an I/O error occurs. * @since 1.1 */ public static byte[] readFileToByteArray(final File file) throws IOException { try (InputStream inputStream = openInputStream(file)) { final long fileLength = file.length(); // file.length() may return 0 for system-dependent entities, treat 0 as unknown length - see IO-453 return fileLength > 0 ? IOUtils.toByteArray(inputStream, fileLength) : IOUtils.toByteArray(inputStream); } } /** * Reads the contents of a file into a String using the default encoding for the VM. * The file is always closed. * * @param file the file to read, must not be {@code null} * @return the file contents, never {@code null} * @throws NullPointerException if file is {@code null}. * @throws FileNotFoundException if the file does not exist, is a directory rather than a regular file, or for some * other reason cannot be opened for reading. * @throws IOException if an I/O error occurs. * @since 1.3.1 * @deprecated 2.5 use {@link #readFileToString(File, Charset)} instead (and specify the appropriate encoding) */ @Deprecated public static String readFileToString(final File file) throws IOException { return readFileToString(file, Charset.defaultCharset()); } /** * Reads the contents of a file into a String. * The file is always closed. * * @param file the file to read, must not be {@code null} * @param charsetName the name of the requested charset, {@code null} means platform default * @return the file contents, never {@code null} * @throws NullPointerException if file is {@code null}. * @throws FileNotFoundException if the file does not exist, is a directory rather than a regular file, or for some * other reason cannot be opened for reading. * @throws IOException if an I/O error occurs. * @since 2.3 */ public static String readFileToString(final File file, final Charset charsetName) throws IOException { try (InputStream inputStream = openInputStream(file)) { return IOUtils.toString(inputStream, Charsets.toCharset(charsetName)); } } /** * Reads the contents of a file into a String. The file is always closed. * * @param file the file to read, must not be {@code null} * @param charsetName the name of the requested charset, {@code null} means platform default * @return the file contents, never {@code null} * @throws NullPointerException if file is {@code null}. * @throws FileNotFoundException if the file does not exist, is a directory rather than a regular file, or for some * other reason cannot be opened for reading. * @throws IOException if an I/O error occurs. * @throws java.nio.charset.UnsupportedCharsetException thrown instead of {@link java.io * .UnsupportedEncodingException} in version 2.2 if the named charset is unavailable. * @since 2.3 */ public static String readFileToString(final File file, final String charsetName) throws IOException { return readFileToString(file, Charsets.toCharset(charsetName)); } /** * Reads the contents of a file line by line to a List of Strings using the default encoding for the VM. * The file is always closed. * * @param file the file to read, must not be {@code null} * @return the list of Strings representing each line in the file, never {@code null} * @throws NullPointerException if file is {@code null}. * @throws FileNotFoundException if the file does not exist, is a directory rather than a regular file, or for some * other reason cannot be opened for reading. * @throws IOException if an I/O error occurs. * @since 1.3 * @deprecated 2.5 use {@link #readLines(File, Charset)} instead (and specify the appropriate encoding) */ @Deprecated public static List readLines(final File file) throws IOException { return readLines(file, Charset.defaultCharset()); } /** * Reads the contents of a file line by line to a List of Strings. * The file is always closed. * * @param file the file to read, must not be {@code null} * @param charset the charset to use, {@code null} means platform default * @return the list of Strings representing each line in the file, never {@code null} * @throws NullPointerException if file is {@code null}. * @throws FileNotFoundException if the file does not exist, is a directory rather than a regular file, or for some * other reason cannot be opened for reading. * @throws IOException if an I/O error occurs. * @since 2.3 */ public static List readLines(final File file, final Charset charset) throws IOException { try (InputStream inputStream = openInputStream(file)) { return IOUtils.readLines(inputStream, Charsets.toCharset(charset)); } } /** * Reads the contents of a file line by line to a List of Strings. The file is always closed. * * @param file the file to read, must not be {@code null} * @param charsetName the name of the requested charset, {@code null} means platform default * @return the list of Strings representing each line in the file, never {@code null} * @throws NullPointerException if file is {@code null}. * @throws FileNotFoundException if the file does not exist, is a directory rather than a regular file, or for some * other reason cannot be opened for reading. * @throws IOException if an I/O error occurs. * @throws java.nio.charset.UnsupportedCharsetException thrown instead of {@link java.io * .UnsupportedEncodingException} in version 2.2 if the named charset is unavailable. * @since 1.1 */ public static List readLines(final File file, final String charsetName) throws IOException { return readLines(file, Charsets.toCharset(charsetName)); } private static void requireAbsent(final File file, final String name) throws FileExistsException { if (file.exists()) { throw new FileExistsException( String.format("File element in parameter '%s' already exists: '%s'", name, file)); } } /** * Throws IllegalArgumentException if the given files' canonical representations are equal. * * @param file1 The first file to compare. * @param file2 The second file to compare. * @throws IllegalArgumentException if the given files' canonical representations are equal. */ private static void requireCanonicalPathsNotEquals(final File file1, final File file2) throws IOException { final String canonicalPath = file1.getCanonicalPath(); if (canonicalPath.equals(file2.getCanonicalPath())) { throw new IllegalArgumentException(String .format("File canonical paths are equal: '%s' (file1='%s', file2='%s')", canonicalPath, file1, file2)); } } /** * Throws an {@link IllegalArgumentException} if the file is not writable. This provides a more precise exception * message than a plain access denied. * * @param file The file to test. * @param name The parameter name to use in the exception message. * @throws NullPointerException if the given {@code File} is {@code null}. * @throws IllegalArgumentException if the file is not writable. */ private static void requireCanWrite(final File file, final String name) { Objects.requireNonNull(file, "file"); if (!file.canWrite()) { throw new IllegalArgumentException("File parameter '" + name + " is not writable: '" + file + "'"); } } /** * Requires that the given {@code File} is a directory. * * @param directory The {@code File} to check. * @param name The parameter name to use in the exception message in case of null input or if the file is not a directory. * @return the given directory. * @throws NullPointerException if the given {@code File} is {@code null}. * @throws IllegalArgumentException if the given {@code File} does not exist or is not a directory. */ private static File requireDirectory(final File directory, final String name) { Objects.requireNonNull(directory, name); if (!directory.isDirectory()) { throw new IllegalArgumentException("Parameter '" + name + "' is not a directory: '" + directory + "'"); } return directory; } /** * Requires that the given {@code File} exists and is a directory. * * @param directory The {@code File} to check. * @param name The parameter name to use in the exception message in case of null input. * @return the given directory. * @throws NullPointerException if the given {@code File} is {@code null}. * @throws IllegalArgumentException if the given {@code File} does not exist or is not a directory. */ private static File requireDirectoryExists(final File directory, final String name) { requireExists(directory, name); requireDirectory(directory, name); return directory; } /** * Requires that the given {@code File} is a directory if it exists. * * @param directory The {@code File} to check. * @param name The parameter name to use in the exception message in case of null input. * @return the given directory. * @throws NullPointerException if the given {@code File} is {@code null}. * @throws IllegalArgumentException if the given {@code File} exists but is not a directory. */ private static File requireDirectoryIfExists(final File directory, final String name) { Objects.requireNonNull(directory, name); if (directory.exists()) { requireDirectory(directory, name); } return directory; } /** * Requires that two file lengths are equal. * * @param srcFile Source file. * @param destFile Destination file. * @param srcLen Source file length. * @param dstLen Destination file length * @throws IOException Thrown when the given sizes are not equal. */ private static void requireEqualSizes(final File srcFile, final File destFile, final long srcLen, final long dstLen) throws IOException { if (srcLen != dstLen) { throw new IOException("Failed to copy full contents from '" + srcFile + "' to '" + destFile + "' Expected length: " + srcLen + " Actual: " + dstLen); } } /** * Requires that the given {@code File} exists and throws an {@link IllegalArgumentException} if it doesn't. * * @param file The {@code File} to check. * @param fileParamName The parameter name to use in the exception message in case of {@code null} input. * @return the given file. * @throws NullPointerException if the given {@code File} is {@code null}. * @throws IllegalArgumentException if the given {@code File} does not exist. */ private static File requireExists(final File file, final String fileParamName) { Objects.requireNonNull(file, fileParamName); if (!file.exists()) { throw new IllegalArgumentException( "File system element for parameter '" + fileParamName + "' does not exist: '" + file + "'"); } return file; } /** * Requires that the given {@code File} exists and throws an {@link FileNotFoundException} if it doesn't. * * @param file The {@code File} to check. * @param fileParamName The parameter name to use in the exception message in case of {@code null} input. * @return the given file. * @throws NullPointerException if the given {@code File} is {@code null}. * @throws FileNotFoundException if the given {@code File} does not exist. */ private static File requireExistsChecked(final File file, final String fileParamName) throws FileNotFoundException { Objects.requireNonNull(file, fileParamName); if (!file.exists()) { throw new FileNotFoundException( "File system element for parameter '" + fileParamName + "' does not exist: '" + file + "'"); } return file; } /** * Requires that the given {@code File} is a file. * * @param file The {@code File} to check. * @param name The parameter name to use in the exception message. * @return the given file. * @throws NullPointerException if the given {@code File} is {@code null}. * @throws IllegalArgumentException if the given {@code File} does not exist or is not a directory. */ private static File requireFile(final File file, final String name) { Objects.requireNonNull(file, name); if (!file.isFile()) { throw new IllegalArgumentException("Parameter '" + name + "' is not a file: " + file); } return file; } /** * Requires parameter attributes for a file copy operation. * * @param source the source file * @param destination the destination * @throws NullPointerException if any of the given {@code File}s are {@code null}. * @throws FileNotFoundException if the source does not exist. */ private static void requireFileCopy(final File source, final File destination) throws FileNotFoundException { requireExistsChecked(source, "source"); Objects.requireNonNull(destination, "destination"); } /** * Requires that the given {@code File} is a file if it exists. * * @param file The {@code File} to check. * @param name The parameter name to use in the exception message in case of null input. * @return the given directory. * @throws NullPointerException if the given {@code File} is {@code null}. * @throws IllegalArgumentException if the given {@code File} does exists but is not a directory. */ private static File requireFileIfExists(final File file, final String name) { Objects.requireNonNull(file, name); return file.exists() ? requireFile(file, name) : file; } /** * Sets the given {@code targetFile}'s last modified date to the value from {@code sourceFile}. * * @param sourceFile The source file to query. * @param targetFile The target file to set. * @throws NullPointerException if sourceFile is {@code null}. * @throws NullPointerException if targetFile is {@code null}. * @throws IOException if setting the last-modified time failed. */ private static void setLastModified(final File sourceFile, final File targetFile) throws IOException { Objects.requireNonNull(sourceFile, "sourceFile"); setLastModified(targetFile, lastModified(sourceFile)); } /** * Sets the given {@code targetFile}'s last modified date to the given value. * * @param file The source file to query. * @param timeMillis The new last-modified time, measured in milliseconds since the epoch 01-01-1970 GMT. * @throws NullPointerException if file is {@code null}. * @throws IOException if setting the last-modified time failed. */ private static void setLastModified(final File file, final long timeMillis) throws IOException { Objects.requireNonNull(file, "file"); if (!file.setLastModified(timeMillis)) { throw new IOException(String.format("Failed setLastModified(%s) on '%s'", timeMillis, file)); } } /** * Returns the size of the specified file or directory. If the provided * {@link File} is a regular file, then the file's length is returned. * If the argument is a directory, then the size of the directory is * calculated recursively. If a directory or subdirectory is security * restricted, its size will not be included. *

* Note that overflow is not detected, and the return value may be negative if * overflow occurs. See {@link #sizeOfAsBigInteger(File)} for an alternative * method that does not overflow. *

* * @param file the regular file or directory to return the size * of (must not be {@code null}). * * @return the length of the file, or recursive size of the directory, * provided (in bytes). * * @throws NullPointerException if the file is {@code null}. * @throws IllegalArgumentException if the file does not exist. * * @since 2.0 */ public static long sizeOf(final File file) { requireExists(file, "file"); return file.isDirectory() ? sizeOfDirectory0(file) : file.length(); } /** * Gets the size of a file. * * @param file the file to check. * @return the size of the file. * @throws NullPointerException if the file is {@code null}. */ private static long sizeOf0(final File file) { Objects.requireNonNull(file, "file"); if (file.isDirectory()) { return sizeOfDirectory0(file); } return file.length(); // will be 0 if file does not exist } /** * Returns the size of the specified file or directory. If the provided * {@link File} is a regular file, then the file's length is returned. * If the argument is a directory, then the size of the directory is * calculated recursively. If a directory or subdirectory is security * restricted, its size will not be included. * * @param file the regular file or directory to return the size * of (must not be {@code null}). * * @return the length of the file, or recursive size of the directory, * provided (in bytes). * * @throws NullPointerException if the file is {@code null}. * @throws IllegalArgumentException if the file does not exist. * * @since 2.4 */ public static BigInteger sizeOfAsBigInteger(final File file) { requireExists(file, "file"); return file.isDirectory() ? sizeOfDirectoryBig0(file) : BigInteger.valueOf(file.length()); } /** * Returns the size of a file or directory. * * @param file The file or directory. * @return the size */ private static BigInteger sizeOfBig0(final File file) { Objects.requireNonNull(file, "fileOrDir"); return file.isDirectory() ? sizeOfDirectoryBig0(file) : BigInteger.valueOf(file.length()); } /** * Counts the size of a directory recursively (sum of the length of all files). *

* Note that overflow is not detected, and the return value may be negative if * overflow occurs. See {@link #sizeOfDirectoryAsBigInteger(File)} for an alternative * method that does not overflow. *

* * @param directory directory to inspect, must not be {@code null}. * @return size of directory in bytes, 0 if directory is security restricted, a negative number when the real total * is greater than {@link Long#MAX_VALUE}. * @throws NullPointerException if the directory is {@code null}. */ public static long sizeOfDirectory(final File directory) { return sizeOfDirectory0(requireDirectoryExists(directory, "directory")); } /** * Gets the size of a directory. * * @param directory the directory to check * @return the size * @throws NullPointerException if the directory is {@code null}. */ private static long sizeOfDirectory0(final File directory) { Objects.requireNonNull(directory, "directory"); final File[] files = directory.listFiles(); if (files == null) { // null if security restricted return 0L; } long size = 0; for (final File file : files) { if (!isSymlink(file)) { size += sizeOf0(file); if (size < 0) { break; } } } return size; } /** * Counts the size of a directory recursively (sum of the length of all files). * * @param directory directory to inspect, must not be {@code null}. * @return size of directory in bytes, 0 if directory is security restricted. * @throws NullPointerException if the directory is {@code null}. * @since 2.4 */ public static BigInteger sizeOfDirectoryAsBigInteger(final File directory) { return sizeOfDirectoryBig0(requireDirectoryExists(directory, "directory")); } /** * Computes the size of a directory. * * @param directory The directory. * @return the size. */ private static BigInteger sizeOfDirectoryBig0(final File directory) { Objects.requireNonNull(directory, "directory"); final File[] files = directory.listFiles(); if (files == null) { // null if security restricted return BigInteger.ZERO; } BigInteger size = BigInteger.ZERO; for (final File file : files) { if (!isSymlink(file)) { size = size.add(sizeOfBig0(file)); } } return size; } /** * Streams over the files in a given directory (and optionally * its subdirectories) which match an array of extensions. * * @param directory the directory to search in * @param recursive if true all subdirectories are searched as well * @param extensions an array of extensions, ex. {"java","xml"}. If this * parameter is {@code null}, all files are returned. * @return an iterator of java.io.File with the matching files * @throws IOException if an I/O error is thrown when accessing the starting file. * @since 2.9.0 */ public static Stream streamFiles(final File directory, final boolean recursive, final String... extensions) throws IOException { final IOFileFilter filter = extensions == null ? FileFileFilter.INSTANCE : FileFileFilter.INSTANCE.and(new SuffixFileFilter(toSuffixes(extensions))); return PathUtils.walk(directory.toPath(), filter, toMaxDepth(recursive), false, FileVisitOption.FOLLOW_LINKS) .map(Path::toFile); } /** * Converts from a {@code URL} to a {@code File}. *

* From version 1.1 this method will decode the URL. * Syntax such as {@code file:///my%20docs/file.txt} will be * correctly decoded to {@code /my docs/file.txt}. Starting with version * 1.5, this method uses UTF-8 to decode percent-encoded octets to characters. * Additionally, malformed percent-encoded octets are handled leniently by * passing them through literally. *

* * @param url the file URL to convert, {@code null} returns {@code null} * @return the equivalent {@code File} object, or {@code null} * if the URL's protocol is not {@code file} */ public static File toFile(final URL url) { if (url == null || !"file".equalsIgnoreCase(url.getProtocol())) { return null; } final String filename = url.getFile().replace('/', File.separatorChar); return new File(decodeUrl(filename)); } /** * Converts each of an array of {@code URL} to a {@code File}. *

* Returns an array of the same size as the input. * If the input is {@code null}, an empty array is returned. * If the input contains {@code null}, the output array contains {@code null} at the same * index. *

*

* This method will decode the URL. * Syntax such as {@code file:///my%20docs/file.txt} will be * correctly decoded to {@code /my docs/file.txt}. *

* * @param urls the file URLs to convert, {@code null} returns empty array * @return a non-{@code null} array of Files matching the input, with a {@code null} item * if there was a {@code null} at that index in the input array * @throws IllegalArgumentException if any file is not a URL file * @throws IllegalArgumentException if any file is incorrectly encoded * @since 1.1 */ public static File[] toFiles(final URL... urls) { if (IOUtils.length(urls) == 0) { return EMPTY_FILE_ARRAY; } final File[] files = new File[urls.length]; for (int i = 0; i < urls.length; i++) { final URL url = urls[i]; if (url != null) { if (!"file".equalsIgnoreCase(url.getProtocol())) { throw new IllegalArgumentException("Can only convert file URL to a File: " + url); } files[i] = toFile(url); } } return files; } private static List toList(final Stream stream) { return stream.collect(Collectors.toList()); } /** * Converts whether or not to recurse into a recursion max depth. * * @param recursive whether or not to recurse * @return the recursion depth */ private static int toMaxDepth(final boolean recursive) { return recursive ? Integer.MAX_VALUE : 1; } /** * Converts an array of file extensions to suffixes. * * @param extensions an array of extensions. Format: {"java", "xml"} * @return an array of suffixes. Format: {".java", ".xml"} * @throws NullPointerException if the parameter is null */ private static String[] toSuffixes(final String... extensions) { Objects.requireNonNull(extensions, "extensions"); final String[] suffixes = new String[extensions.length]; for (int i = 0; i < extensions.length; i++) { suffixes[i] = "." + extensions[i]; } return suffixes; } /** * Implements the same behavior as the "touch" utility on Unix. It creates * a new file with size 0 or, if the file exists already, it is opened and * closed without modifying it, but updating the file date and time. *

* NOTE: As from v1.3, this method throws an IOException if the last * modified date of the file cannot be set. Also, as from v1.3 this method * creates parent directories if they do not exist. *

* * @param file the File to touch. * @throws IOException if an I/O problem occurs. * @throws IOException if setting the last-modified time failed. */ public static void touch(final File file) throws IOException { Objects.requireNonNull(file, "file"); if (!file.exists()) { openOutputStream(file).close(); } setLastModified(file, System.currentTimeMillis()); } /** * Converts each of an array of {@code File} to a {@code URL}. *

* Returns an array of the same size as the input. *

* * @param files the files to convert, must not be {@code null} * @return an array of URLs matching the input * @throws IOException if a file cannot be converted * @throws NullPointerException if the parameter is null */ public static URL[] toURLs(final File... files) throws IOException { Objects.requireNonNull(files, "files"); final URL[] urls = new URL[files.length]; for (int i = 0; i < urls.length; i++) { urls[i] = files[i].toURI().toURL(); } return urls; } /** * Validates the given arguments. *
    *
  • Throws {@link NullPointerException} if {@code source} is null
  • *
  • Throws {@link NullPointerException} if {@code destination} is null
  • *
  • Throws {@link FileNotFoundException} if {@code source} does not exist
  • *
* * @param source the file or directory to be moved * @param destination the destination file or directory * @throws FileNotFoundException if {@code source} file does not exist */ private static void validateMoveParameters(final File source, final File destination) throws FileNotFoundException { Objects.requireNonNull(source, "source"); Objects.requireNonNull(destination, "destination"); if (!source.exists()) { throw new FileNotFoundException("Source '" + source + "' does not exist"); } } /** * Waits for NFS to propagate a file creation, imposing a timeout. *

* This method repeatedly tests {@link File#exists()} until it returns * true up to the maximum time specified in seconds. *

* * @param file the file to check, must not be {@code null} * @param seconds the maximum time in seconds to wait * @return true if file exists * @throws NullPointerException if the file is {@code null} */ public static boolean waitFor(final File file, final int seconds) { Objects.requireNonNull(file, "file"); final long finishAtMillis = System.currentTimeMillis() + (seconds * 1000L); boolean wasInterrupted = false; try { while (!file.exists()) { final long remainingMillis = finishAtMillis - System.currentTimeMillis(); if (remainingMillis < 0){ return false; } try { Thread.sleep(Math.min(100, remainingMillis)); } catch (final InterruptedException ignore) { wasInterrupted = true; } catch (final Exception ex) { break; } } } finally { if (wasInterrupted) { Thread.currentThread().interrupt(); } } return true; } /** * Writes a CharSequence to a file creating the file if it does not exist using the default encoding for the VM. * * @param file the file to write * @param data the content to write to the file * @throws IOException in case of an I/O error * @since 2.0 * @deprecated 2.5 use {@link #write(File, CharSequence, Charset)} instead (and specify the appropriate encoding) */ @Deprecated public static void write(final File file, final CharSequence data) throws IOException { write(file, data, Charset.defaultCharset(), false); } /** * Writes a CharSequence to a file creating the file if it does not exist using the default encoding for the VM. * * @param file the file to write * @param data the content to write to the file * @param append if {@code true}, then the data will be added to the * end of the file rather than overwriting * @throws IOException in case of an I/O error * @since 2.1 * @deprecated 2.5 use {@link #write(File, CharSequence, Charset, boolean)} instead (and specify the appropriate encoding) */ @Deprecated public static void write(final File file, final CharSequence data, final boolean append) throws IOException { write(file, data, Charset.defaultCharset(), append); } /** * Writes a CharSequence to a file creating the file if it does not exist. * * @param file the file to write * @param data the content to write to the file * @param charset the name of the requested charset, {@code null} means platform default * @throws IOException in case of an I/O error * @since 2.3 */ public static void write(final File file, final CharSequence data, final Charset charset) throws IOException { write(file, data, charset, false); } /** * Writes a CharSequence to a file creating the file if it does not exist. * * @param file the file to write * @param data the content to write to the file * @param charset the charset to use, {@code null} means platform default * @param append if {@code true}, then the data will be added to the * end of the file rather than overwriting * @throws IOException in case of an I/O error * @since 2.3 */ public static void write(final File file, final CharSequence data, final Charset charset, final boolean append) throws IOException { writeStringToFile(file, Objects.toString(data, null), charset, append); } // Private method, must be invoked will a directory parameter /** * Writes a CharSequence to a file creating the file if it does not exist. * * @param file the file to write * @param data the content to write to the file * @param charsetName the name of the requested charset, {@code null} means platform default * @throws IOException in case of an I/O error * @throws java.io.UnsupportedEncodingException if the encoding is not supported by the VM * @since 2.0 */ public static void write(final File file, final CharSequence data, final String charsetName) throws IOException { write(file, data, charsetName, false); } /** * Writes a CharSequence to a file creating the file if it does not exist. * * @param file the file to write * @param data the content to write to the file * @param charsetName the name of the requested charset, {@code null} means platform default * @param append if {@code true}, then the data will be added to the * end of the file rather than overwriting * @throws IOException in case of an I/O error * @throws java.nio.charset.UnsupportedCharsetException thrown instead of {@link java.io * .UnsupportedEncodingException} in version 2.2 if the encoding is not supported by the VM * @since 2.1 */ public static void write(final File file, final CharSequence data, final String charsetName, final boolean append) throws IOException { write(file, data, Charsets.toCharset(charsetName), append); } /** * Writes a byte array to a file creating the file if it does not exist. *

* NOTE: As from v1.3, the parent directories of the file will be created * if they do not exist. *

* * @param file the file to write to * @param data the content to write to the file * @throws IOException in case of an I/O error * @since 1.1 */ public static void writeByteArrayToFile(final File file, final byte[] data) throws IOException { writeByteArrayToFile(file, data, false); } // Must be called with a directory /** * Writes a byte array to a file creating the file if it does not exist. * * @param file the file to write to * @param data the content to write to the file * @param append if {@code true}, then bytes will be added to the * end of the file rather than overwriting * @throws IOException in case of an I/O error * @since 2.1 */ public static void writeByteArrayToFile(final File file, final byte[] data, final boolean append) throws IOException { writeByteArrayToFile(file, data, 0, data.length, append); } /** * Writes {@code len} bytes from the specified byte array starting * at offset {@code off} to a file, creating the file if it does * not exist. * * @param file the file to write to * @param data the content to write to the file * @param off the start offset in the data * @param len the number of bytes to write * @throws IOException in case of an I/O error * @since 2.5 */ public static void writeByteArrayToFile(final File file, final byte[] data, final int off, final int len) throws IOException { writeByteArrayToFile(file, data, off, len, false); } /** * Writes {@code len} bytes from the specified byte array starting * at offset {@code off} to a file, creating the file if it does * not exist. * * @param file the file to write to * @param data the content to write to the file * @param off the start offset in the data * @param len the number of bytes to write * @param append if {@code true}, then bytes will be added to the * end of the file rather than overwriting * @throws IOException in case of an I/O error * @since 2.5 */ public static void writeByteArrayToFile(final File file, final byte[] data, final int off, final int len, final boolean append) throws IOException { try (OutputStream out = openOutputStream(file, append)) { out.write(data, off, len); } } /** * Writes the {@code toString()} value of each item in a collection to * the specified {@code File} line by line. * The default VM encoding and the default line ending will be used. * * @param file the file to write to * @param lines the lines to write, {@code null} entries produce blank lines * @throws IOException in case of an I/O error * @since 1.3 */ public static void writeLines(final File file, final Collection lines) throws IOException { writeLines(file, null, lines, null, false); } /** * Writes the {@code toString()} value of each item in a collection to * the specified {@code File} line by line. * The default VM encoding and the default line ending will be used. * * @param file the file to write to * @param lines the lines to write, {@code null} entries produce blank lines * @param append if {@code true}, then the lines will be added to the * end of the file rather than overwriting * @throws IOException in case of an I/O error * @since 2.1 */ public static void writeLines(final File file, final Collection lines, final boolean append) throws IOException { writeLines(file, null, lines, null, append); } /** * Writes the {@code toString()} value of each item in a collection to * the specified {@code File} line by line. * The default VM encoding and the specified line ending will be used. * * @param file the file to write to * @param lines the lines to write, {@code null} entries produce blank lines * @param lineEnding the line separator to use, {@code null} is system default * @throws IOException in case of an I/O error * @since 1.3 */ public static void writeLines(final File file, final Collection lines, final String lineEnding) throws IOException { writeLines(file, null, lines, lineEnding, false); } /** * Writes the {@code toString()} value of each item in a collection to * the specified {@code File} line by line. * The default VM encoding and the specified line ending will be used. * * @param file the file to write to * @param lines the lines to write, {@code null} entries produce blank lines * @param lineEnding the line separator to use, {@code null} is system default * @param append if {@code true}, then the lines will be added to the * end of the file rather than overwriting * @throws IOException in case of an I/O error * @since 2.1 */ public static void writeLines(final File file, final Collection lines, final String lineEnding, final boolean append) throws IOException { writeLines(file, null, lines, lineEnding, append); } /** * Writes the {@code toString()} value of each item in a collection to * the specified {@code File} line by line. * The specified character encoding and the default line ending will be used. *

* NOTE: As from v1.3, the parent directories of the file will be created * if they do not exist. *

* * @param file the file to write to * @param charsetName the name of the requested charset, {@code null} means platform default * @param lines the lines to write, {@code null} entries produce blank lines * @throws IOException in case of an I/O error * @throws java.io.UnsupportedEncodingException if the encoding is not supported by the VM * @since 1.1 */ public static void writeLines(final File file, final String charsetName, final Collection lines) throws IOException { writeLines(file, charsetName, lines, null, false); } /** * Writes the {@code toString()} value of each item in a collection to * the specified {@code File} line by line, optionally appending. * The specified character encoding and the default line ending will be used. * * @param file the file to write to * @param charsetName the name of the requested charset, {@code null} means platform default * @param lines the lines to write, {@code null} entries produce blank lines * @param append if {@code true}, then the lines will be added to the * end of the file rather than overwriting * @throws IOException in case of an I/O error * @throws java.io.UnsupportedEncodingException if the encoding is not supported by the VM * @since 2.1 */ public static void writeLines(final File file, final String charsetName, final Collection lines, final boolean append) throws IOException { writeLines(file, charsetName, lines, null, append); } /** * Writes the {@code toString()} value of each item in a collection to * the specified {@code File} line by line. * The specified character encoding and the line ending will be used. *

* NOTE: As from v1.3, the parent directories of the file will be created * if they do not exist. *

* * @param file the file to write to * @param charsetName the name of the requested charset, {@code null} means platform default * @param lines the lines to write, {@code null} entries produce blank lines * @param lineEnding the line separator to use, {@code null} is system default * @throws IOException in case of an I/O error * @throws java.io.UnsupportedEncodingException if the encoding is not supported by the VM * @since 1.1 */ public static void writeLines(final File file, final String charsetName, final Collection lines, final String lineEnding) throws IOException { writeLines(file, charsetName, lines, lineEnding, false); } /** * Writes the {@code toString()} value of each item in a collection to * the specified {@code File} line by line. * The specified character encoding and the line ending will be used. * * @param file the file to write to * @param charsetName the name of the requested charset, {@code null} means platform default * @param lines the lines to write, {@code null} entries produce blank lines * @param lineEnding the line separator to use, {@code null} is system default * @param append if {@code true}, then the lines will be added to the * end of the file rather than overwriting * @throws IOException in case of an I/O error * @throws java.io.UnsupportedEncodingException if the encoding is not supported by the VM * @since 2.1 */ public static void writeLines(final File file, final String charsetName, final Collection lines, final String lineEnding, final boolean append) throws IOException { try (OutputStream out = new BufferedOutputStream(openOutputStream(file, append))) { IOUtils.writeLines(lines, lineEnding, out, charsetName); } } /** * Writes a String to a file creating the file if it does not exist using the default encoding for the VM. * * @param file the file to write * @param data the content to write to the file * @throws IOException in case of an I/O error * @deprecated 2.5 use {@link #writeStringToFile(File, String, Charset)} instead (and specify the appropriate encoding) */ @Deprecated public static void writeStringToFile(final File file, final String data) throws IOException { writeStringToFile(file, data, Charset.defaultCharset(), false); } /** * Writes a String to a file creating the file if it does not exist using the default encoding for the VM. * * @param file the file to write * @param data the content to write to the file * @param append if {@code true}, then the String will be added to the * end of the file rather than overwriting * @throws IOException in case of an I/O error * @since 2.1 * @deprecated 2.5 use {@link #writeStringToFile(File, String, Charset, boolean)} instead (and specify the appropriate encoding) */ @Deprecated public static void writeStringToFile(final File file, final String data, final boolean append) throws IOException { writeStringToFile(file, data, Charset.defaultCharset(), append); } /** * Writes a String to a file creating the file if it does not exist. *

* NOTE: As from v1.3, the parent directories of the file will be created * if they do not exist. *

* * @param file the file to write * @param data the content to write to the file * @param charset the charset to use, {@code null} means platform default * @throws IOException in case of an I/O error * @throws java.io.UnsupportedEncodingException if the encoding is not supported by the VM * @since 2.4 */ public static void writeStringToFile(final File file, final String data, final Charset charset) throws IOException { writeStringToFile(file, data, charset, false); } /** * Writes a String to a file creating the file if it does not exist. * * @param file the file to write * @param data the content to write to the file * @param charset the charset to use, {@code null} means platform default * @param append if {@code true}, then the String will be added to the * end of the file rather than overwriting * @throws IOException in case of an I/O error * @since 2.3 */ public static void writeStringToFile(final File file, final String data, final Charset charset, final boolean append) throws IOException { try (OutputStream out = openOutputStream(file, append)) { IOUtils.write(data, out, charset); } } /** * Writes a String to a file creating the file if it does not exist. *

* NOTE: As from v1.3, the parent directories of the file will be created * if they do not exist. *

* * @param file the file to write * @param data the content to write to the file * @param charsetName the name of the requested charset, {@code null} means platform default * @throws IOException in case of an I/O error * @throws java.io.UnsupportedEncodingException if the encoding is not supported by the VM */ public static void writeStringToFile(final File file, final String data, final String charsetName) throws IOException { writeStringToFile(file, data, charsetName, false); } /** * Writes a String to a file creating the file if it does not exist. * * @param file the file to write * @param data the content to write to the file * @param charsetName the name of the requested charset, {@code null} means platform default * @param append if {@code true}, then the String will be added to the * end of the file rather than overwriting * @throws IOException in case of an I/O error * @throws java.nio.charset.UnsupportedCharsetException thrown instead of {@link java.io * .UnsupportedEncodingException} in version 2.2 if the encoding is not supported by the VM * @since 2.1 */ public static void writeStringToFile(final File file, final String data, final String charsetName, final boolean append) throws IOException { writeStringToFile(file, data, Charsets.toCharset(charsetName), append); } /** * Instances should NOT be constructed in standard programming. * @deprecated Will be private in 3.0. */ @Deprecated public FileUtils() { //NOSONAR } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/FilenameUtils.java0100644 0000000 0000000 00000175160 13612062727 027151 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import java.io.File; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Deque; import java.util.List; import java.util.Objects; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * General file name and file path manipulation utilities. *

* When dealing with file names you can hit problems when moving from a Windows * based development machine to a Unix based production machine. * This class aims to help avoid those problems. *

* NOTE: You may be able to avoid using this class entirely simply by * using JDK {@link java.io.File File} objects and the two argument constructor * {@link java.io.File#File(java.io.File, java.lang.String) File(File,String)}. *

* Most methods on this class are designed to work the same on both Unix and Windows. * Those that don't include 'System', 'Unix' or 'Windows' in their name. *

* Most methods recognize both separators (forward and back), and both * sets of prefixes. See the Javadoc of each method for details. *

* This class defines six components within a file name * (example C:\dev\project\file.txt): *

    *
  • the prefix - C:\
  • *
  • the path - dev\project\
  • *
  • the full path - C:\dev\project\
  • *
  • the name - file.txt
  • *
  • the base name - file
  • *
  • the extension - txt
  • *
* Note that this class works best if directory file names end with a separator. * If you omit the last separator, it is impossible to determine if the file name * corresponds to a file or a directory. As a result, we have chosen to say * it corresponds to a file. *

* This class only supports Unix and Windows style names. * Prefixes are matched as follows: *

 * Windows:
 * a\b\c.txt           --> ""          --> relative
 * \a\b\c.txt          --> "\"         --> current drive absolute
 * C:a\b\c.txt         --> "C:"        --> drive relative
 * C:\a\b\c.txt        --> "C:\"       --> absolute
 * \\server\a\b\c.txt  --> "\\server\" --> UNC
 *
 * Unix:
 * a/b/c.txt           --> ""          --> relative
 * /a/b/c.txt          --> "/"         --> absolute
 * ~/a/b/c.txt         --> "~/"        --> current user
 * ~                   --> "~/"        --> current user (slash added)
 * ~user/a/b/c.txt     --> "~user/"    --> named user
 * ~user               --> "~user/"    --> named user (slash added)
 * 
* Both prefix styles are matched always, irrespective of the machine that you are * currently running on. *

* Origin of code: Excalibur, Alexandria, Tomcat, Commons-Utils. * * @since 1.1 */ public class FilenameUtils { private static final String[] EMPTY_STRING_ARRAY = {}; private static final String EMPTY_STRING = ""; private static final int NOT_FOUND = -1; /** * The extension separator character. * @since 1.4 */ public static final char EXTENSION_SEPARATOR = '.'; /** * The extension separator String. * @since 1.4 */ public static final String EXTENSION_SEPARATOR_STR = Character.toString(EXTENSION_SEPARATOR); /** * The Unix separator character. */ private static final char UNIX_SEPARATOR = '/'; /** * The Windows separator character. */ private static final char WINDOWS_SEPARATOR = '\\'; /** * The system separator character. */ private static final char SYSTEM_SEPARATOR = File.separatorChar; /** * The separator character that is the opposite of the system separator. */ private static final char OTHER_SEPARATOR; static { if (isSystemWindows()) { OTHER_SEPARATOR = UNIX_SEPARATOR; } else { OTHER_SEPARATOR = WINDOWS_SEPARATOR; } } /** * Instances should NOT be constructed in standard programming. */ public FilenameUtils() { } /** * Determines if Windows file system is in use. * * @return true if the system is Windows */ static boolean isSystemWindows() { return SYSTEM_SEPARATOR == WINDOWS_SEPARATOR; } /** * Checks if the character is a separator. * * @param ch the character to check * @return true if it is a separator character */ private static boolean isSeparator(final char ch) { return ch == UNIX_SEPARATOR || ch == WINDOWS_SEPARATOR; } /** * Normalizes a path, removing double and single dot path steps. *

* This method normalizes a path to a standard format. * The input may contain separators in either Unix or Windows format. * The output will contain separators in the format of the system. *

* A trailing slash will be retained. * A double slash will be merged to a single slash (but UNC names are handled). * A single dot path segment will be removed. * A double dot will cause that path segment and the one before to be removed. * If the double dot has no parent path segment to work with, {@code null} * is returned. *

* The output will be the same on both Unix and Windows except * for the separator character. *

     * /foo//               -->   /foo/
     * /foo/./              -->   /foo/
     * /foo/../bar          -->   /bar
     * /foo/../bar/         -->   /bar/
     * /foo/../bar/../baz   -->   /baz
     * //foo//./bar         -->   /foo/bar
     * /../                 -->   null
     * ../foo               -->   null
     * foo/bar/..           -->   foo/
     * foo/../../bar        -->   null
     * foo/../bar           -->   bar
     * //server/foo/../bar  -->   //server/bar
     * //server/../bar      -->   null
     * C:\foo\..\bar        -->   C:\bar
     * C:\..\bar            -->   null
     * ~/foo/../bar/        -->   ~/bar/
     * ~/../bar             -->   null
     * 
* (Note the file separator returned will be correct for Windows/Unix) * * @param fileName the fileName to normalize, null returns null * @return the normalized fileName, or null if invalid. Null bytes inside string will be removed */ public static String normalize(final String fileName) { return doNormalize(fileName, SYSTEM_SEPARATOR, true); } /** * Normalizes a path, removing double and single dot path steps. *

* This method normalizes a path to a standard format. * The input may contain separators in either Unix or Windows format. * The output will contain separators in the format specified. *

* A trailing slash will be retained. * A double slash will be merged to a single slash (but UNC names are handled). * A single dot path segment will be removed. * A double dot will cause that path segment and the one before to be removed. * If the double dot has no parent path segment to work with, {@code null} * is returned. *

* The output will be the same on both Unix and Windows except * for the separator character. *

     * /foo//               -->   /foo/
     * /foo/./              -->   /foo/
     * /foo/../bar          -->   /bar
     * /foo/../bar/         -->   /bar/
     * /foo/../bar/../baz   -->   /baz
     * //foo//./bar         -->   /foo/bar
     * /../                 -->   null
     * ../foo               -->   null
     * foo/bar/..           -->   foo/
     * foo/../../bar        -->   null
     * foo/../bar           -->   bar
     * //server/foo/../bar  -->   //server/bar
     * //server/../bar      -->   null
     * C:\foo\..\bar        -->   C:\bar
     * C:\..\bar            -->   null
     * ~/foo/../bar/        -->   ~/bar/
     * ~/../bar             -->   null
     * 
* The output will be the same on both Unix and Windows including * the separator character. * * @param fileName the fileName to normalize, null returns null * @param unixSeparator {@code true} if a unix separator should * be used or {@code false} if a windows separator should be used. * @return the normalized fileName, or null if invalid. Null bytes inside string will be removed * @since 2.0 */ public static String normalize(final String fileName, final boolean unixSeparator) { final char separator = unixSeparator ? UNIX_SEPARATOR : WINDOWS_SEPARATOR; return doNormalize(fileName, separator, true); } /** * Normalizes a path, removing double and single dot path steps, * and removing any final directory separator. *

* This method normalizes a path to a standard format. * The input may contain separators in either Unix or Windows format. * The output will contain separators in the format of the system. *

* A trailing slash will be removed. * A double slash will be merged to a single slash (but UNC names are handled). * A single dot path segment will be removed. * A double dot will cause that path segment and the one before to be removed. * If the double dot has no parent path segment to work with, {@code null} * is returned. *

* The output will be the same on both Unix and Windows except * for the separator character. *

     * /foo//               -->   /foo
     * /foo/./              -->   /foo
     * /foo/../bar          -->   /bar
     * /foo/../bar/         -->   /bar
     * /foo/../bar/../baz   -->   /baz
     * //foo//./bar         -->   /foo/bar
     * /../                 -->   null
     * ../foo               -->   null
     * foo/bar/..           -->   foo
     * foo/../../bar        -->   null
     * foo/../bar           -->   bar
     * //server/foo/../bar  -->   //server/bar
     * //server/../bar      -->   null
     * C:\foo\..\bar        -->   C:\bar
     * C:\..\bar            -->   null
     * ~/foo/../bar/        -->   ~/bar
     * ~/../bar             -->   null
     * 
* (Note the file separator returned will be correct for Windows/Unix) * * @param fileName the fileName to normalize, null returns null * @return the normalized fileName, or null if invalid. Null bytes inside string will be removed */ public static String normalizeNoEndSeparator(final String fileName) { return doNormalize(fileName, SYSTEM_SEPARATOR, false); } /** * Normalizes a path, removing double and single dot path steps, * and removing any final directory separator. *

* This method normalizes a path to a standard format. * The input may contain separators in either Unix or Windows format. * The output will contain separators in the format specified. *

* A trailing slash will be removed. * A double slash will be merged to a single slash (but UNC names are handled). * A single dot path segment will be removed. * A double dot will cause that path segment and the one before to be removed. * If the double dot has no parent path segment to work with, {@code null} * is returned. *

* The output will be the same on both Unix and Windows including * the separator character. *

     * /foo//               -->   /foo
     * /foo/./              -->   /foo
     * /foo/../bar          -->   /bar
     * /foo/../bar/         -->   /bar
     * /foo/../bar/../baz   -->   /baz
     * //foo//./bar         -->   /foo/bar
     * /../                 -->   null
     * ../foo               -->   null
     * foo/bar/..           -->   foo
     * foo/../../bar        -->   null
     * foo/../bar           -->   bar
     * //server/foo/../bar  -->   //server/bar
     * //server/../bar      -->   null
     * C:\foo\..\bar        -->   C:\bar
     * C:\..\bar            -->   null
     * ~/foo/../bar/        -->   ~/bar
     * ~/../bar             -->   null
     * 
* * @param fileName the fileName to normalize, null returns null * @param unixSeparator {@code true} if a unix separator should * be used or {@code false} if a windows separator should be used. * @return the normalized fileName, or null if invalid. Null bytes inside string will be removed * @since 2.0 */ public static String normalizeNoEndSeparator(final String fileName, final boolean unixSeparator) { final char separator = unixSeparator ? UNIX_SEPARATOR : WINDOWS_SEPARATOR; return doNormalize(fileName, separator, false); } /** * Internal method to perform the normalization. * * @param fileName the fileName * @param separator The separator character to use * @param keepSeparator true to keep the final separator * @return the normalized fileName. Null bytes inside string will be removed. */ private static String doNormalize(final String fileName, final char separator, final boolean keepSeparator) { if (fileName == null) { return null; } requireNonNullChars(fileName); int size = fileName.length(); if (size == 0) { return fileName; } final int prefix = getPrefixLength(fileName); if (prefix < 0) { return null; } final char[] array = new char[size + 2]; // +1 for possible extra slash, +2 for arraycopy fileName.getChars(0, fileName.length(), array, 0); // fix separators throughout final char otherSeparator = separator == SYSTEM_SEPARATOR ? OTHER_SEPARATOR : SYSTEM_SEPARATOR; for (int i = 0; i < array.length; i++) { if (array[i] == otherSeparator) { array[i] = separator; } } // add extra separator on the end to simplify code below boolean lastIsDirectory = true; if (array[size - 1] != separator) { array[size++] = separator; lastIsDirectory = false; } // adjoining slashes // If we get here, prefix can only be 0 or greater, size 1 or greater // If prefix is 0, set loop start to 1 to prevent index errors for (int i = (prefix != 0) ? prefix : 1; i < size; i++) { if (array[i] == separator && array[i - 1] == separator) { System.arraycopy(array, i, array, i - 1, size - i); size--; i--; } } // dot slash for (int i = prefix + 1; i < size; i++) { if (array[i] == separator && array[i - 1] == '.' && (i == prefix + 1 || array[i - 2] == separator)) { if (i == size - 1) { lastIsDirectory = true; } System.arraycopy(array, i + 1, array, i - 1, size - i); size -=2; i--; } } // double dot slash outer: for (int i = prefix + 2; i < size; i++) { if (array[i] == separator && array[i - 1] == '.' && array[i - 2] == '.' && (i == prefix + 2 || array[i - 3] == separator)) { if (i == prefix + 2) { return null; } if (i == size - 1) { lastIsDirectory = true; } int j; for (j = i - 4 ; j >= prefix; j--) { if (array[j] == separator) { // remove b/../ from a/b/../c System.arraycopy(array, i + 1, array, j + 1, size - i); size -= i - j; i = j + 1; continue outer; } } // remove a/../ from a/../c System.arraycopy(array, i + 1, array, prefix, size - i); size -= i + 1 - prefix; i = prefix + 1; } } if (size <= 0) { // should never be less than 0 return EMPTY_STRING; } if (size <= prefix) { // should never be less than prefix return new String(array, 0, size); } if (lastIsDirectory && keepSeparator) { return new String(array, 0, size); // keep trailing separator } return new String(array, 0, size - 1); // lose trailing separator } /** * Concatenates a fileName to a base path using normal command line style rules. *

* The effect is equivalent to resultant directory after changing * directory to the first argument, followed by changing directory to * the second argument. *

* The first argument is the base path, the second is the path to concatenate. * The returned path is always normalized via {@link #normalize(String)}, * thus {@code ..} is handled. *

* If {@code pathToAdd} is absolute (has an absolute prefix), then * it will be normalized and returned. * Otherwise, the paths will be joined, normalized and returned. *

* The output will be the same on both Unix and Windows except * for the separator character. *

     * /foo/      + bar        -->  /foo/bar
     * /foo       + bar        -->  /foo/bar
     * /foo       + /bar       -->  /bar
     * /foo       + C:/bar     -->  C:/bar
     * /foo       + C:bar      -->  C:bar (*)
     * /foo/a/    + ../bar     -->  /foo/bar
     * /foo/      + ../../bar  -->  null
     * /foo/      + /bar       -->  /bar
     * /foo/..    + /bar       -->  /bar
     * /foo       + bar/c.txt  -->  /foo/bar/c.txt
     * /foo/c.txt + bar        -->  /foo/c.txt/bar (!)
     * 
* (*) Note that the Windows relative drive prefix is unreliable when * used with this method. * (!) Note that the first parameter must be a path. If it ends with a name, then * the name will be built into the concatenated path. If this might be a problem, * use {@link #getFullPath(String)} on the base path argument. * * @param basePath the base path to attach to, always treated as a path * @param fullFileNameToAdd the fileName (or path) to attach to the base * @return the concatenated path, or null if invalid. Null bytes inside string will be removed */ public static String concat(final String basePath, final String fullFileNameToAdd) { final int prefix = getPrefixLength(fullFileNameToAdd); if (prefix < 0) { return null; } if (prefix > 0) { return normalize(fullFileNameToAdd); } if (basePath == null) { return null; } final int len = basePath.length(); if (len == 0) { return normalize(fullFileNameToAdd); } final char ch = basePath.charAt(len - 1); if (isSeparator(ch)) { return normalize(basePath + fullFileNameToAdd); } return normalize(basePath + '/' + fullFileNameToAdd); } /** * Determines whether the {@code parent} directory contains the {@code child} element (a file or directory). *

* The files names are expected to be normalized. *

* * Edge cases: *
    *
  • A {@code directory} must not be null: if null, throw IllegalArgumentException
  • *
  • A directory does not contain itself: return false
  • *
  • A null child file is not contained in any parent: return false
  • *
* * @param canonicalParent * the file to consider as the parent. * @param canonicalChild * the file to consider as the child. * @return true is the candidate leaf is under by the specified composite. False otherwise. * @since 2.2 * @see FileUtils#directoryContains(File, File) */ public static boolean directoryContains(final String canonicalParent, final String canonicalChild) { Objects.requireNonNull(canonicalParent, "canonicalParent"); if (canonicalChild == null) { return false; } if (IOCase.SYSTEM.checkEquals(canonicalParent, canonicalChild)) { return false; } return IOCase.SYSTEM.checkStartsWith(canonicalChild, canonicalParent); } /** * Converts all separators to the Unix separator of forward slash. * * @param path the path to be changed, null ignored * @return the updated path */ public static String separatorsToUnix(final String path) { if (path == null || path.indexOf(WINDOWS_SEPARATOR) == NOT_FOUND) { return path; } return path.replace(WINDOWS_SEPARATOR, UNIX_SEPARATOR); } /** * Converts all separators to the Windows separator of backslash. * * @param path the path to be changed, null ignored * @return the updated path */ public static String separatorsToWindows(final String path) { if (path == null || path.indexOf(UNIX_SEPARATOR) == NOT_FOUND) { return path; } return path.replace(UNIX_SEPARATOR, WINDOWS_SEPARATOR); } /** * Converts all separators to the system separator. * * @param path the path to be changed, null ignored * @return the updated path */ public static String separatorsToSystem(final String path) { if (path == null) { return null; } return isSystemWindows() ? separatorsToWindows(path) : separatorsToUnix(path); } /** * Returns the length of the fileName prefix, such as {@code C:/} or {@code ~/}. *

* This method will handle a file in either Unix or Windows format. *

* The prefix length includes the first slash in the full fileName * if applicable. Thus, it is possible that the length returned is greater * than the length of the input string. *

     * Windows:
     * a\b\c.txt           --> 0           --> relative
     * \a\b\c.txt          --> 1           --> current drive absolute
     * C:a\b\c.txt         --> 2           --> drive relative
     * C:\a\b\c.txt        --> 3           --> absolute
     * \\server\a\b\c.txt  --> 9           --> UNC
     * \\\a\b\c.txt        --> -1          --> error
     *
     * Unix:
     * a/b/c.txt           --> 0           --> relative
     * /a/b/c.txt          --> 1           --> absolute
     * ~/a/b/c.txt         --> 2           --> current user
     * ~                   --> 2           --> current user (slash added)
     * ~user/a/b/c.txt     --> 6           --> named user
     * ~user               --> 6           --> named user (slash added)
     * //server/a/b/c.txt  --> 9
     * ///a/b/c.txt        --> -1          --> error
     * C:                  --> 0           --> valid filename as only null byte and / are reserved characters
     * 
*

* The output will be the same irrespective of the machine that the code is running on. * ie. both Unix and Windows prefixes are matched regardless. * * Note that a leading // (or \\) is used to indicate a UNC name on Windows. * These must be followed by a server name, so double-slashes are not collapsed * to a single slash at the start of the fileName. * * @param fileName the fileName to find the prefix in, null returns -1 * @return the length of the prefix, -1 if invalid or null */ public static int getPrefixLength(final String fileName) { if (fileName == null) { return NOT_FOUND; } final int len = fileName.length(); if (len == 0) { return 0; } char ch0 = fileName.charAt(0); if (ch0 == ':') { return NOT_FOUND; } if (len == 1) { if (ch0 == '~') { return 2; // return a length greater than the input } return isSeparator(ch0) ? 1 : 0; } if (ch0 == '~') { int posUnix = fileName.indexOf(UNIX_SEPARATOR, 1); int posWin = fileName.indexOf(WINDOWS_SEPARATOR, 1); if (posUnix == NOT_FOUND && posWin == NOT_FOUND) { return len + 1; // return a length greater than the input } posUnix = posUnix == NOT_FOUND ? posWin : posUnix; posWin = posWin == NOT_FOUND ? posUnix : posWin; return Math.min(posUnix, posWin) + 1; } final char ch1 = fileName.charAt(1); if (ch1 == ':') { ch0 = Character.toUpperCase(ch0); if (ch0 >= 'A' && ch0 <= 'Z') { if (len == 2 && !FileSystem.getCurrent().supportsDriveLetter()) { return 0; } if (len == 2 || !isSeparator(fileName.charAt(2))) { return 2; } return 3; } if (ch0 == UNIX_SEPARATOR) { return 1; } return NOT_FOUND; } if (!isSeparator(ch0) || !isSeparator(ch1)) { return isSeparator(ch0) ? 1 : 0; } int posUnix = fileName.indexOf(UNIX_SEPARATOR, 2); int posWin = fileName.indexOf(WINDOWS_SEPARATOR, 2); if (posUnix == NOT_FOUND && posWin == NOT_FOUND || posUnix == 2 || posWin == 2) { return NOT_FOUND; } posUnix = posUnix == NOT_FOUND ? posWin : posUnix; posWin = posWin == NOT_FOUND ? posUnix : posWin; final int pos = Math.min(posUnix, posWin) + 1; final String hostnamePart = fileName.substring(2, pos - 1); return isValidHostName(hostnamePart) ? pos : NOT_FOUND; } /** * Returns the index of the last directory separator character. *

* This method will handle a file in either Unix or Windows format. * The position of the last forward or backslash is returned. *

* The output will be the same irrespective of the machine that the code is running on. * * @param fileName the fileName to find the last path separator in, null returns -1 * @return the index of the last separator character, or -1 if there * is no such character */ public static int indexOfLastSeparator(final String fileName) { if (fileName == null) { return NOT_FOUND; } final int lastUnixPos = fileName.lastIndexOf(UNIX_SEPARATOR); final int lastWindowsPos = fileName.lastIndexOf(WINDOWS_SEPARATOR); return Math.max(lastUnixPos, lastWindowsPos); } /** * Returns the index of the last extension separator character, which is a dot. *

* This method also checks that there is no directory separator after the last dot. To do this it uses * {@link #indexOfLastSeparator(String)} which will handle a file in either Unix or Windows format. *

*

* The output will be the same irrespective of the machine that the code is running on, with the * exception of a possible {@link IllegalArgumentException} on Windows (see below). *

* Note: This method used to have a hidden problem for names like "foo.exe:bar.txt". * In this case, the name wouldn't be the name of a file, but the identifier of an * alternate data stream (bar.txt) on the file foo.exe. The method used to return * ".txt" here, which would be misleading. Commons IO 2.7, and later versions, are throwing * an {@link IllegalArgumentException} for names like this. * * @param fileName * the fileName to find the last extension separator in, null returns -1 * @return the index of the last extension separator character, or -1 if there is no such character * @throws IllegalArgumentException Windows only: The fileName parameter is, in fact, * the identifier of an Alternate Data Stream, for example "foo.exe:bar.txt". */ public static int indexOfExtension(final String fileName) throws IllegalArgumentException { if (fileName == null) { return NOT_FOUND; } if (isSystemWindows()) { // Special handling for NTFS ADS: Don't accept colon in the fileName. final int offset = fileName.indexOf(':', getAdsCriticalOffset(fileName)); if (offset != -1) { throw new IllegalArgumentException("NTFS ADS separator (':') in file name is forbidden."); } } final int extensionPos = fileName.lastIndexOf(EXTENSION_SEPARATOR); final int lastSeparator = indexOfLastSeparator(fileName); return lastSeparator > extensionPos ? NOT_FOUND : extensionPos; } /** * Gets the prefix from a full fileName, such as {@code C:/} * or {@code ~/}. *

* This method will handle a file in either Unix or Windows format. * The prefix includes the first slash in the full fileName where applicable. *

     * Windows:
     * a\b\c.txt           --> ""          --> relative
     * \a\b\c.txt          --> "\"         --> current drive absolute
     * C:a\b\c.txt         --> "C:"        --> drive relative
     * C:\a\b\c.txt        --> "C:\"       --> absolute
     * \\server\a\b\c.txt  --> "\\server\" --> UNC
     *
     * Unix:
     * a/b/c.txt           --> ""          --> relative
     * /a/b/c.txt          --> "/"         --> absolute
     * ~/a/b/c.txt         --> "~/"        --> current user
     * ~                   --> "~/"        --> current user (slash added)
     * ~user/a/b/c.txt     --> "~user/"    --> named user
     * ~user               --> "~user/"    --> named user (slash added)
     * 
*

* The output will be the same irrespective of the machine that the code is running on. * ie. both Unix and Windows prefixes are matched regardless. * * @param fileName the fileName to query, null returns null * @return the prefix of the file, null if invalid. Null bytes inside string will be removed */ public static String getPrefix(final String fileName) { if (fileName == null) { return null; } final int len = getPrefixLength(fileName); if (len < 0) { return null; } if (len > fileName.length()) { requireNonNullChars(fileName + UNIX_SEPARATOR); return fileName + UNIX_SEPARATOR; } final String path = fileName.substring(0, len); requireNonNullChars(path); return path; } /** * Gets the path from a full fileName, which excludes the prefix. *

* This method will handle a file in either Unix or Windows format. * The method is entirely text based, and returns the text before and * including the last forward or backslash. *

     * C:\a\b\c.txt --> a\b\
     * ~/a/b/c.txt  --> a/b/
     * a.txt        --> ""
     * a/b/c        --> a/b/
     * a/b/c/       --> a/b/c/
     * 
*

* The output will be the same irrespective of the machine that the code is running on. *

* This method drops the prefix from the result. * See {@link #getFullPath(String)} for the method that retains the prefix. * * @param fileName the fileName to query, null returns null * @return the path of the file, an empty string if none exists, null if invalid. * Null bytes inside string will be removed */ public static String getPath(final String fileName) { return doGetPath(fileName, 1); } /** * Gets the path from a full fileName, which excludes the prefix, and * also excluding the final directory separator. *

* This method will handle a file in either Unix or Windows format. * The method is entirely text based, and returns the text before the * last forward or backslash. *

     * C:\a\b\c.txt --> a\b
     * ~/a/b/c.txt  --> a/b
     * a.txt        --> ""
     * a/b/c        --> a/b
     * a/b/c/       --> a/b/c
     * 
*

* The output will be the same irrespective of the machine that the code is running on. *

* This method drops the prefix from the result. * See {@link #getFullPathNoEndSeparator(String)} for the method that retains the prefix. * * @param fileName the fileName to query, null returns null * @return the path of the file, an empty string if none exists, null if invalid. * Null bytes inside string will be removed */ public static String getPathNoEndSeparator(final String fileName) { return doGetPath(fileName, 0); } /** * Does the work of getting the path. * * @param fileName the fileName * @param separatorAdd 0 to omit the end separator, 1 to return it * @return the path. Null bytes inside string will be removed */ private static String doGetPath(final String fileName, final int separatorAdd) { if (fileName == null) { return null; } final int prefix = getPrefixLength(fileName); if (prefix < 0) { return null; } final int index = indexOfLastSeparator(fileName); final int endIndex = index+separatorAdd; if (prefix >= fileName.length() || index < 0 || prefix >= endIndex) { return EMPTY_STRING; } final String path = fileName.substring(prefix, endIndex); requireNonNullChars(path); return path; } /** * Gets the full path from a full fileName, which is the prefix + path. *

* This method will handle a file in either Unix or Windows format. * The method is entirely text based, and returns the text before and * including the last forward or backslash. *

     * C:\a\b\c.txt --> C:\a\b\
     * ~/a/b/c.txt  --> ~/a/b/
     * a.txt        --> ""
     * a/b/c        --> a/b/
     * a/b/c/       --> a/b/c/
     * C:           --> C:
     * C:\          --> C:\
     * ~            --> ~/
     * ~/           --> ~/
     * ~user        --> ~user/
     * ~user/       --> ~user/
     * 
*

* The output will be the same irrespective of the machine that the code is running on. * * @param fileName the fileName to query, null returns null * @return the path of the file, an empty string if none exists, null if invalid */ public static String getFullPath(final String fileName) { return doGetFullPath(fileName, true); } /** * Gets the full path from a full fileName, which is the prefix + path, * and also excluding the final directory separator. *

* This method will handle a file in either Unix or Windows format. * The method is entirely text based, and returns the text before the * last forward or backslash. *

     * C:\a\b\c.txt --> C:\a\b
     * ~/a/b/c.txt  --> ~/a/b
     * a.txt        --> ""
     * a/b/c        --> a/b
     * a/b/c/       --> a/b/c
     * C:           --> C:
     * C:\          --> C:\
     * ~            --> ~
     * ~/           --> ~
     * ~user        --> ~user
     * ~user/       --> ~user
     * 
*

* The output will be the same irrespective of the machine that the code is running on. * * @param fileName the fileName to query, null returns null * @return the path of the file, an empty string if none exists, null if invalid */ public static String getFullPathNoEndSeparator(final String fileName) { return doGetFullPath(fileName, false); } /** * Does the work of getting the path. * * @param fileName the fileName * @param includeSeparator true to include the end separator * @return the path */ private static String doGetFullPath(final String fileName, final boolean includeSeparator) { if (fileName == null) { return null; } final int prefix = getPrefixLength(fileName); if (prefix < 0) { return null; } if (prefix >= fileName.length()) { if (includeSeparator) { return getPrefix(fileName); // add end slash if necessary } return fileName; } final int index = indexOfLastSeparator(fileName); if (index < 0) { return fileName.substring(0, prefix); } int end = index + (includeSeparator ? 1 : 0); if (end == 0) { end++; } return fileName.substring(0, end); } /** * Gets the name minus the path from a full fileName. *

* This method will handle a file in either Unix or Windows format. * The text after the last forward or backslash is returned. *

     * a/b/c.txt --> c.txt
     * a.txt     --> a.txt
     * a/b/c     --> c
     * a/b/c/    --> ""
     * 
*

* The output will be the same irrespective of the machine that the code is running on. * * @param fileName the fileName to query, null returns null * @return the name of the file without the path, or an empty string if none exists. * Null bytes inside string will be removed */ public static String getName(final String fileName) { if (fileName == null) { return null; } requireNonNullChars(fileName); final int index = indexOfLastSeparator(fileName); return fileName.substring(index + 1); } /** * Checks the input for null bytes, a sign of unsanitized data being passed to to file level functions. * * This may be used for poison byte attacks. * * @param path the path to check */ private static void requireNonNullChars(final String path) { if (path.indexOf(0) >= 0) { throw new IllegalArgumentException("Null byte present in file/path name. There are no " + "known legitimate use cases for such data, but several injection attacks may use it"); } } /** * Gets the base name, minus the full path and extension, from a full fileName. *

* This method will handle a file in either Unix or Windows format. * The text after the last forward or backslash and before the last dot is returned. *

     * a/b/c.txt --> c
     * a.txt     --> a
     * a/b/c     --> c
     * a/b/c/    --> ""
     * 
*

* The output will be the same irrespective of the machine that the code is running on. * * @param fileName the fileName to query, null returns null * @return the name of the file without the path, or an empty string if none exists. Null bytes inside string * will be removed */ public static String getBaseName(final String fileName) { return removeExtension(getName(fileName)); } /** * Gets the extension of a fileName. *

* This method returns the textual part of the fileName after the last dot. * There must be no directory separator after the dot. *

     * foo.txt      --> "txt"
     * a/b/c.jpg    --> "jpg"
     * a/b.txt/c    --> ""
     * a/b/c        --> ""
     * 
*

* The output will be the same irrespective of the machine that the code is running on, with the * exception of a possible {@link IllegalArgumentException} on Windows (see below). *

*

* Note: This method used to have a hidden problem for names like "foo.exe:bar.txt". * In this case, the name wouldn't be the name of a file, but the identifier of an * alternate data stream (bar.txt) on the file foo.exe. The method used to return * ".txt" here, which would be misleading. Commons IO 2.7, and later versions, are throwing * an {@link IllegalArgumentException} for names like this. * * @param fileName the fileName to retrieve the extension of. * @return the extension of the file or an empty string if none exists or {@code null} * if the fileName is {@code null}. * @throws IllegalArgumentException Windows only: The fileName parameter is, in fact, * the identifier of an Alternate Data Stream, for example "foo.exe:bar.txt". */ public static String getExtension(final String fileName) throws IllegalArgumentException { if (fileName == null) { return null; } final int index = indexOfExtension(fileName); if (index == NOT_FOUND) { return EMPTY_STRING; } return fileName.substring(index + 1); } /** * Special handling for NTFS ADS: Don't accept colon in the fileName. * * @param fileName a file name * @return ADS offsets. */ private static int getAdsCriticalOffset(final String fileName) { // Step 1: Remove leading path segments. final int offset1 = fileName.lastIndexOf(SYSTEM_SEPARATOR); final int offset2 = fileName.lastIndexOf(OTHER_SEPARATOR); if (offset1 == -1) { if (offset2 == -1) { return 0; } return offset2 + 1; } if (offset2 == -1) { return offset1 + 1; } return Math.max(offset1, offset2) + 1; } /** * Removes the extension from a fileName. *

* This method returns the textual part of the fileName before the last dot. * There must be no directory separator after the dot. *

     * foo.txt    --> foo
     * a\b\c.jpg  --> a\b\c
     * a\b\c      --> a\b\c
     * a.b\c      --> a.b\c
     * 
*

* The output will be the same irrespective of the machine that the code is running on. * * @param fileName the fileName to query, null returns null * @return the fileName minus the extension */ public static String removeExtension(final String fileName) { if (fileName == null) { return null; } requireNonNullChars(fileName); final int index = indexOfExtension(fileName); if (index == NOT_FOUND) { return fileName; } return fileName.substring(0, index); } /** * Checks whether two fileNames are equal exactly. *

* No processing is performed on the fileNames other than comparison, * thus this is merely a null-safe case-sensitive equals. * * @param fileName1 the first fileName to query, may be null * @param fileName2 the second fileName to query, may be null * @return true if the fileNames are equal, null equals null * @see IOCase#SENSITIVE */ public static boolean equals(final String fileName1, final String fileName2) { return equals(fileName1, fileName2, false, IOCase.SENSITIVE); } /** * Checks whether two fileNames are equal using the case rules of the system. *

* No processing is performed on the fileNames other than comparison. * The check is case-sensitive on Unix and case-insensitive on Windows. * * @param fileName1 the first fileName to query, may be null * @param fileName2 the second fileName to query, may be null * @return true if the fileNames are equal, null equals null * @see IOCase#SYSTEM */ public static boolean equalsOnSystem(final String fileName1, final String fileName2) { return equals(fileName1, fileName2, false, IOCase.SYSTEM); } /** * Checks whether two fileNames are equal after both have been normalized. *

* Both fileNames are first passed to {@link #normalize(String)}. * The check is then performed in a case-sensitive manner. * * @param fileName1 the first fileName to query, may be null * @param fileName2 the second fileName to query, may be null * @return true if the fileNames are equal, null equals null * @see IOCase#SENSITIVE */ public static boolean equalsNormalized(final String fileName1, final String fileName2) { return equals(fileName1, fileName2, true, IOCase.SENSITIVE); } /** * Checks whether two fileNames are equal after both have been normalized * and using the case rules of the system. *

* Both fileNames are first passed to {@link #normalize(String)}. * The check is then performed case-sensitive on Unix and * case-insensitive on Windows. * * @param fileName1 the first fileName to query, may be null * @param fileName2 the second fileName to query, may be null * @return true if the fileNames are equal, null equals null * @see IOCase#SYSTEM */ public static boolean equalsNormalizedOnSystem(final String fileName1, final String fileName2) { return equals(fileName1, fileName2, true, IOCase.SYSTEM); } /** * Checks whether two fileNames are equal, optionally normalizing and providing * control over the case-sensitivity. * * @param fileName1 the first fileName to query, may be null * @param fileName2 the second fileName to query, may be null * @param normalized whether to normalize the fileNames * @param caseSensitivity what case sensitivity rule to use, null means case-sensitive * @return true if the fileNames are equal, null equals null * @since 1.3 */ public static boolean equals( String fileName1, String fileName2, final boolean normalized, IOCase caseSensitivity) { if (fileName1 == null || fileName2 == null) { return fileName1 == null && fileName2 == null; } if (normalized) { fileName1 = normalize(fileName1); if (fileName1 == null) { return false; } fileName2 = normalize(fileName2); if (fileName2 == null) { return false; } } if (caseSensitivity == null) { caseSensitivity = IOCase.SENSITIVE; } return caseSensitivity.checkEquals(fileName1, fileName2); } /** * Checks whether the extension of the fileName is that specified. *

* This method obtains the extension as the textual part of the fileName * after the last dot. There must be no directory separator after the dot. * The extension check is case-sensitive on all platforms. * * @param fileName the fileName to query, null returns false * @param extension the extension to check for, null or empty checks for no extension * @return true if the fileName has the specified extension * @throws java.lang.IllegalArgumentException if the supplied fileName contains null bytes */ public static boolean isExtension(final String fileName, final String extension) { if (fileName == null) { return false; } requireNonNullChars(fileName); if (extension == null || extension.isEmpty()) { return indexOfExtension(fileName) == NOT_FOUND; } final String fileExt = getExtension(fileName); return fileExt.equals(extension); } /** * Checks whether the extension of the fileName is one of those specified. *

* This method obtains the extension as the textual part of the fileName * after the last dot. There must be no directory separator after the dot. * The extension check is case-sensitive on all platforms. * * @param fileName the fileName to query, null returns false * @param extensions the extensions to check for, null checks for no extension * @return true if the fileName is one of the extensions * @throws java.lang.IllegalArgumentException if the supplied fileName contains null bytes */ public static boolean isExtension(final String fileName, final String... extensions) { if (fileName == null) { return false; } requireNonNullChars(fileName); if (extensions == null || extensions.length == 0) { return indexOfExtension(fileName) == NOT_FOUND; } final String fileExt = getExtension(fileName); for (final String extension : extensions) { if (fileExt.equals(extension)) { return true; } } return false; } /** * Checks whether the extension of the fileName is one of those specified. *

* This method obtains the extension as the textual part of the fileName * after the last dot. There must be no directory separator after the dot. * The extension check is case-sensitive on all platforms. * * @param fileName the fileName to query, null returns false * @param extensions the extensions to check for, null checks for no extension * @return true if the fileName is one of the extensions * @throws java.lang.IllegalArgumentException if the supplied fileName contains null bytes */ public static boolean isExtension(final String fileName, final Collection extensions) { if (fileName == null) { return false; } requireNonNullChars(fileName); if (extensions == null || extensions.isEmpty()) { return indexOfExtension(fileName) == NOT_FOUND; } final String fileExt = getExtension(fileName); for (final String extension : extensions) { if (fileExt.equals(extension)) { return true; } } return false; } /** * Checks a fileName to see if it matches the specified wildcard matcher, * always testing case-sensitive. *

* The wildcard matcher uses the characters '?' and '*' to represent a * single or multiple (zero or more) wildcard characters. * This is the same as often found on Dos/Unix command lines. * The check is case-sensitive always. *

     * wildcardMatch("c.txt", "*.txt")      --> true
     * wildcardMatch("c.txt", "*.jpg")      --> false
     * wildcardMatch("a/b/c.txt", "a/b/*")  --> true
     * wildcardMatch("c.txt", "*.???")      --> true
     * wildcardMatch("c.txt", "*.????")     --> false
     * 
* N.B. the sequence "*?" does not work properly at present in match strings. * * @param fileName the fileName to match on * @param wildcardMatcher the wildcard string to match against * @return true if the fileName matches the wildcard string * @see IOCase#SENSITIVE */ public static boolean wildcardMatch(final String fileName, final String wildcardMatcher) { return wildcardMatch(fileName, wildcardMatcher, IOCase.SENSITIVE); } /** * Checks a fileName to see if it matches the specified wildcard matcher * using the case rules of the system. *

* The wildcard matcher uses the characters '?' and '*' to represent a * single or multiple (zero or more) wildcard characters. * This is the same as often found on Dos/Unix command lines. * The check is case-sensitive on Unix and case-insensitive on Windows. *

     * wildcardMatch("c.txt", "*.txt")      --> true
     * wildcardMatch("c.txt", "*.jpg")      --> false
     * wildcardMatch("a/b/c.txt", "a/b/*")  --> true
     * wildcardMatch("c.txt", "*.???")      --> true
     * wildcardMatch("c.txt", "*.????")     --> false
     * 
* N.B. the sequence "*?" does not work properly at present in match strings. * * @param fileName the fileName to match on * @param wildcardMatcher the wildcard string to match against * @return true if the fileName matches the wildcard string * @see IOCase#SYSTEM */ public static boolean wildcardMatchOnSystem(final String fileName, final String wildcardMatcher) { return wildcardMatch(fileName, wildcardMatcher, IOCase.SYSTEM); } /** * Checks a fileName to see if it matches the specified wildcard matcher * allowing control over case-sensitivity. *

* The wildcard matcher uses the characters '?' and '*' to represent a * single or multiple (zero or more) wildcard characters. * N.B. the sequence "*?" does not work properly at present in match strings. * * @param fileName the fileName to match on * @param wildcardMatcher the wildcard string to match against * @param caseSensitivity what case sensitivity rule to use, null means case-sensitive * @return true if the fileName matches the wildcard string * @since 1.3 */ public static boolean wildcardMatch(final String fileName, final String wildcardMatcher, IOCase caseSensitivity) { if (fileName == null && wildcardMatcher == null) { return true; } if (fileName == null || wildcardMatcher == null) { return false; } if (caseSensitivity == null) { caseSensitivity = IOCase.SENSITIVE; } final String[] wcs = splitOnTokens(wildcardMatcher); boolean anyChars = false; int textIdx = 0; int wcsIdx = 0; final Deque backtrack = new ArrayDeque<>(wcs.length); // loop around a backtrack stack, to handle complex * matching do { if (!backtrack.isEmpty()) { final int[] array = backtrack.pop(); wcsIdx = array[0]; textIdx = array[1]; anyChars = true; } // loop whilst tokens and text left to process while (wcsIdx < wcs.length) { if (wcs[wcsIdx].equals("?")) { // ? so move to next text char textIdx++; if (textIdx > fileName.length()) { break; } anyChars = false; } else if (wcs[wcsIdx].equals("*")) { // set any chars status anyChars = true; if (wcsIdx == wcs.length - 1) { textIdx = fileName.length(); } } else { // matching text token if (anyChars) { // any chars then try to locate text token textIdx = caseSensitivity.checkIndexOf(fileName, textIdx, wcs[wcsIdx]); if (textIdx == NOT_FOUND) { // token not found break; } final int repeat = caseSensitivity.checkIndexOf(fileName, textIdx + 1, wcs[wcsIdx]); if (repeat >= 0) { backtrack.push(new int[] {wcsIdx, repeat}); } } else if (!caseSensitivity.checkRegionMatches(fileName, textIdx, wcs[wcsIdx])) { // matching from current position // couldn't match token break; } // matched text token, move text index to end of matched token textIdx += wcs[wcsIdx].length(); anyChars = false; } wcsIdx++; } // full match if (wcsIdx == wcs.length && textIdx == fileName.length()) { return true; } } while (!backtrack.isEmpty()); return false; } /** * Splits a string into a number of tokens. * The text is split by '?' and '*'. * Where multiple '*' occur consecutively they are collapsed into a single '*'. * * @param text the text to split * @return the array of tokens, never null */ static String[] splitOnTokens(final String text) { // used by wildcardMatch // package level so a unit test may run on this if (text.indexOf('?') == NOT_FOUND && text.indexOf('*') == NOT_FOUND) { return new String[] { text }; } final char[] array = text.toCharArray(); final ArrayList list = new ArrayList<>(); final StringBuilder buffer = new StringBuilder(); char prevChar = 0; for (final char ch : array) { if (ch == '?' || ch == '*') { if (buffer.length() != 0) { list.add(buffer.toString()); buffer.setLength(0); } if (ch == '?') { list.add("?"); } else if (prevChar != '*') {// ch == '*' here; check if previous char was '*' list.add("*"); } } else { buffer.append(ch); } prevChar = ch; } if (buffer.length() != 0) { list.add(buffer.toString()); } return list.toArray(EMPTY_STRING_ARRAY); } /** * Checks whether a given string is a valid host name according to * RFC 3986. * *

Accepted are IP addresses (v4 and v6) as well as what the * RFC calls a "reg-name". Percent encoded names don't seem to be * valid names in UNC paths.

* * @see "https://tools.ietf.org/html/rfc3986#section-3.2.2" * @param name the hostname to validate * @return true if the given name is a valid host name */ private static boolean isValidHostName(final String name) { return isIPv6Address(name) || isRFC3986HostName(name); } private static final Pattern IPV4_PATTERN = Pattern.compile("^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$"); private static final int IPV4_MAX_OCTET_VALUE = 255; /** * Checks whether a given string represents a valid IPv4 address. * * @param name the name to validate * @return true if the given name is a valid IPv4 address */ // mostly copied from org.apache.commons.validator.routines.InetAddressValidator#isValidInet4Address private static boolean isIPv4Address(final String name) { final Matcher m = IPV4_PATTERN.matcher(name); if (!m.matches() || m.groupCount() != 4) { return false; } // verify that address subgroups are legal for (int i = 1; i <= 4; i++) { final String ipSegment = m.group(i); final int iIpSegment = Integer.parseInt(ipSegment); if (iIpSegment > IPV4_MAX_OCTET_VALUE) { return false; } if (ipSegment.length() > 1 && ipSegment.startsWith("0")) { return false; } } return true; } private static final int IPV6_MAX_HEX_GROUPS = 8; private static final int IPV6_MAX_HEX_DIGITS_PER_GROUP = 4; private static final int MAX_UNSIGNED_SHORT = 0xffff; private static final int BASE_16 = 16; // copied from org.apache.commons.validator.routines.InetAddressValidator#isValidInet6Address /** * Checks whether a given string represents a valid IPv6 address. * * @param inet6Address the name to validate * @return true if the given name is a valid IPv6 address */ private static boolean isIPv6Address(final String inet6Address) { final boolean containsCompressedZeroes = inet6Address.contains("::"); if (containsCompressedZeroes && (inet6Address.indexOf("::") != inet6Address.lastIndexOf("::"))) { return false; } if ((inet6Address.startsWith(":") && !inet6Address.startsWith("::")) || (inet6Address.endsWith(":") && !inet6Address.endsWith("::"))) { return false; } String[] octets = inet6Address.split(":"); if (containsCompressedZeroes) { final List octetList = new ArrayList<>(Arrays.asList(octets)); if (inet6Address.endsWith("::")) { // String.split() drops ending empty segments octetList.add(""); } else if (inet6Address.startsWith("::") && !octetList.isEmpty()) { octetList.remove(0); } octets = octetList.toArray(EMPTY_STRING_ARRAY); } if (octets.length > IPV6_MAX_HEX_GROUPS) { return false; } int validOctets = 0; int emptyOctets = 0; // consecutive empty chunks for (int index = 0; index < octets.length; index++) { final String octet = octets[index]; if (octet.isEmpty()) { emptyOctets++; if (emptyOctets > 1) { return false; } } else { emptyOctets = 0; // Is last chunk an IPv4 address? if (index == octets.length - 1 && octet.contains(".")) { if (!isIPv4Address(octet)) { return false; } validOctets += 2; continue; } if (octet.length() > IPV6_MAX_HEX_DIGITS_PER_GROUP) { return false; } final int octetInt; try { octetInt = Integer.parseInt(octet, BASE_16); } catch (final NumberFormatException e) { return false; } if (octetInt < 0 || octetInt > MAX_UNSIGNED_SHORT) { return false; } } validOctets++; } return validOctets <= IPV6_MAX_HEX_GROUPS && (validOctets >= IPV6_MAX_HEX_GROUPS || containsCompressedZeroes); } private static final Pattern REG_NAME_PART_PATTERN = Pattern.compile("^[a-zA-Z0-9][a-zA-Z0-9-]*$"); /** * Checks whether a given string is a valid host name according to * RFC 3986 - not accepting IP addresses. * * @see "https://tools.ietf.org/html/rfc3986#section-3.2.2" * @param name the hostname to validate * @return true if the given name is a valid host name */ private static boolean isRFC3986HostName(final String name) { final String[] parts = name.split("\\.", -1); for (int i = 0; i < parts.length; i++) { if (parts[i].isEmpty()) { // trailing dot is legal, otherwise we've hit a .. sequence return i == parts.length - 1; } if (!REG_NAME_PART_PATTERN.matcher(parts[i]).matches()) { return false; } } return true; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/HexDump.java0100644 0000000 0000000 00000013410 13612062727 025747 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import java.io.IOException; import java.io.OutputStream; import java.nio.charset.Charset; /** * Dumps data in hexadecimal format. *

* Provides a single function to take an array of bytes and display it * in hexadecimal form. *

* Origin of code: POI. * */ public class HexDump { /** * Instances should NOT be constructed in standard programming. */ public HexDump() { } /** * Dump an array of bytes to an OutputStream. The output is formatted * for human inspection, with a hexadecimal offset followed by the * hexadecimal values of the next 16 bytes of data and the printable ASCII * characters (if any) that those bytes represent printed per each line * of output. *

* The offset argument specifies the start offset of the data array * within a larger entity like a file or an incoming stream. For example, * if the data array contains the third kibibyte of a file, then the * offset argument should be set to 2048. The offset value printed * at the beginning of each line indicates where in that larger entity * the first byte on that line is located. *

* All bytes between the given index (inclusive) and the end of the * data array are dumped. * * @param data the byte array to be dumped * @param offset offset of the byte array within a larger entity * @param stream the OutputStream to which the data is to be * written * @param index initial index into the byte array * * @throws IOException is thrown if anything goes wrong writing * the data to stream * @throws ArrayIndexOutOfBoundsException if the index is * outside the data array's bounds * @throws IllegalArgumentException if the output stream is null */ public static void dump(final byte[] data, final long offset, final OutputStream stream, final int index) throws IOException, ArrayIndexOutOfBoundsException, IllegalArgumentException { if (index < 0 || index >= data.length) { throw new ArrayIndexOutOfBoundsException( "illegal index: " + index + " into array of length " + data.length); } if (stream == null) { throw new IllegalArgumentException("cannot write to nullstream"); } long display_offset = offset + index; final StringBuilder buffer = new StringBuilder(74); for (int j = index; j < data.length; j += 16) { int chars_read = data.length - j; if (chars_read > 16) { chars_read = 16; } dump(buffer, display_offset).append(' '); for (int k = 0; k < 16; k++) { if (k < chars_read) { dump(buffer, data[k + j]); } else { buffer.append(" "); } buffer.append(' '); } for (int k = 0; k < chars_read; k++) { if (data[k + j] >= ' ' && data[k + j] < 127) { buffer.append((char) data[k + j]); } else { buffer.append('.'); } } buffer.append(EOL); // make explicit the dependency on the default encoding stream.write(buffer.toString().getBytes(Charset.defaultCharset())); stream.flush(); buffer.setLength(0); display_offset += chars_read; } } /** * The line-separator (initializes to "line.separator" system property. */ public static final String EOL = System.getProperty("line.separator"); private static final char[] _hexcodes = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; private static final int[] _shifts = { 28, 24, 20, 16, 12, 8, 4, 0 }; /** * Dump a long value into a StringBuilder. * * @param _lbuffer the StringBuilder to dump the value in * @param value the long value to be dumped * @return StringBuilder containing the dumped value. */ private static StringBuilder dump(final StringBuilder _lbuffer, final long value) { for (int j = 0; j < 8; j++) { _lbuffer .append(_hexcodes[(int) (value >> _shifts[j]) & 15]); } return _lbuffer; } /** * Dump a byte value into a StringBuilder. * * @param _cbuffer the StringBuilder to dump the value in * @param value the byte value to be dumped * @return StringBuilder containing the dumped value. */ private static StringBuilder dump(final StringBuilder _cbuffer, final byte value) { for (int j = 0; j < 2; j++) { _cbuffer.append(_hexcodes[value >> _shifts[j + 6] & 15]); } return _cbuffer; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/IOCase.java0100644 0000000 0000000 00000021535 13612062727 025507 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import java.util.Objects; /** * Enumeration of IO case sensitivity. *

* Different filing systems have different rules for case-sensitivity. * Windows is case-insensitive, Unix is case-sensitive. *

*

* This class captures that difference, providing an enumeration to * control how file name comparisons should be performed. It also provides * methods that use the enumeration to perform comparisons. *

*

* Wherever possible, you should use the {@code check} methods in this * class to compare file names. *

* * @since 1.3 */ public enum IOCase { /** * The constant for case sensitive regardless of operating system. */ SENSITIVE("Sensitive", true), /** * The constant for case insensitive regardless of operating system. */ INSENSITIVE("Insensitive", false), /** * The constant for case sensitivity determined by the current operating system. * Windows is case-insensitive when comparing file names, Unix is case-sensitive. *

* Note: This only caters for Windows and Unix. Other operating * systems (e.g. OSX and OpenVMS) are treated as case sensitive if they use the * Unix file separator and case-insensitive if they use the Windows file separator * (see {@link java.io.File#separatorChar}). *

*

* If you serialize this constant on Windows, and deserialize on Unix, or vice * versa, then the value of the case-sensitivity flag will change. *

*/ SYSTEM("System", !FilenameUtils.isSystemWindows()); /** * Tests for cases sensitivity in a null-safe manner. * * @param caseSensitivity an IOCase. * @return true if the input is non-null and {@link #isCaseSensitive()}. * @since 2.10.0 */ public static boolean isCaseSensitive(final IOCase caseSensitivity) { return caseSensitivity != null && !caseSensitivity.isCaseSensitive(); } /** Serialization version. */ private static final long serialVersionUID = -6343169151696340687L; /** The enumeration name. */ private final String name; /** The sensitivity flag. */ private final transient boolean sensitive; /** * Factory method to create an IOCase from a name. * * @param name the name to find * @return the IOCase object * @throws IllegalArgumentException if the name is invalid */ public static IOCase forName(final String name) { for (final IOCase ioCase : IOCase.values()) { if (ioCase.getName().equals(name)) { return ioCase; } } throw new IllegalArgumentException("Invalid IOCase name: " + name); } /** * Constructs a new instance. * * @param name the name * @param sensitive the sensitivity */ IOCase(final String name, final boolean sensitive) { this.name = name; this.sensitive = sensitive; } /** * Replaces the enumeration from the stream with a real one. * This ensures that the correct flag is set for SYSTEM. * * @return the resolved object */ private Object readResolve() { return forName(name); } /** * Gets the name of the constant. * * @return the name of the constant */ public String getName() { return name; } /** * Does the object represent case sensitive comparison. * * @return true if case sensitive */ public boolean isCaseSensitive() { return sensitive; } /** * Compares two strings using the case-sensitivity rule. *

* This method mimics {@link String#compareTo} but takes case-sensitivity * into account. *

* * @param str1 the first string to compare, not null * @param str2 the second string to compare, not null * @return true if equal using the case rules * @throws NullPointerException if either string is null */ public int checkCompareTo(final String str1, final String str2) { Objects.requireNonNull(str1, "str1"); Objects.requireNonNull(str2, "str2"); return sensitive ? str1.compareTo(str2) : str1.compareToIgnoreCase(str2); } /** * Compares two strings using the case-sensitivity rule. *

* This method mimics {@link String#equals} but takes case-sensitivity * into account. *

* * @param str1 the first string to compare, not null * @param str2 the second string to compare, not null * @return true if equal using the case rules * @throws NullPointerException if either string is null */ public boolean checkEquals(final String str1, final String str2) { Objects.requireNonNull(str1, "str1"); Objects.requireNonNull(str2, "str2"); return sensitive ? str1.equals(str2) : str1.equalsIgnoreCase(str2); } /** * Checks if one string starts with another using the case-sensitivity rule. *

* This method mimics {@link String#startsWith(String)} but takes case-sensitivity * into account. *

* * @param str the string to check * @param start the start to compare against * @return true if equal using the case rules, false if either input is null */ public boolean checkStartsWith(final String str, final String start) { return str != null && start != null && str.regionMatches(!sensitive, 0, start, 0, start.length()); } /** * Checks if one string ends with another using the case-sensitivity rule. *

* This method mimics {@link String#endsWith} but takes case-sensitivity * into account. *

* * @param str the string to check * @param end the end to compare against * @return true if equal using the case rules, false if either input is null */ public boolean checkEndsWith(final String str, final String end) { if (str == null || end == null) { return false; } final int endLen = end.length(); return str.regionMatches(!sensitive, str.length() - endLen, end, 0, endLen); } /** * Checks if one string contains another starting at a specific index using the * case-sensitivity rule. *

* This method mimics parts of {@link String#indexOf(String, int)} * but takes case-sensitivity into account. *

* * @param str the string to check, not null * @param strStartIndex the index to start at in str * @param search the start to search for, not null * @return the first index of the search String, * -1 if no match or {@code null} string input * @throws NullPointerException if either string is null * @since 2.0 */ public int checkIndexOf(final String str, final int strStartIndex, final String search) { final int endIndex = str.length() - search.length(); if (endIndex >= strStartIndex) { for (int i = strStartIndex; i <= endIndex; i++) { if (checkRegionMatches(str, i, search)) { return i; } } } return -1; } /** * Checks if one string contains another at a specific index using the case-sensitivity rule. *

* This method mimics parts of {@link String#regionMatches(boolean, int, String, int, int)} * but takes case-sensitivity into account. *

* * @param str the string to check, not null * @param strStartIndex the index to start at in str * @param search the start to search for, not null * @return true if equal using the case rules * @throws NullPointerException if either string is null */ public boolean checkRegionMatches(final String str, final int strStartIndex, final String search) { return str.regionMatches(!sensitive, strStartIndex, search, 0, search.length()); } /** * Gets a string describing the sensitivity. * * @return a string describing the sensitivity */ @Override public String toString() { return name; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/IOExceptionList.java0100644 0000000 0000000 00000006654 13612062727 027433 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import java.io.IOException; import java.util.Collections; import java.util.List; /** * A IOException based on a list of Throwable causes. *

* The first exception in the list is used as this exception's cause and is accessible with the usual * {@link #getCause()} while the complete list is accessible with {@link #getCauseList()}. *

* * @since 2.7 */ public class IOExceptionList extends IOException { private static final long serialVersionUID = 1L; private final List causeList; /** * Creates a new exception caused by a list of exceptions. * * @param causeList a list of cause exceptions. */ public IOExceptionList(final List causeList) { this(String.format("%,d exceptions: %s", causeList == null ? 0 : causeList.size(), causeList), causeList); } /** * Creates a new exception caused by a list of exceptions. * * @param message The detail message, see {@link #getMessage()}. * @param causeList a list of cause exceptions. * @since 2.9.0 */ public IOExceptionList(final String message, final List causeList) { super(message, causeList == null || causeList.isEmpty() ? null : causeList.get(0)); this.causeList = causeList == null ? Collections.emptyList() : causeList; } /** * Gets the cause exception at the given index. * * @param type of exception to return. * @param index index in the cause list. * @return The list of causes. */ public T getCause(final int index) { return (T) causeList.get(index); } /** * Gets the cause exception at the given index. * * @param type of exception to return. * @param index index in the cause list. * @param clazz type of exception to return. * @return The list of causes. */ public T getCause(final int index, final Class clazz) { return clazz.cast(causeList.get(index)); } /** * Gets the cause list. * * @param type of exception to return. * @return The list of causes. */ public List getCauseList() { return (List) causeList; } /** * Works around Throwable and Generics, may fail at runtime depending on the argument value. * * @param type of exception to return. * @param clazz the target type * @return The list of causes. */ public List getCauseList(final Class clazz) { return (List) causeList; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/IOExceptionWithCause.java0100644 0000000 0000000 00000004354 13612062727 030407 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import java.io.IOException; /** * Subclasses IOException with the {@link Throwable} constructors missing before Java 6. * * @since 1.4 * @deprecated (since 2.5) use {@link IOException} instead */ @Deprecated public class IOExceptionWithCause extends IOException { /** * Defines the serial version UID. */ private static final long serialVersionUID = 1L; /** * Constructs a new instance with the given message and cause. *

* As specified in {@link Throwable}, the message in the given {@code cause} is not used in this instance's * message. *

* * @param message * the message (see {@link #getMessage()}) * @param cause * the cause (see {@link #getCause()}). A {@code null} value is allowed. */ public IOExceptionWithCause(final String message, final Throwable cause) { super(message, cause); } /** * Constructs a new instance with the given cause. *

* The message is set to {@code cause==null ? null : cause.toString()}, which by default contains the class * and message of {@code cause}. This constructor is useful for call sites that just wrap another throwable. *

* * @param cause * the cause (see {@link #getCause()}). A {@code null} value is allowed. */ public IOExceptionWithCause(final Throwable cause) { super(cause); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/IOIndexedException.java0100644 0000000 0000000 00000004114 13612062727 030065 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import java.io.IOException; /** * A IOException associated with a source index. * * @since 2.7 */ public class IOIndexedException extends IOException { private static final long serialVersionUID = 1L; private final int index; /** * Creates a new exception. * * @param index index of this exception. * @param cause cause exceptions. */ public IOIndexedException(final int index, final Throwable cause) { super(toMessage(index, cause), cause); this.index = index; } /** * Converts input to a suitable String for exception message. * * @param index An index into a source collection. * @param cause A cause. * @return A message. */ protected static String toMessage(final int index, final Throwable cause) { // Letting index be any int final String unspecified = "Null"; final String name = cause == null ? unspecified : cause.getClass().getSimpleName(); final String msg = cause == null ? unspecified : cause.getMessage(); return String.format("%s #%,d: %s", name, index, msg); } /** * The index of this exception. * * @return index of this exception. */ public int getIndex() { return index; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/IOUtils.java0100644 0000000 0000000 00000421756 13612062727 025745 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.ByteArrayInputStream; import java.io.CharArrayWriter; import java.io.Closeable; import java.io.EOFException; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Reader; import java.io.Writer; import java.net.HttpURLConnection; import java.net.ServerSocket; import java.net.Socket; import java.net.URI; import java.net.URL; import java.net.URLConnection; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.channels.ReadableByteChannel; import java.nio.channels.Selector; import java.nio.charset.Charset; import java.nio.file.Files; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Objects; import java.util.function.Consumer; import org.apache.commons.io.function.IOConsumer; import org.apache.commons.io.output.AppendableWriter; import org.apache.commons.io.output.ByteArrayOutputStream; import org.apache.commons.io.output.NullOutputStream; import org.apache.commons.io.output.StringBuilderWriter; import org.apache.commons.io.output.ThresholdingOutputStream; import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream; /** * General IO stream manipulation utilities. *

* This class provides static utility methods for input/output operations. *

    *
  • [Deprecated] closeQuietly - these methods close a stream ignoring nulls and exceptions *
  • toXxx/read - these methods read data from a stream *
  • write - these methods write data to a stream *
  • copy - these methods copy all the data from one stream to another *
  • contentEquals - these methods compare the content of two streams *
*

* The byte-to-char methods and char-to-byte methods involve a conversion step. * Two methods are provided in each case, one that uses the platform default * encoding and the other which allows you to specify an encoding. You are * encouraged to always specify an encoding because relying on the platform * default can lead to unexpected results, for example when moving from * development to production. *

* All the methods in this class that read a stream are buffered internally. * This means that there is no cause to use a {@code BufferedInputStream} * or {@code BufferedReader}. The default buffer size of 4K has been shown * to be efficient in tests. *

* The various copy methods all delegate the actual copying to one of the following methods: *

    *
  • {@link #copyLarge(InputStream, OutputStream, byte[])}
  • *
  • {@link #copyLarge(InputStream, OutputStream, long, long, byte[])}
  • *
  • {@link #copyLarge(Reader, Writer, char[])}
  • *
  • {@link #copyLarge(Reader, Writer, long, long, char[])}
  • *
* For example, {@link #copy(InputStream, OutputStream)} calls {@link #copyLarge(InputStream, OutputStream)} * which calls {@link #copy(InputStream, OutputStream, int)} which creates the buffer and calls * {@link #copyLarge(InputStream, OutputStream, byte[])}. *

* Applications can re-use buffers by using the underlying methods directly. * This may improve performance for applications that need to do a lot of copying. *

* Wherever possible, the methods in this class do not flush or close * the stream. This is to avoid making non-portable assumptions about the * streams' origin and further use. Thus the caller is still responsible for * closing streams after use. *

* Origin of code: Excalibur. */ public class IOUtils { // NOTE: This class is focused on InputStream, OutputStream, Reader and // Writer. Each method should take at least one of these as a parameter, // or return one of them. /** * CR char. * * @since 2.9.0 */ public static final int CR = '\r'; /** * The default buffer size ({@value}) to use in copy methods. */ public static final int DEFAULT_BUFFER_SIZE = 8192; /** * The system directory separator character. */ public static final char DIR_SEPARATOR = File.separatorChar; /** * The Unix directory separator character. */ public static final char DIR_SEPARATOR_UNIX = '/'; /** * The Windows directory separator character. */ public static final char DIR_SEPARATOR_WINDOWS = '\\'; /** * A singleton empty byte array. * * @since 2.9.0 */ public static final byte[] EMPTY_BYTE_ARRAY = {}; /** * Represents the end-of-file (or stream). * @since 2.5 (made public) */ public static final int EOF = -1; /** * LF char. * * @since 2.9.0 */ public static final int LF = '\n'; /** * The system line separator string. * * @deprecated Use {@link System#lineSeparator()}. */ @Deprecated public static final String LINE_SEPARATOR = System.lineSeparator(); /** * The Unix line separator string. * * @see StandardLineSeparator#LF */ public static final String LINE_SEPARATOR_UNIX = StandardLineSeparator.LF.getString(); /** * The Windows line separator string. * * @see StandardLineSeparator#CRLF */ public static final String LINE_SEPARATOR_WINDOWS = StandardLineSeparator.CRLF.getString(); /** * Internal byte array buffer. */ private static final ThreadLocal SKIP_BYTE_BUFFER = ThreadLocal.withInitial(IOUtils::byteArray); /** * Internal byte array buffer. */ private static final ThreadLocal SKIP_CHAR_BUFFER = ThreadLocal.withInitial(IOUtils::charArray); /** * Returns the given InputStream if it is already a {@link BufferedInputStream}, otherwise creates a * BufferedInputStream from the given InputStream. * * @param inputStream the InputStream to wrap or return (not null) * @return the given InputStream or a new {@link BufferedInputStream} for the given InputStream * @throws NullPointerException if the input parameter is null * @since 2.5 */ @SuppressWarnings("resource") // parameter null check public static BufferedInputStream buffer(final InputStream inputStream) { // reject null early on rather than waiting for IO operation to fail // not checked by BufferedInputStream Objects.requireNonNull(inputStream, "inputStream"); return inputStream instanceof BufferedInputStream ? (BufferedInputStream) inputStream : new BufferedInputStream(inputStream); } /** * Returns the given InputStream if it is already a {@link BufferedInputStream}, otherwise creates a * BufferedInputStream from the given InputStream. * * @param inputStream the InputStream to wrap or return (not null) * @param size the buffer size, if a new BufferedInputStream is created. * @return the given InputStream or a new {@link BufferedInputStream} for the given InputStream * @throws NullPointerException if the input parameter is null * @since 2.5 */ @SuppressWarnings("resource") // parameter null check public static BufferedInputStream buffer(final InputStream inputStream, final int size) { // reject null early on rather than waiting for IO operation to fail // not checked by BufferedInputStream Objects.requireNonNull(inputStream, "inputStream"); return inputStream instanceof BufferedInputStream ? (BufferedInputStream) inputStream : new BufferedInputStream(inputStream, size); } /** * Returns the given OutputStream if it is already a {@link BufferedOutputStream}, otherwise creates a * BufferedOutputStream from the given OutputStream. * * @param outputStream the OutputStream to wrap or return (not null) * @return the given OutputStream or a new {@link BufferedOutputStream} for the given OutputStream * @throws NullPointerException if the input parameter is null * @since 2.5 */ @SuppressWarnings("resource") // parameter null check public static BufferedOutputStream buffer(final OutputStream outputStream) { // reject null early on rather than waiting for IO operation to fail // not checked by BufferedInputStream Objects.requireNonNull(outputStream, "outputStream"); return outputStream instanceof BufferedOutputStream ? (BufferedOutputStream) outputStream : new BufferedOutputStream(outputStream); } /** * Returns the given OutputStream if it is already a {@link BufferedOutputStream}, otherwise creates a * BufferedOutputStream from the given OutputStream. * * @param outputStream the OutputStream to wrap or return (not null) * @param size the buffer size, if a new BufferedOutputStream is created. * @return the given OutputStream or a new {@link BufferedOutputStream} for the given OutputStream * @throws NullPointerException if the input parameter is null * @since 2.5 */ @SuppressWarnings("resource") // parameter null check public static BufferedOutputStream buffer(final OutputStream outputStream, final int size) { // reject null early on rather than waiting for IO operation to fail // not checked by BufferedInputStream Objects.requireNonNull(outputStream, "outputStream"); return outputStream instanceof BufferedOutputStream ? (BufferedOutputStream) outputStream : new BufferedOutputStream(outputStream, size); } /** * Returns the given reader if it is already a {@link BufferedReader}, otherwise creates a BufferedReader from * the given reader. * * @param reader the reader to wrap or return (not null) * @return the given reader or a new {@link BufferedReader} for the given reader * @throws NullPointerException if the input parameter is null * @since 2.5 */ public static BufferedReader buffer(final Reader reader) { return reader instanceof BufferedReader ? (BufferedReader) reader : new BufferedReader(reader); } /** * Returns the given reader if it is already a {@link BufferedReader}, otherwise creates a BufferedReader from the * given reader. * * @param reader the reader to wrap or return (not null) * @param size the buffer size, if a new BufferedReader is created. * @return the given reader or a new {@link BufferedReader} for the given reader * @throws NullPointerException if the input parameter is null * @since 2.5 */ public static BufferedReader buffer(final Reader reader, final int size) { return reader instanceof BufferedReader ? (BufferedReader) reader : new BufferedReader(reader, size); } /** * Returns the given Writer if it is already a {@link BufferedWriter}, otherwise creates a BufferedWriter from the * given Writer. * * @param writer the Writer to wrap or return (not null) * @return the given Writer or a new {@link BufferedWriter} for the given Writer * @throws NullPointerException if the input parameter is null * @since 2.5 */ public static BufferedWriter buffer(final Writer writer) { return writer instanceof BufferedWriter ? (BufferedWriter) writer : new BufferedWriter(writer); } /** * Returns the given Writer if it is already a {@link BufferedWriter}, otherwise creates a BufferedWriter from the * given Writer. * * @param writer the Writer to wrap or return (not null) * @param size the buffer size, if a new BufferedWriter is created. * @return the given Writer or a new {@link BufferedWriter} for the given Writer * @throws NullPointerException if the input parameter is null * @since 2.5 */ public static BufferedWriter buffer(final Writer writer, final int size) { return writer instanceof BufferedWriter ? (BufferedWriter) writer : new BufferedWriter(writer, size); } /** * Returns a new byte array of size {@link #DEFAULT_BUFFER_SIZE}. * * @return a new byte array of size {@link #DEFAULT_BUFFER_SIZE}. * @since 2.9.0 */ public static byte[] byteArray() { return byteArray(DEFAULT_BUFFER_SIZE); } /** * Returns a new byte array of the given size. * * TODO Consider guarding or warning against large allocations... * * @param size array size. * @return a new byte array of the given size. * @since 2.9.0 */ public static byte[] byteArray(final int size) { return new byte[size]; } /** * Returns a new char array of size {@link #DEFAULT_BUFFER_SIZE}. * * @return a new char array of size {@link #DEFAULT_BUFFER_SIZE}. * @since 2.9.0 */ private static char[] charArray() { return charArray(DEFAULT_BUFFER_SIZE); } /** * Returns a new char array of the given size. * * TODO Consider guarding or warning against large allocations... * * @param size array size. * @return a new char array of the given size. * @since 2.9.0 */ private static char[] charArray(final int size) { return new char[size]; } /** * Closes the given {@link Closeable} as a null-safe operation. * * @param closeable The resource to close, may be null. * @throws IOException if an I/O error occurs. * @since 2.7 */ public static void close(final Closeable closeable) throws IOException { if (closeable != null) { closeable.close(); } } /** * Closes the given {@link Closeable} as a null-safe operation. * * @param closeables The resource(s) to close, may be null. * @throws IOException if an I/O error occurs. * @since 2.8.0 */ public static void close(final Closeable... closeables) throws IOException { if (closeables != null) { for (final Closeable closeable : closeables) { close(closeable); } } } /** * Closes the given {@link Closeable} as a null-safe operation. * * @param closeable The resource to close, may be null. * @param consumer Consume the IOException thrown by {@link Closeable#close()}. * @throws IOException if an I/O error occurs. * @since 2.7 */ public static void close(final Closeable closeable, final IOConsumer consumer) throws IOException { if (closeable != null) { try { closeable.close(); } catch (final IOException e) { if (consumer != null) { consumer.accept(e); } } } } /** * Closes a URLConnection. * * @param conn the connection to close. * @since 2.4 */ public static void close(final URLConnection conn) { if (conn instanceof HttpURLConnection) { ((HttpURLConnection) conn).disconnect(); } } /** * Closes a {@code Closeable} unconditionally. * *

* Equivalent to {@link Closeable#close()}, except any exceptions will be ignored. This is typically used in * finally blocks. *

* Example code: *

*
     * Closeable closeable = null;
     * try {
     *     closeable = new FileReader("foo.txt");
     *     // process closeable
     *     closeable.close();
     * } catch (Exception e) {
     *     // error handling
     * } finally {
     *     IOUtils.closeQuietly(closeable);
     * }
     * 
*

* Closing all streams: *

*
     * try {
     *     return IOUtils.copy(inputStream, outputStream);
     * } finally {
     *     IOUtils.closeQuietly(inputStream);
     *     IOUtils.closeQuietly(outputStream);
     * }
     * 
*

* Also consider using a try-with-resources statement where appropriate. *

* * @param closeable the objects to close, may be null or already closed * @since 2.0 * * @see Throwable#addSuppressed(java.lang.Throwable) */ public static void closeQuietly(final Closeable closeable) { closeQuietly(closeable, (Consumer) null); } /** * Closes a {@code Closeable} unconditionally. *

* Equivalent to {@link Closeable#close()}, except any exceptions will be ignored. *

* This is typically used in finally blocks to ensure that the closeable is closed * even if an Exception was thrown before the normal close statement was reached. *
* It should not be used to replace the close statement(s) * which should be present for the non-exceptional case. *
* It is only intended to simplify tidying up where normal processing has already failed * and reporting close failure as well is not necessary or useful. *

* Example code: *

*
     * Closeable closeable = null;
     * try {
     *     closeable = new FileReader("foo.txt");
     *     // processing using the closeable; may throw an Exception
     *     closeable.close(); // Normal close - exceptions not ignored
     * } catch (Exception e) {
     *     // error handling
     * } finally {
     *     IOUtils.closeQuietly(closeable); // In case normal close was skipped due to Exception
     * }
     * 
*

* Closing all streams: *
*

     * try {
     *     return IOUtils.copy(inputStream, outputStream);
     * } finally {
     *     IOUtils.closeQuietly(inputStream, outputStream);
     * }
     * 
*

* Also consider using a try-with-resources statement where appropriate. *

* @param closeables the objects to close, may be null or already closed * @see #closeQuietly(Closeable) * @since 2.5 * @see Throwable#addSuppressed(java.lang.Throwable) */ public static void closeQuietly(final Closeable... closeables) { if (closeables == null) { return; } for (final Closeable closeable : closeables) { closeQuietly(closeable); } } /** * Closes the given {@link Closeable} as a null-safe operation while consuming IOException by the given {@code consumer}. * * @param closeable The resource to close, may be null. * @param consumer Consumes the IOException thrown by {@link Closeable#close()}. * @since 2.7 */ public static void closeQuietly(final Closeable closeable, final Consumer consumer) { if (closeable != null) { try { closeable.close(); } catch (final IOException e) { if (consumer != null) { consumer.accept(e); } } } } /** * Closes an {@code InputStream} unconditionally. *

* Equivalent to {@link InputStream#close()}, except any exceptions will be ignored. * This is typically used in finally blocks. *

* Example code: *

     *   byte[] data = new byte[1024];
     *   InputStream in = null;
     *   try {
     *       in = new FileInputStream("foo.txt");
     *       in.read(data);
     *       in.close(); //close errors are handled
     *   } catch (Exception e) {
     *       // error handling
     *   } finally {
     *       IOUtils.closeQuietly(in);
     *   }
     * 
*

* Also consider using a try-with-resources statement where appropriate. *

* * @param input the InputStream to close, may be null or already closed * @see Throwable#addSuppressed(java.lang.Throwable) */ public static void closeQuietly(final InputStream input) { closeQuietly((Closeable) input); } /** * Closes an {@code OutputStream} unconditionally. *

* Equivalent to {@link OutputStream#close()}, except any exceptions will be ignored. * This is typically used in finally blocks. *

* Example code: *

     * byte[] data = "Hello, World".getBytes();
     *
     * OutputStream out = null;
     * try {
     *     out = new FileOutputStream("foo.txt");
     *     out.write(data);
     *     out.close(); //close errors are handled
     * } catch (IOException e) {
     *     // error handling
     * } finally {
     *     IOUtils.closeQuietly(out);
     * }
     * 
*

* Also consider using a try-with-resources statement where appropriate. *

* * @param output the OutputStream to close, may be null or already closed * @see Throwable#addSuppressed(java.lang.Throwable) */ public static void closeQuietly(final OutputStream output) { closeQuietly((Closeable) output); } /** * Closes an {@code Reader} unconditionally. *

* Equivalent to {@link Reader#close()}, except any exceptions will be ignored. * This is typically used in finally blocks. *

* Example code: *

     *   char[] data = new char[1024];
     *   Reader in = null;
     *   try {
     *       in = new FileReader("foo.txt");
     *       in.read(data);
     *       in.close(); //close errors are handled
     *   } catch (Exception e) {
     *       // error handling
     *   } finally {
     *       IOUtils.closeQuietly(in);
     *   }
     * 
*

* Also consider using a try-with-resources statement where appropriate. *

* * @param reader the Reader to close, may be null or already closed * @see Throwable#addSuppressed(java.lang.Throwable) */ public static void closeQuietly(final Reader reader) { closeQuietly((Closeable) reader); } /** * Closes a {@code Selector} unconditionally. *

* Equivalent to {@link Selector#close()}, except any exceptions will be ignored. * This is typically used in finally blocks. *

* Example code: *

     *   Selector selector = null;
     *   try {
     *       selector = Selector.open();
     *       // process socket
     *
     *   } catch (Exception e) {
     *       // error handling
     *   } finally {
     *       IOUtils.closeQuietly(selector);
     *   }
     * 
*

* Also consider using a try-with-resources statement where appropriate. *

* * @param selector the Selector to close, may be null or already closed * @since 2.2 * @see Throwable#addSuppressed(java.lang.Throwable) */ public static void closeQuietly(final Selector selector) { closeQuietly((Closeable) selector); } /** * Closes a {@code ServerSocket} unconditionally. *

* Equivalent to {@link ServerSocket#close()}, except any exceptions will be ignored. * This is typically used in finally blocks. *

* Example code: *

     *   ServerSocket socket = null;
     *   try {
     *       socket = new ServerSocket();
     *       // process socket
     *       socket.close();
     *   } catch (Exception e) {
     *       // error handling
     *   } finally {
     *       IOUtils.closeQuietly(socket);
     *   }
     * 
*

* Also consider using a try-with-resources statement where appropriate. *

* * @param serverSocket the ServerSocket to close, may be null or already closed * @since 2.2 * @see Throwable#addSuppressed(java.lang.Throwable) */ public static void closeQuietly(final ServerSocket serverSocket) { closeQuietly((Closeable) serverSocket); } /** * Closes a {@code Socket} unconditionally. *

* Equivalent to {@link Socket#close()}, except any exceptions will be ignored. * This is typically used in finally blocks. *

* Example code: *

     *   Socket socket = null;
     *   try {
     *       socket = new Socket("http://www.foo.com/", 80);
     *       // process socket
     *       socket.close();
     *   } catch (Exception e) {
     *       // error handling
     *   } finally {
     *       IOUtils.closeQuietly(socket);
     *   }
     * 
*

* Also consider using a try-with-resources statement where appropriate. *

* * @param socket the Socket to close, may be null or already closed * @since 2.0 * @see Throwable#addSuppressed(java.lang.Throwable) */ public static void closeQuietly(final Socket socket) { closeQuietly((Closeable) socket); } /** * Closes an {@code Writer} unconditionally. *

* Equivalent to {@link Writer#close()}, except any exceptions will be ignored. * This is typically used in finally blocks. *

* Example code: *

     *   Writer out = null;
     *   try {
     *       out = new StringWriter();
     *       out.write("Hello World");
     *       out.close(); //close errors are handled
     *   } catch (Exception e) {
     *       // error handling
     *   } finally {
     *       IOUtils.closeQuietly(out);
     *   }
     * 
*

* Also consider using a try-with-resources statement where appropriate. *

* * @param writer the Writer to close, may be null or already closed * @see Throwable#addSuppressed(java.lang.Throwable) */ public static void closeQuietly(final Writer writer) { closeQuietly((Closeable) writer); } /** * Consumes bytes from a {@code InputStream} and ignores them. *

* The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}. *

* * @param input the {@code InputStream} to read. * @return the number of bytes copied. or {@code 0} if {@code input is null}. * @throws NullPointerException if the InputStream is {@code null}. * @throws NullPointerException if the OutputStream is {@code null}. * @throws IOException if an I/O error occurs. * @since 2.8.0 */ public static long consume(final InputStream input) throws IOException { return copyLarge(input, NullOutputStream.NULL_OUTPUT_STREAM, getByteArray()); } /** * Compares the contents of two Streams to determine if they are equal or * not. *

* This method buffers the input internally using * {@code BufferedInputStream} if they are not already buffered. *

* * @param input1 the first stream * @param input2 the second stream * @return true if the content of the streams are equal or they both don't * exist, false otherwise * @throws NullPointerException if either input is null * @throws IOException if an I/O error occurs */ public static boolean contentEquals(final InputStream input1, final InputStream input2) throws IOException { // Before making any changes, please test with // org.apache.commons.io.jmh.IOUtilsContentEqualsInputStreamsBenchmark if (input1 == input2) { return true; } if (input1 == null || input2 == null) { return false; } // reuse one final byte[] array1 = getByteArray(); // allocate another final byte[] array2 = byteArray(); int pos1; int pos2; int count1; int count2; while (true) { pos1 = 0; pos2 = 0; for (int index = 0; index < DEFAULT_BUFFER_SIZE; index++) { if (pos1 == index) { do { count1 = input1.read(array1, pos1, DEFAULT_BUFFER_SIZE - pos1); } while (count1 == 0); if (count1 == EOF) { return pos2 == index && input2.read() == EOF; } pos1 += count1; } if (pos2 == index) { do { count2 = input2.read(array2, pos2, DEFAULT_BUFFER_SIZE - pos2); } while (count2 == 0); if (count2 == EOF) { return pos1 == index && input1.read() == EOF; } pos2 += count2; } if (array1[index] != array2[index]) { return false; } } } } /** * Compares the contents of two Readers to determine if they are equal or not. *

* This method buffers the input internally using {@code BufferedReader} if they are not already buffered. *

* * @param input1 the first reader * @param input2 the second reader * @return true if the content of the readers are equal or they both don't exist, false otherwise * @throws NullPointerException if either input is null * @throws IOException if an I/O error occurs * @since 1.1 */ public static boolean contentEquals(final Reader input1, final Reader input2) throws IOException { if (input1 == input2) { return true; } if (input1 == null || input2 == null) { return false; } // reuse one final char[] array1 = getCharArray(); // but allocate another final char[] array2 = charArray(); int pos1; int pos2; int count1; int count2; while (true) { pos1 = 0; pos2 = 0; for (int index = 0; index < DEFAULT_BUFFER_SIZE; index++) { if (pos1 == index) { do { count1 = input1.read(array1, pos1, DEFAULT_BUFFER_SIZE - pos1); } while (count1 == 0); if (count1 == EOF) { return pos2 == index && input2.read() == EOF; } pos1 += count1; } if (pos2 == index) { do { count2 = input2.read(array2, pos2, DEFAULT_BUFFER_SIZE - pos2); } while (count2 == 0); if (count2 == EOF) { return pos1 == index && input1.read() == EOF; } pos2 += count2; } if (array1[index] != array2[index]) { return false; } } } } /** * Compares the contents of two Readers to determine if they are equal or * not, ignoring EOL characters. *

* This method buffers the input internally using * {@code BufferedReader} if they are not already buffered. * * @param reader1 the first reader * @param reader2 the second reader * @return true if the content of the readers are equal (ignoring EOL differences), false otherwise * @throws NullPointerException if either input is null * @throws IOException if an I/O error occurs * @since 2.2 */ @SuppressWarnings("resource") public static boolean contentEqualsIgnoreEOL(final Reader reader1, final Reader reader2) throws IOException { if (reader1 == reader2) { return true; } if (reader1 == null ^ reader2 == null) { return false; } final BufferedReader br1 = toBufferedReader(reader1); final BufferedReader br2 = toBufferedReader(reader2); String line1 = br1.readLine(); String line2 = br2.readLine(); while (line1 != null && line1.equals(line2)) { line1 = br1.readLine(); line2 = br2.readLine(); } return Objects.equals(line1, line2); } /** * Copies bytes from an {@code InputStream} to an {@code OutputStream}. *

* This method buffers the input internally, so there is no need to use a {@code BufferedInputStream}. *

*

* Large streams (over 2GB) will return a bytes copied value of {@code -1} after the copy has completed since * the correct number of bytes cannot be returned as an int. For large streams use the * {@code copyLarge(InputStream, OutputStream)} method. *

* * @param inputStream the {@code InputStream} to read. * @param outputStream the {@code OutputStream} to write. * @return the number of bytes copied, or -1 if greater than {@link Integer#MAX_VALUE}. * @throws NullPointerException if the InputStream is {@code null}. * @throws NullPointerException if the OutputStream is {@code null}. * @throws IOException if an I/O error occurs. * @since 1.1 */ public static int copy(final InputStream inputStream, final OutputStream outputStream) throws IOException { final long count = copyLarge(inputStream, outputStream); if (count > Integer.MAX_VALUE) { return EOF; } return (int) count; } /** * Copies bytes from an {@code InputStream} to an {@code OutputStream} using an internal buffer of the * given size. *

* This method buffers the input internally, so there is no need to use a {@code BufferedInputStream}. *

* * @param inputStream the {@code InputStream} to read. * @param outputStream the {@code OutputStream} to write to * @param bufferSize the bufferSize used to copy from the input to the output * @return the number of bytes copied. * @throws NullPointerException if the InputStream is {@code null}. * @throws NullPointerException if the OutputStream is {@code null}. * @throws IOException if an I/O error occurs. * @since 2.5 */ public static long copy(final InputStream inputStream, final OutputStream outputStream, final int bufferSize) throws IOException { return copyLarge(inputStream, outputStream, IOUtils.byteArray(bufferSize)); } /** * Copies bytes from an {@code InputStream} to chars on a * {@code Writer} using the default character encoding of the platform. *

* This method buffers the input internally, so there is no need to use a * {@code BufferedInputStream}. *

* This method uses {@link InputStreamReader}. * * @param input the {@code InputStream} to read from * @param writer the {@code Writer} to write to * @throws NullPointerException if the input or output is null * @throws IOException if an I/O error occurs * @since 1.1 * @deprecated 2.5 use {@link #copy(InputStream, Writer, Charset)} instead */ @Deprecated public static void copy(final InputStream input, final Writer writer) throws IOException { copy(input, writer, Charset.defaultCharset()); } /** * Copies bytes from an {@code InputStream} to chars on a * {@code Writer} using the specified character encoding. *

* This method buffers the input internally, so there is no need to use a * {@code BufferedInputStream}. *

* This method uses {@link InputStreamReader}. * * @param input the {@code InputStream} to read from * @param writer the {@code Writer} to write to * @param inputCharset the charset to use for the input stream, null means platform default * @throws NullPointerException if the input or output is null * @throws IOException if an I/O error occurs * @since 2.3 */ public static void copy(final InputStream input, final Writer writer, final Charset inputCharset) throws IOException { final InputStreamReader reader = new InputStreamReader(input, Charsets.toCharset(inputCharset)); copy(reader, writer); } /** * Copies bytes from an {@code InputStream} to chars on a * {@code Writer} using the specified character encoding. *

* This method buffers the input internally, so there is no need to use a * {@code BufferedInputStream}. *

* Character encoding names can be found at * IANA. *

* This method uses {@link InputStreamReader}. * * @param input the {@code InputStream} to read from * @param writer the {@code Writer} to write to * @param inputCharsetName the name of the requested charset for the InputStream, null means platform default * @throws NullPointerException if the input or output is null * @throws IOException if an I/O error occurs * @throws java.nio.charset.UnsupportedCharsetException thrown instead of {@link java.io * .UnsupportedEncodingException} in version 2.2 if the * encoding is not supported. * @since 1.1 */ public static void copy(final InputStream input, final Writer writer, final String inputCharsetName) throws IOException { copy(input, writer, Charsets.toCharset(inputCharsetName)); } /** * Copies chars from a {@code Reader} to a {@code Appendable}. *

* This method buffers the input internally, so there is no need to use a * {@code BufferedReader}. *

* Large streams (over 2GB) will return a chars copied value of * {@code -1} after the copy has completed since the correct * number of chars cannot be returned as an int. For large streams * use the {@code copyLarge(Reader, Writer)} method. * * @param reader the {@code Reader} to read from * @param output the {@code Appendable} to write to * @return the number of characters copied, or -1 if > Integer.MAX_VALUE * @throws NullPointerException if the input or output is null * @throws IOException if an I/O error occurs * @since 2.7 */ public static long copy(final Reader reader, final Appendable output) throws IOException { return copy(reader, output, CharBuffer.allocate(DEFAULT_BUFFER_SIZE)); } /** * Copies chars from a {@code Reader} to an {@code Appendable}. *

* This method uses the provided buffer, so there is no need to use a * {@code BufferedReader}. *

* * @param reader the {@code Reader} to read from * @param output the {@code Appendable} to write to * @param buffer the buffer to be used for the copy * @return the number of characters copied * @throws NullPointerException if the input or output is null * @throws IOException if an I/O error occurs * @since 2.7 */ public static long copy(final Reader reader, final Appendable output, final CharBuffer buffer) throws IOException { long count = 0; int n; while (EOF != (n = reader.read(buffer))) { buffer.flip(); output.append(buffer, 0, n); count += n; } return count; } /** * Copies chars from a {@code Reader} to bytes on an * {@code OutputStream} using the default character encoding of the * platform, and calling flush. *

* This method buffers the input internally, so there is no need to use a * {@code BufferedReader}. *

* Due to the implementation of OutputStreamWriter, this method performs a * flush. *

* This method uses {@link OutputStreamWriter}. * * @param reader the {@code Reader} to read from * @param output the {@code OutputStream} to write to * @throws NullPointerException if the input or output is null * @throws IOException if an I/O error occurs * @since 1.1 * @deprecated 2.5 use {@link #copy(Reader, OutputStream, Charset)} instead */ @Deprecated public static void copy(final Reader reader, final OutputStream output) throws IOException { copy(reader, output, Charset.defaultCharset()); } /** * Copies chars from a {@code Reader} to bytes on an * {@code OutputStream} using the specified character encoding, and * calling flush. *

* This method buffers the input internally, so there is no need to use a * {@code BufferedReader}. *

*

* Due to the implementation of OutputStreamWriter, this method performs a * flush. *

*

* This method uses {@link OutputStreamWriter}. *

* * @param reader the {@code Reader} to read from * @param output the {@code OutputStream} to write to * @param outputCharset the charset to use for the OutputStream, null means platform default * @throws NullPointerException if the input or output is null * @throws IOException if an I/O error occurs * @since 2.3 */ public static void copy(final Reader reader, final OutputStream output, final Charset outputCharset) throws IOException { final OutputStreamWriter writer = new OutputStreamWriter(output, Charsets.toCharset(outputCharset)); copy(reader, writer); // XXX Unless anyone is planning on rewriting OutputStreamWriter, // we have to flush here. writer.flush(); } /** * Copies chars from a {@code Reader} to bytes on an * {@code OutputStream} using the specified character encoding, and * calling flush. *

* This method buffers the input internally, so there is no need to use a * {@code BufferedReader}. *

* Character encoding names can be found at * IANA. *

* Due to the implementation of OutputStreamWriter, this method performs a * flush. *

* This method uses {@link OutputStreamWriter}. * * @param reader the {@code Reader} to read from * @param output the {@code OutputStream} to write to * @param outputCharsetName the name of the requested charset for the OutputStream, null means platform default * @throws NullPointerException if the input or output is null * @throws IOException if an I/O error occurs * @throws java.nio.charset.UnsupportedCharsetException thrown instead of {@link java.io * .UnsupportedEncodingException} in version 2.2 if the * encoding is not supported. * @since 1.1 */ public static void copy(final Reader reader, final OutputStream output, final String outputCharsetName) throws IOException { copy(reader, output, Charsets.toCharset(outputCharsetName)); } /** * Copies chars from a {@code Reader} to a {@code Writer}. *

* This method buffers the input internally, so there is no need to use a * {@code BufferedReader}. *

* Large streams (over 2GB) will return a chars copied value of * {@code -1} after the copy has completed since the correct * number of chars cannot be returned as an int. For large streams * use the {@code copyLarge(Reader, Writer)} method. * * @param reader the {@code Reader} to read. * @param writer the {@code Writer} to write. * @return the number of characters copied, or -1 if > Integer.MAX_VALUE * @throws NullPointerException if the input or output is null * @throws IOException if an I/O error occurs * @since 1.1 */ public static int copy(final Reader reader, final Writer writer) throws IOException { final long count = copyLarge(reader, writer); if (count > Integer.MAX_VALUE) { return EOF; } return (int) count; } /** * Copies bytes from a {@code URL} to an {@code OutputStream}. *

* This method buffers the input internally, so there is no need to use a {@code BufferedInputStream}. *

*

* The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}. *

* * @param url the {@code URL} to read. * @param file the {@code OutputStream} to write. * @return the number of bytes copied. * @throws NullPointerException if the URL is {@code null}. * @throws NullPointerException if the OutputStream is {@code null}. * @throws IOException if an I/O error occurs. * @since 2.9.0 */ public static long copy(final URL url, final File file) throws IOException { try (OutputStream outputStream = Files.newOutputStream(Objects.requireNonNull(file, "file").toPath())) { return copy(url, outputStream); } } /** * Copies bytes from a {@code URL} to an {@code OutputStream}. *

* This method buffers the input internally, so there is no need to use a {@code BufferedInputStream}. *

*

* The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}. *

* * @param url the {@code URL} to read. * @param outputStream the {@code OutputStream} to write. * @return the number of bytes copied. * @throws NullPointerException if the URL is {@code null}. * @throws NullPointerException if the OutputStream is {@code null}. * @throws IOException if an I/O error occurs. * @since 2.9.0 */ public static long copy(final URL url, final OutputStream outputStream) throws IOException { try (InputStream inputStream = Objects.requireNonNull(url, "url").openStream()) { return copyLarge(inputStream, outputStream); } } /** * Copies bytes from a large (over 2GB) {@code InputStream} to an * {@code OutputStream}. *

* This method buffers the input internally, so there is no need to use a * {@code BufferedInputStream}. *

*

* The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}. *

* * @param inputStream the {@code InputStream} to read. * @param outputStream the {@code OutputStream} to write. * @return the number of bytes copied. * @throws NullPointerException if the InputStream is {@code null}. * @throws NullPointerException if the OutputStream is {@code null}. * @throws IOException if an I/O error occurs. * @since 1.3 */ public static long copyLarge(final InputStream inputStream, final OutputStream outputStream) throws IOException { return copy(inputStream, outputStream, DEFAULT_BUFFER_SIZE); } /** * Copies bytes from a large (over 2GB) {@code InputStream} to an * {@code OutputStream}. *

* This method uses the provided buffer, so there is no need to use a * {@code BufferedInputStream}. *

* * @param inputStream the {@code InputStream} to read. * @param outputStream the {@code OutputStream} to write. * @param buffer the buffer to use for the copy * @return the number of bytes copied. * @throws NullPointerException if the InputStream is {@code null}. * @throws NullPointerException if the OutputStream is {@code null}. * @throws IOException if an I/O error occurs. * @since 2.2 */ @SuppressWarnings("resource") // streams are closed by the caller. public static long copyLarge(final InputStream inputStream, final OutputStream outputStream, final byte[] buffer) throws IOException { Objects.requireNonNull(inputStream, "inputStream"); Objects.requireNonNull(outputStream, "outputStream"); long count = 0; int n; while (EOF != (n = inputStream.read(buffer))) { outputStream.write(buffer, 0, n); count += n; } return count; } /** * Copies some or all bytes from a large (over 2GB) {@code InputStream} to an * {@code OutputStream}, optionally skipping input bytes. *

* This method buffers the input internally, so there is no need to use a * {@code BufferedInputStream}. *

*

* Note that the implementation uses {@link #skip(InputStream, long)}. * This means that the method may be considerably less efficient than using the actual skip implementation, * this is done to guarantee that the correct number of characters are skipped. *

* The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}. * * @param input the {@code InputStream} to read from * @param output the {@code OutputStream} to write to * @param inputOffset : number of bytes to skip from input before copying * -ve values are ignored * @param length : number of bytes to copy. -ve means all * @return the number of bytes copied * @throws NullPointerException if the input or output is null * @throws IOException if an I/O error occurs * @since 2.2 */ public static long copyLarge(final InputStream input, final OutputStream output, final long inputOffset, final long length) throws IOException { return copyLarge(input, output, inputOffset, length, getByteArray()); } /** * Copies some or all bytes from a large (over 2GB) {@code InputStream} to an * {@code OutputStream}, optionally skipping input bytes. *

* This method uses the provided buffer, so there is no need to use a * {@code BufferedInputStream}. *

*

* Note that the implementation uses {@link #skip(InputStream, long)}. * This means that the method may be considerably less efficient than using the actual skip implementation, * this is done to guarantee that the correct number of characters are skipped. *

* * @param input the {@code InputStream} to read from * @param output the {@code OutputStream} to write to * @param inputOffset : number of bytes to skip from input before copying * -ve values are ignored * @param length : number of bytes to copy. -ve means all * @param buffer the buffer to use for the copy * @return the number of bytes copied * @throws NullPointerException if the input or output is null * @throws IOException if an I/O error occurs * @since 2.2 */ public static long copyLarge(final InputStream input, final OutputStream output, final long inputOffset, final long length, final byte[] buffer) throws IOException { if (inputOffset > 0) { skipFully(input, inputOffset); } if (length == 0) { return 0; } final int bufferLength = buffer.length; int bytesToRead = bufferLength; if (length > 0 && length < bufferLength) { bytesToRead = (int) length; } int read; long totalRead = 0; while (bytesToRead > 0 && EOF != (read = input.read(buffer, 0, bytesToRead))) { output.write(buffer, 0, read); totalRead += read; if (length > 0) { // only adjust length if not reading to the end // Note the cast must work because buffer.length is an integer bytesToRead = (int) Math.min(length - totalRead, bufferLength); } } return totalRead; } /** * Copies chars from a large (over 2GB) {@code Reader} to a {@code Writer}. *

* This method buffers the input internally, so there is no need to use a * {@code BufferedReader}. *

* The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}. * * @param reader the {@code Reader} to source. * @param writer the {@code Writer} to target. * @return the number of characters copied * @throws NullPointerException if the input or output is null * @throws IOException if an I/O error occurs * @since 1.3 */ public static long copyLarge(final Reader reader, final Writer writer) throws IOException { return copyLarge(reader, writer, getCharArray()); } /** * Copies chars from a large (over 2GB) {@code Reader} to a {@code Writer}. *

* This method uses the provided buffer, so there is no need to use a * {@code BufferedReader}. *

* * @param reader the {@code Reader} to source. * @param writer the {@code Writer} to target. * @param buffer the buffer to be used for the copy * @return the number of characters copied * @throws NullPointerException if the input or output is null * @throws IOException if an I/O error occurs * @since 2.2 */ public static long copyLarge(final Reader reader, final Writer writer, final char[] buffer) throws IOException { long count = 0; int n; while (EOF != (n = reader.read(buffer))) { writer.write(buffer, 0, n); count += n; } return count; } /** * Copies some or all chars from a large (over 2GB) {@code InputStream} to an * {@code OutputStream}, optionally skipping input chars. *

* This method buffers the input internally, so there is no need to use a * {@code BufferedReader}. *

* The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}. * * @param reader the {@code Reader} to read from * @param writer the {@code Writer} to write to * @param inputOffset : number of chars to skip from input before copying * -ve values are ignored * @param length : number of chars to copy. -ve means all * @return the number of chars copied * @throws NullPointerException if the input or output is null * @throws IOException if an I/O error occurs * @since 2.2 */ public static long copyLarge(final Reader reader, final Writer writer, final long inputOffset, final long length) throws IOException { return copyLarge(reader, writer, inputOffset, length, getCharArray()); } /** * Copies some or all chars from a large (over 2GB) {@code InputStream} to an * {@code OutputStream}, optionally skipping input chars. *

* This method uses the provided buffer, so there is no need to use a * {@code BufferedReader}. *

* * @param reader the {@code Reader} to read from * @param writer the {@code Writer} to write to * @param inputOffset : number of chars to skip from input before copying * -ve values are ignored * @param length : number of chars to copy. -ve means all * @param buffer the buffer to be used for the copy * @return the number of chars copied * @throws NullPointerException if the input or output is null * @throws IOException if an I/O error occurs * @since 2.2 */ public static long copyLarge(final Reader reader, final Writer writer, final long inputOffset, final long length, final char[] buffer) throws IOException { if (inputOffset > 0) { skipFully(reader, inputOffset); } if (length == 0) { return 0; } int bytesToRead = buffer.length; if (length > 0 && length < buffer.length) { bytesToRead = (int) length; } int read; long totalRead = 0; while (bytesToRead > 0 && EOF != (read = reader.read(buffer, 0, bytesToRead))) { writer.write(buffer, 0, read); totalRead += read; if (length > 0) { // only adjust length if not reading to the end // Note the cast must work because buffer.length is an integer bytesToRead = (int) Math.min(length - totalRead, buffer.length); } } return totalRead; } /** * Gets the thread local byte array. * * @return the thread local byte array. */ static byte[] getByteArray() { return SKIP_BYTE_BUFFER.get(); } /** * Gets the thread local char array. * * @return the thread local char array. */ static char[] getCharArray() { return SKIP_CHAR_BUFFER.get(); } /** * Returns the length of the given array in a null-safe manner. * * @param array an array or null * @return the array length -- or 0 if the given array is null. * @since 2.7 */ public static int length(final byte[] array) { return array == null ? 0 : array.length; } /** * Returns the length of the given array in a null-safe manner. * * @param array an array or null * @return the array length -- or 0 if the given array is null. * @since 2.7 */ public static int length(final char[] array) { return array == null ? 0 : array.length; } /** * Returns the length of the given CharSequence in a null-safe manner. * * @param csq a CharSequence or null * @return the CharSequence length -- or 0 if the given CharSequence is null. * @since 2.7 */ public static int length(final CharSequence csq) { return csq == null ? 0 : csq.length(); } /** * Returns the length of the given array in a null-safe manner. * * @param array an array or null * @return the array length -- or 0 if the given array is null. * @since 2.7 */ public static int length(final Object[] array) { return array == null ? 0 : array.length; } /** * Returns an Iterator for the lines in an {@code InputStream}, using * the character encoding specified (or default encoding if null). *

* {@code LineIterator} holds a reference to the open * {@code InputStream} specified here. When you have finished with * the iterator you should close the stream to free internal resources. * This can be done by closing the stream directly, or by calling * {@link LineIterator#close()} or {@link LineIterator#closeQuietly(LineIterator)}. *

* The recommended usage pattern is: *

     * try {
     *   LineIterator it = IOUtils.lineIterator(stream, charset);
     *   while (it.hasNext()) {
     *     String line = it.nextLine();
     *     /// do something with line
     *   }
     * } finally {
     *   IOUtils.closeQuietly(stream);
     * }
     * 
* * @param input the {@code InputStream} to read from, not null * @param charset the charset to use, null means platform default * @return an Iterator of the lines in the reader, never null * @throws IllegalArgumentException if the input is null * @since 2.3 */ public static LineIterator lineIterator(final InputStream input, final Charset charset) { return new LineIterator(new InputStreamReader(input, Charsets.toCharset(charset))); } /** * Returns an Iterator for the lines in an {@code InputStream}, using * the character encoding specified (or default encoding if null). *

* {@code LineIterator} holds a reference to the open * {@code InputStream} specified here. When you have finished with * the iterator you should close the stream to free internal resources. * This can be done by closing the stream directly, or by calling * {@link LineIterator#close()} or {@link LineIterator#closeQuietly(LineIterator)}. *

* The recommended usage pattern is: *

     * try {
     *   LineIterator it = IOUtils.lineIterator(stream, "UTF-8");
     *   while (it.hasNext()) {
     *     String line = it.nextLine();
     *     /// do something with line
     *   }
     * } finally {
     *   IOUtils.closeQuietly(stream);
     * }
     * 
* * @param input the {@code InputStream} to read from, not null * @param charsetName the encoding to use, null means platform default * @return an Iterator of the lines in the reader, never null * @throws IllegalArgumentException if the input is null * @throws java.nio.charset.UnsupportedCharsetException thrown instead of {@link java.io * .UnsupportedEncodingException} in version 2.2 if the * encoding is not supported. * @since 1.2 */ public static LineIterator lineIterator(final InputStream input, final String charsetName) { return lineIterator(input, Charsets.toCharset(charsetName)); } /** * Returns an Iterator for the lines in a {@code Reader}. *

* {@code LineIterator} holds a reference to the open * {@code Reader} specified here. When you have finished with the * iterator you should close the reader to free internal resources. * This can be done by closing the reader directly, or by calling * {@link LineIterator#close()} or {@link LineIterator#closeQuietly(LineIterator)}. *

* The recommended usage pattern is: *

     * try {
     *   LineIterator it = IOUtils.lineIterator(reader);
     *   while (it.hasNext()) {
     *     String line = it.nextLine();
     *     /// do something with line
     *   }
     * } finally {
     *   IOUtils.closeQuietly(reader);
     * }
     * 
* * @param reader the {@code Reader} to read from, not null * @return an Iterator of the lines in the reader, never null * @throws IllegalArgumentException if the reader is null * @since 1.2 */ public static LineIterator lineIterator(final Reader reader) { return new LineIterator(reader); } /** * Reads bytes from an input stream. * This implementation guarantees that it will read as many bytes * as possible before giving up; this may not always be the case for * subclasses of {@link InputStream}. * * @param input where to read input from * @param buffer destination * @return actual length read; may be less than requested if EOF was reached * @throws IOException if a read error occurs * @since 2.2 */ public static int read(final InputStream input, final byte[] buffer) throws IOException { return read(input, buffer, 0, buffer.length); } /** * Reads bytes from an input stream. * This implementation guarantees that it will read as many bytes * as possible before giving up; this may not always be the case for * subclasses of {@link InputStream}. * * @param input where to read input from * @param buffer destination * @param offset initial offset into buffer * @param length length to read, must be >= 0 * @return actual length read; may be less than requested if EOF was reached * @throws IOException if a read error occurs * @since 2.2 */ public static int read(final InputStream input, final byte[] buffer, final int offset, final int length) throws IOException { if (length < 0) { throw new IllegalArgumentException("Length must not be negative: " + length); } int remaining = length; while (remaining > 0) { final int location = length - remaining; final int count = input.read(buffer, offset + location, remaining); if (EOF == count) { // EOF break; } remaining -= count; } return length - remaining; } /** * Reads bytes from a ReadableByteChannel. *

* This implementation guarantees that it will read as many bytes * as possible before giving up; this may not always be the case for * subclasses of {@link ReadableByteChannel}. * * @param input the byte channel to read * @param buffer byte buffer destination * @return the actual length read; may be less than requested if EOF was reached * @throws IOException if a read error occurs * @since 2.5 */ public static int read(final ReadableByteChannel input, final ByteBuffer buffer) throws IOException { final int length = buffer.remaining(); while (buffer.remaining() > 0) { final int count = input.read(buffer); if (EOF == count) { // EOF break; } } return length - buffer.remaining(); } /** * Reads characters from an input character stream. * This implementation guarantees that it will read as many characters * as possible before giving up; this may not always be the case for * subclasses of {@link Reader}. * * @param reader where to read input from * @param buffer destination * @return actual length read; may be less than requested if EOF was reached * @throws IOException if a read error occurs * @since 2.2 */ public static int read(final Reader reader, final char[] buffer) throws IOException { return read(reader, buffer, 0, buffer.length); } /** * Reads characters from an input character stream. * This implementation guarantees that it will read as many characters * as possible before giving up; this may not always be the case for * subclasses of {@link Reader}. * * @param reader where to read input from * @param buffer destination * @param offset initial offset into buffer * @param length length to read, must be >= 0 * @return actual length read; may be less than requested if EOF was reached * @throws IOException if a read error occurs * @since 2.2 */ public static int read(final Reader reader, final char[] buffer, final int offset, final int length) throws IOException { if (length < 0) { throw new IllegalArgumentException("Length must not be negative: " + length); } int remaining = length; while (remaining > 0) { final int location = length - remaining; final int count = reader.read(buffer, offset + location, remaining); if (EOF == count) { // EOF break; } remaining -= count; } return length - remaining; } /** * Reads the requested number of bytes or fail if there are not enough left. *

* This allows for the possibility that {@link InputStream#read(byte[], int, int)} may * not read as many bytes as requested (most likely because of reaching EOF). * * @param input where to read input from * @param buffer destination * * @throws IOException if there is a problem reading the file * @throws IllegalArgumentException if length is negative * @throws EOFException if the number of bytes read was incorrect * @since 2.2 */ public static void readFully(final InputStream input, final byte[] buffer) throws IOException { readFully(input, buffer, 0, buffer.length); } /** * Reads the requested number of bytes or fail if there are not enough left. *

* This allows for the possibility that {@link InputStream#read(byte[], int, int)} may * not read as many bytes as requested (most likely because of reaching EOF). * * @param input where to read input from * @param buffer destination * @param offset initial offset into buffer * @param length length to read, must be >= 0 * * @throws IOException if there is a problem reading the file * @throws IllegalArgumentException if length is negative * @throws EOFException if the number of bytes read was incorrect * @since 2.2 */ public static void readFully(final InputStream input, final byte[] buffer, final int offset, final int length) throws IOException { final int actual = read(input, buffer, offset, length); if (actual != length) { throw new EOFException("Length to read: " + length + " actual: " + actual); } } /** * Reads the requested number of bytes or fail if there are not enough left. *

* This allows for the possibility that {@link InputStream#read(byte[], int, int)} may * not read as many bytes as requested (most likely because of reaching EOF). * * @param input where to read input from * @param length length to read, must be >= 0 * @return the bytes read from input * @throws IOException if there is a problem reading the file * @throws IllegalArgumentException if length is negative * @throws EOFException if the number of bytes read was incorrect * @since 2.5 */ public static byte[] readFully(final InputStream input, final int length) throws IOException { final byte[] buffer = IOUtils.byteArray(length); readFully(input, buffer, 0, buffer.length); return buffer; } /** * Reads the requested number of bytes or fail if there are not enough left. *

* This allows for the possibility that {@link ReadableByteChannel#read(ByteBuffer)} may * not read as many bytes as requested (most likely because of reaching EOF). * * @param input the byte channel to read * @param buffer byte buffer destination * @throws IOException if there is a problem reading the file * @throws EOFException if the number of bytes read was incorrect * @since 2.5 */ public static void readFully(final ReadableByteChannel input, final ByteBuffer buffer) throws IOException { final int expected = buffer.remaining(); final int actual = read(input, buffer); if (actual != expected) { throw new EOFException("Length to read: " + expected + " actual: " + actual); } } /** * Reads the requested number of characters or fail if there are not enough left. *

* This allows for the possibility that {@link Reader#read(char[], int, int)} may * not read as many characters as requested (most likely because of reaching EOF). * * @param reader where to read input from * @param buffer destination * @throws IOException if there is a problem reading the file * @throws IllegalArgumentException if length is negative * @throws EOFException if the number of characters read was incorrect * @since 2.2 */ public static void readFully(final Reader reader, final char[] buffer) throws IOException { readFully(reader, buffer, 0, buffer.length); } /** * Reads the requested number of characters or fail if there are not enough left. *

* This allows for the possibility that {@link Reader#read(char[], int, int)} may * not read as many characters as requested (most likely because of reaching EOF). * * @param reader where to read input from * @param buffer destination * @param offset initial offset into buffer * @param length length to read, must be >= 0 * @throws IOException if there is a problem reading the file * @throws IllegalArgumentException if length is negative * @throws EOFException if the number of characters read was incorrect * @since 2.2 */ public static void readFully(final Reader reader, final char[] buffer, final int offset, final int length) throws IOException { final int actual = read(reader, buffer, offset, length); if (actual != length) { throw new EOFException("Length to read: " + length + " actual: " + actual); } } /** * Gets the contents of an {@code InputStream} as a list of Strings, * one entry per line, using the default character encoding of the platform. *

* This method buffers the input internally, so there is no need to use a * {@code BufferedInputStream}. * * @param input the {@code InputStream} to read from, not null * @return the list of Strings, never null * @throws NullPointerException if the input is null * @throws IOException if an I/O error occurs * @since 1.1 * @deprecated 2.5 use {@link #readLines(InputStream, Charset)} instead */ @Deprecated public static List readLines(final InputStream input) throws IOException { return readLines(input, Charset.defaultCharset()); } /** * Gets the contents of an {@code InputStream} as a list of Strings, * one entry per line, using the specified character encoding. *

* This method buffers the input internally, so there is no need to use a * {@code BufferedInputStream}. * * @param input the {@code InputStream} to read from, not null * @param charset the charset to use, null means platform default * @return the list of Strings, never null * @throws NullPointerException if the input is null * @throws IOException if an I/O error occurs * @since 2.3 */ public static List readLines(final InputStream input, final Charset charset) throws IOException { final InputStreamReader reader = new InputStreamReader(input, Charsets.toCharset(charset)); return readLines(reader); } /** * Gets the contents of an {@code InputStream} as a list of Strings, * one entry per line, using the specified character encoding. *

* Character encoding names can be found at * IANA. *

* This method buffers the input internally, so there is no need to use a * {@code BufferedInputStream}. * * @param input the {@code InputStream} to read from, not null * @param charsetName the name of the requested charset, null means platform default * @return the list of Strings, never null * @throws NullPointerException if the input is null * @throws IOException if an I/O error occurs * @throws java.nio.charset.UnsupportedCharsetException thrown instead of {@link java.io * .UnsupportedEncodingException} in version 2.2 if the * encoding is not supported. * @since 1.1 */ public static List readLines(final InputStream input, final String charsetName) throws IOException { return readLines(input, Charsets.toCharset(charsetName)); } /** * Gets the contents of a {@code Reader} as a list of Strings, * one entry per line. *

* This method buffers the input internally, so there is no need to use a * {@code BufferedReader}. * * @param reader the {@code Reader} to read from, not null * @return the list of Strings, never null * @throws NullPointerException if the input is null * @throws IOException if an I/O error occurs * @since 1.1 */ @SuppressWarnings("resource") // reader wraps input and is the responsibility of the caller. public static List readLines(final Reader reader) throws IOException { final BufferedReader bufReader = toBufferedReader(reader); final List list = new ArrayList<>(); String line; while ((line = bufReader.readLine()) != null) { list.add(line); } return list; } /** * Gets the contents of a classpath resource as a byte array. * *

* It is expected the given {@code name} to be absolute. The * behavior is not well-defined otherwise. *

* * @param name name of the desired resource * @return the requested byte array * @throws IOException if an I/O error occurs. * * @since 2.6 */ public static byte[] resourceToByteArray(final String name) throws IOException { return resourceToByteArray(name, null); } /** * Gets the contents of a classpath resource as a byte array. * *

* It is expected the given {@code name} to be absolute. The * behavior is not well-defined otherwise. *

* * @param name name of the desired resource * @param classLoader the class loader that the resolution of the resource is delegated to * @return the requested byte array * @throws IOException if an I/O error occurs. * * @since 2.6 */ public static byte[] resourceToByteArray(final String name, final ClassLoader classLoader) throws IOException { return toByteArray(resourceToURL(name, classLoader)); } /** * Gets the contents of a classpath resource as a String using the * specified character encoding. * *

* It is expected the given {@code name} to be absolute. The * behavior is not well-defined otherwise. *

* * @param name name of the desired resource * @param charset the charset to use, null means platform default * @return the requested String * @throws IOException if an I/O error occurs. * * @since 2.6 */ public static String resourceToString(final String name, final Charset charset) throws IOException { return resourceToString(name, charset, null); } /** * Gets the contents of a classpath resource as a String using the * specified character encoding. * *

* It is expected the given {@code name} to be absolute. The * behavior is not well-defined otherwise. *

* * @param name name of the desired resource * @param charset the charset to use, null means platform default * @param classLoader the class loader that the resolution of the resource is delegated to * @return the requested String * @throws IOException if an I/O error occurs. * * @since 2.6 */ public static String resourceToString(final String name, final Charset charset, final ClassLoader classLoader) throws IOException { return toString(resourceToURL(name, classLoader), charset); } /** * Gets a URL pointing to the given classpath resource. * *

* It is expected the given {@code name} to be absolute. The * behavior is not well-defined otherwise. *

* * @param name name of the desired resource * @return the requested URL * @throws IOException if an I/O error occurs. * * @since 2.6 */ public static URL resourceToURL(final String name) throws IOException { return resourceToURL(name, null); } /** * Gets a URL pointing to the given classpath resource. * *

* It is expected the given {@code name} to be absolute. The * behavior is not well-defined otherwise. *

* * @param name name of the desired resource * @param classLoader the class loader that the resolution of the resource is delegated to * @return the requested URL * @throws IOException if an I/O error occurs. * * @since 2.6 */ public static URL resourceToURL(final String name, final ClassLoader classLoader) throws IOException { // What about the thread context class loader? // What about the system class loader? final URL resource = classLoader == null ? IOUtils.class.getResource(name) : classLoader.getResource(name); if (resource == null) { throw new IOException("Resource not found: " + name); } return resource; } /** * Skips bytes from an input byte stream. * This implementation guarantees that it will read as many bytes * as possible before giving up; this may not always be the case for * skip() implementations in subclasses of {@link InputStream}. *

* Note that the implementation uses {@link InputStream#read(byte[], int, int)} rather * than delegating to {@link InputStream#skip(long)}. * This means that the method may be considerably less efficient than using the actual skip implementation, * this is done to guarantee that the correct number of bytes are skipped. *

* * @param input byte stream to skip * @param toSkip number of bytes to skip. * @return number of bytes actually skipped. * @throws IOException if there is a problem reading the file * @throws IllegalArgumentException if toSkip is negative * @see InputStream#skip(long) * @see IO-203 - Add skipFully() method for InputStreams * @since 2.0 */ public static long skip(final InputStream input, final long toSkip) throws IOException { if (toSkip < 0) { throw new IllegalArgumentException("Skip count must be non-negative, actual: " + toSkip); } /* * N.B. no need to synchronize access to SKIP_BYTE_BUFFER: - we don't care if the buffer is created multiple * times (the data is ignored) - we always use the same size buffer, so if it it is recreated it will still be * OK (if the buffer size were variable, we would need to synch. to ensure some other thread did not create a * smaller one) */ long remain = toSkip; while (remain > 0) { // See https://issues.apache.org/jira/browse/IO-203 for why we use read() rather than delegating to skip() final byte[] byteArray = getByteArray(); final long n = input.read(byteArray, 0, (int) Math.min(remain, byteArray.length)); if (n < 0) { // EOF break; } remain -= n; } return toSkip - remain; } /** * Skips bytes from a ReadableByteChannel. * This implementation guarantees that it will read as many bytes * as possible before giving up. * * @param input ReadableByteChannel to skip * @param toSkip number of bytes to skip. * @return number of bytes actually skipped. * @throws IOException if there is a problem reading the ReadableByteChannel * @throws IllegalArgumentException if toSkip is negative * @since 2.5 */ public static long skip(final ReadableByteChannel input, final long toSkip) throws IOException { if (toSkip < 0) { throw new IllegalArgumentException("Skip count must be non-negative, actual: " + toSkip); } final ByteBuffer skipByteBuffer = ByteBuffer.allocate((int) Math.min(toSkip, DEFAULT_BUFFER_SIZE)); long remain = toSkip; while (remain > 0) { skipByteBuffer.position(0); skipByteBuffer.limit((int) Math.min(remain, DEFAULT_BUFFER_SIZE)); final int n = input.read(skipByteBuffer); if (n == EOF) { break; } remain -= n; } return toSkip - remain; } /** * Skips characters from an input character stream. * This implementation guarantees that it will read as many characters * as possible before giving up; this may not always be the case for * skip() implementations in subclasses of {@link Reader}. *

* Note that the implementation uses {@link Reader#read(char[], int, int)} rather * than delegating to {@link Reader#skip(long)}. * This means that the method may be considerably less efficient than using the actual skip implementation, * this is done to guarantee that the correct number of characters are skipped. *

* * @param reader character stream to skip * @param toSkip number of characters to skip. * @return number of characters actually skipped. * @throws IOException if there is a problem reading the file * @throws IllegalArgumentException if toSkip is negative * @see Reader#skip(long) * @see IO-203 - Add skipFully() method for InputStreams * @since 2.0 */ public static long skip(final Reader reader, final long toSkip) throws IOException { if (toSkip < 0) { throw new IllegalArgumentException("Skip count must be non-negative, actual: " + toSkip); } long remain = toSkip; while (remain > 0) { // See https://issues.apache.org/jira/browse/IO-203 for why we use read() rather than delegating to skip() final char[] charArray = getCharArray(); final long n = reader.read(charArray, 0, (int) Math.min(remain, charArray.length)); if (n < 0) { // EOF break; } remain -= n; } return toSkip - remain; } /** * Skips the requested number of bytes or fail if there are not enough left. *

* This allows for the possibility that {@link InputStream#skip(long)} may * not skip as many bytes as requested (most likely because of reaching EOF). *

* Note that the implementation uses {@link #skip(InputStream, long)}. * This means that the method may be considerably less efficient than using the actual skip implementation, * this is done to guarantee that the correct number of characters are skipped. *

* * @param input stream to skip * @param toSkip the number of bytes to skip * @throws IOException if there is a problem reading the file * @throws IllegalArgumentException if toSkip is negative * @throws EOFException if the number of bytes skipped was incorrect * @see InputStream#skip(long) * @since 2.0 */ public static void skipFully(final InputStream input, final long toSkip) throws IOException { if (toSkip < 0) { throw new IllegalArgumentException("Bytes to skip must not be negative: " + toSkip); } final long skipped = skip(input, toSkip); if (skipped != toSkip) { throw new EOFException("Bytes to skip: " + toSkip + " actual: " + skipped); } } /** * Skips the requested number of bytes or fail if there are not enough left. * * @param input ReadableByteChannel to skip * @param toSkip the number of bytes to skip * @throws IOException if there is a problem reading the ReadableByteChannel * @throws IllegalArgumentException if toSkip is negative * @throws EOFException if the number of bytes skipped was incorrect * @since 2.5 */ public static void skipFully(final ReadableByteChannel input, final long toSkip) throws IOException { if (toSkip < 0) { throw new IllegalArgumentException("Bytes to skip must not be negative: " + toSkip); } final long skipped = skip(input, toSkip); if (skipped != toSkip) { throw new EOFException("Bytes to skip: " + toSkip + " actual: " + skipped); } } /** * Skips the requested number of characters or fail if there are not enough left. *

* This allows for the possibility that {@link Reader#skip(long)} may * not skip as many characters as requested (most likely because of reaching EOF). *

* Note that the implementation uses {@link #skip(Reader, long)}. * This means that the method may be considerably less efficient than using the actual skip implementation, * this is done to guarantee that the correct number of characters are skipped. *

* * @param reader stream to skip * @param toSkip the number of characters to skip * @throws IOException if there is a problem reading the file * @throws IllegalArgumentException if toSkip is negative * @throws EOFException if the number of characters skipped was incorrect * @see Reader#skip(long) * @since 2.0 */ public static void skipFully(final Reader reader, final long toSkip) throws IOException { final long skipped = skip(reader, toSkip); if (skipped != toSkip) { throw new EOFException("Chars to skip: " + toSkip + " actual: " + skipped); } } /** * Fetches entire contents of an {@code InputStream} and represent * same data as result InputStream. *

* This method is useful where, *

    *
  • Source InputStream is slow.
  • *
  • It has network resources associated, so we cannot keep it open for * long time.
  • *
  • It has network timeout associated.
  • *
* It can be used in favor of {@link #toByteArray(InputStream)}, since it * avoids unnecessary allocation and copy of byte[].
* This method buffers the input internally, so there is no need to use a * {@code BufferedInputStream}. * * @param input Stream to be fully buffered. * @return A fully buffered stream. * @throws IOException if an I/O error occurs. * @since 2.0 */ public static InputStream toBufferedInputStream(final InputStream input) throws IOException { return ByteArrayOutputStream.toBufferedInputStream(input); } /** * Fetches entire contents of an {@code InputStream} and represent * same data as result InputStream. *

* This method is useful where, *

    *
  • Source InputStream is slow.
  • *
  • It has network resources associated, so we cannot keep it open for * long time.
  • *
  • It has network timeout associated.
  • *
* It can be used in favor of {@link #toByteArray(InputStream)}, since it * avoids unnecessary allocation and copy of byte[].
* This method buffers the input internally, so there is no need to use a * {@code BufferedInputStream}. * * @param input Stream to be fully buffered. * @param size the initial buffer size * @return A fully buffered stream. * @throws IOException if an I/O error occurs. * @since 2.5 */ public static InputStream toBufferedInputStream(final InputStream input, final int size) throws IOException { return ByteArrayOutputStream.toBufferedInputStream(input, size); } /** * Returns the given reader if it is a {@link BufferedReader}, otherwise creates a BufferedReader from the given * reader. * * @param reader the reader to wrap or return (not null) * @return the given reader or a new {@link BufferedReader} for the given reader * @throws NullPointerException if the input parameter is null * @see #buffer(Reader) * @since 2.2 */ public static BufferedReader toBufferedReader(final Reader reader) { return reader instanceof BufferedReader ? (BufferedReader) reader : new BufferedReader(reader); } /** * Returns the given reader if it is a {@link BufferedReader}, otherwise creates a BufferedReader from the given * reader. * * @param reader the reader to wrap or return (not null) * @param size the buffer size, if a new BufferedReader is created. * @return the given reader or a new {@link BufferedReader} for the given reader * @throws NullPointerException if the input parameter is null * @see #buffer(Reader) * @since 2.5 */ public static BufferedReader toBufferedReader(final Reader reader, final int size) { return reader instanceof BufferedReader ? (BufferedReader) reader : new BufferedReader(reader, size); } /** * Gets the contents of an {@code InputStream} as a {@code byte[]}. *

* This method buffers the input internally, so there is no need to use a * {@code BufferedInputStream}. *

* * @param inputStream the {@code InputStream} to read. * @return the requested byte array. * @throws NullPointerException if the InputStream is {@code null}. * @throws IOException if an I/O error occurs or reading more than {@link Integer#MAX_VALUE} occurs. */ public static byte[] toByteArray(final InputStream inputStream) throws IOException { // We use a ThresholdingOutputStream to avoid reading AND writing more than Integer.MAX_VALUE. try (final UnsynchronizedByteArrayOutputStream ubaOutput = new UnsynchronizedByteArrayOutputStream(); final ThresholdingOutputStream thresholdOuput = new ThresholdingOutputStream(Integer.MAX_VALUE, os -> { throw new IllegalArgumentException( String.format("Cannot read more than %,d into a byte array", Integer.MAX_VALUE)); }, os -> ubaOutput)) { copy(inputStream, thresholdOuput); return ubaOutput.toByteArray(); } } /** * Gets the contents of an {@code InputStream} as a {@code byte[]}. Use this method instead of * {@code toByteArray(InputStream)} when {@code InputStream} size is known * * @param input the {@code InputStream} to read. * @param size the size of {@code InputStream}. * @return the requested byte array. * @throws IOException if an I/O error occurs or {@code InputStream} size differ from parameter size. * @throws IllegalArgumentException if size is less than zero. * @since 2.1 */ public static byte[] toByteArray(final InputStream input, final int size) throws IOException { if (size < 0) { throw new IllegalArgumentException("Size must be equal or greater than zero: " + size); } if (size == 0) { return EMPTY_BYTE_ARRAY; } final byte[] data = IOUtils.byteArray(size); int offset = 0; int read; while (offset < size && (read = input.read(data, offset, size - offset)) != EOF) { offset += read; } if (offset != size) { throw new IOException("Unexpected read size, current: " + offset + ", expected: " + size); } return data; } /** * Gets contents of an {@code InputStream} as a {@code byte[]}. * Use this method instead of {@code toByteArray(InputStream)} * when {@code InputStream} size is known. * NOTE: the method checks that the length can safely be cast to an int without truncation * before using {@link IOUtils#toByteArray(java.io.InputStream, int)} to read into the byte array. * (Arrays can have no more than Integer.MAX_VALUE entries anyway) * * @param input the {@code InputStream} to read from * @param size the size of {@code InputStream} * @return the requested byte array * @throws IOException if an I/O error occurs or {@code InputStream} size differ from parameter * size * @throws IllegalArgumentException if size is less than zero or size is greater than Integer.MAX_VALUE * @see IOUtils#toByteArray(java.io.InputStream, int) * @since 2.1 */ public static byte[] toByteArray(final InputStream input, final long size) throws IOException { if (size > Integer.MAX_VALUE) { throw new IllegalArgumentException("Size cannot be greater than Integer max value: " + size); } return toByteArray(input, (int) size); } /** * Gets the contents of a {@code Reader} as a {@code byte[]} * using the default character encoding of the platform. *

* This method buffers the input internally, so there is no need to use a * {@code BufferedReader}. * * @param reader the {@code Reader} to read from * @return the requested byte array * @throws NullPointerException if the input is null * @throws IOException if an I/O error occurs * @deprecated 2.5 use {@link #toByteArray(Reader, Charset)} instead */ @Deprecated public static byte[] toByteArray(final Reader reader) throws IOException { return toByteArray(reader, Charset.defaultCharset()); } /** * Gets the contents of a {@code Reader} as a {@code byte[]} * using the specified character encoding. *

* This method buffers the input internally, so there is no need to use a * {@code BufferedReader}. * * @param reader the {@code Reader} to read from * @param charset the charset to use, null means platform default * @return the requested byte array * @throws NullPointerException if the input is null * @throws IOException if an I/O error occurs * @since 2.3 */ public static byte[] toByteArray(final Reader reader, final Charset charset) throws IOException { try (final ByteArrayOutputStream output = new ByteArrayOutputStream()) { copy(reader, output, charset); return output.toByteArray(); } } /** * Gets the contents of a {@code Reader} as a {@code byte[]} * using the specified character encoding. *

* Character encoding names can be found at * IANA. *

* This method buffers the input internally, so there is no need to use a * {@code BufferedReader}. * * @param reader the {@code Reader} to read from * @param charsetName the name of the requested charset, null means platform default * @return the requested byte array * @throws NullPointerException if the input is null * @throws IOException if an I/O error occurs * @throws java.nio.charset.UnsupportedCharsetException thrown instead of {@link java.io * .UnsupportedEncodingException} in version 2.2 if the * encoding is not supported. * @since 1.1 */ public static byte[] toByteArray(final Reader reader, final String charsetName) throws IOException { return toByteArray(reader, Charsets.toCharset(charsetName)); } /** * Gets the contents of a {@code String} as a {@code byte[]} * using the default character encoding of the platform. *

* This is the same as {@link String#getBytes()}. * * @param input the {@code String} to convert * @return the requested byte array * @throws NullPointerException if the input is null * @deprecated 2.5 Use {@link String#getBytes()} instead */ @Deprecated public static byte[] toByteArray(final String input) { // make explicit the use of the default charset return input.getBytes(Charset.defaultCharset()); } /** * Gets the contents of a {@code URI} as a {@code byte[]}. * * @param uri the {@code URI} to read * @return the requested byte array * @throws NullPointerException if the uri is null * @throws IOException if an I/O exception occurs * @since 2.4 */ public static byte[] toByteArray(final URI uri) throws IOException { return IOUtils.toByteArray(uri.toURL()); } /** * Gets the contents of a {@code URL} as a {@code byte[]}. * * @param url the {@code URL} to read * @return the requested byte array * @throws NullPointerException if the input is null * @throws IOException if an I/O exception occurs * @since 2.4 */ public static byte[] toByteArray(final URL url) throws IOException { final URLConnection conn = url.openConnection(); try { return IOUtils.toByteArray(conn); } finally { close(conn); } } /** * Gets the contents of a {@code URLConnection} as a {@code byte[]}. * * @param urlConn the {@code URLConnection} to read. * @return the requested byte array. * @throws NullPointerException if the urlConn is null. * @throws IOException if an I/O exception occurs. * @since 2.4 */ public static byte[] toByteArray(final URLConnection urlConn) throws IOException { try (InputStream inputStream = urlConn.getInputStream()) { return IOUtils.toByteArray(inputStream); } } /** * Gets the contents of an {@code InputStream} as a character array * using the default character encoding of the platform. *

* This method buffers the input internally, so there is no need to use a * {@code BufferedInputStream}. * * @param inputStream the {@code InputStream} to read from * @return the requested character array * @throws NullPointerException if the input is null * @throws IOException if an I/O error occurs * @since 1.1 * @deprecated 2.5 use {@link #toCharArray(InputStream, Charset)} instead */ @Deprecated public static char[] toCharArray(final InputStream inputStream) throws IOException { return toCharArray(inputStream, Charset.defaultCharset()); } /** * Gets the contents of an {@code InputStream} as a character array * using the specified character encoding. *

* This method buffers the input internally, so there is no need to use a * {@code BufferedInputStream}. * * @param inputStream the {@code InputStream} to read from * @param charset the charset to use, null means platform default * @return the requested character array * @throws NullPointerException if the input is null * @throws IOException if an I/O error occurs * @since 2.3 */ public static char[] toCharArray(final InputStream inputStream, final Charset charset) throws IOException { final CharArrayWriter writer = new CharArrayWriter(); copy(inputStream, writer, charset); return writer.toCharArray(); } /** * Gets the contents of an {@code InputStream} as a character array * using the specified character encoding. *

* Character encoding names can be found at * IANA. *

* This method buffers the input internally, so there is no need to use a * {@code BufferedInputStream}. * * @param inputStream the {@code InputStream} to read from * @param charsetName the name of the requested charset, null means platform default * @return the requested character array * @throws NullPointerException if the input is null * @throws IOException if an I/O error occurs * @throws java.nio.charset.UnsupportedCharsetException thrown instead of {@link java.io * .UnsupportedEncodingException} in version 2.2 if the * encoding is not supported. * @since 1.1 */ public static char[] toCharArray(final InputStream inputStream, final String charsetName) throws IOException { return toCharArray(inputStream, Charsets.toCharset(charsetName)); } /** * Gets the contents of a {@code Reader} as a character array. *

* This method buffers the input internally, so there is no need to use a * {@code BufferedReader}. * * @param reader the {@code Reader} to read from * @return the requested character array * @throws NullPointerException if the input is null * @throws IOException if an I/O error occurs * @since 1.1 */ public static char[] toCharArray(final Reader reader) throws IOException { final CharArrayWriter sw = new CharArrayWriter(); copy(reader, sw); return sw.toCharArray(); } /** * Converts the specified CharSequence to an input stream, encoded as bytes * using the default character encoding of the platform. * * @param input the CharSequence to convert * @return an input stream * @since 2.0 * @deprecated 2.5 use {@link #toInputStream(CharSequence, Charset)} instead */ @Deprecated public static InputStream toInputStream(final CharSequence input) { return toInputStream(input, Charset.defaultCharset()); } /** * Converts the specified CharSequence to an input stream, encoded as bytes * using the specified character encoding. * * @param input the CharSequence to convert * @param charset the charset to use, null means platform default * @return an input stream * @since 2.3 */ public static InputStream toInputStream(final CharSequence input, final Charset charset) { return toInputStream(input.toString(), charset); } /** * Converts the specified CharSequence to an input stream, encoded as bytes * using the specified character encoding. *

* Character encoding names can be found at * IANA. * * @param input the CharSequence to convert * @param charsetName the name of the requested charset, null means platform default * @return an input stream * @throws java.nio.charset.UnsupportedCharsetException thrown instead of {@link java.io * .UnsupportedEncodingException} in version 2.2 if the * encoding is not supported. * @since 2.0 */ public static InputStream toInputStream(final CharSequence input, final String charsetName) { return toInputStream(input, Charsets.toCharset(charsetName)); } /** * Converts the specified string to an input stream, encoded as bytes * using the default character encoding of the platform. * * @param input the string to convert * @return an input stream * @since 1.1 * @deprecated 2.5 use {@link #toInputStream(String, Charset)} instead */ @Deprecated public static InputStream toInputStream(final String input) { return toInputStream(input, Charset.defaultCharset()); } /** * Converts the specified string to an input stream, encoded as bytes * using the specified character encoding. * * @param input the string to convert * @param charset the charset to use, null means platform default * @return an input stream * @since 2.3 */ public static InputStream toInputStream(final String input, final Charset charset) { return new ByteArrayInputStream(input.getBytes(Charsets.toCharset(charset))); } /** * Converts the specified string to an input stream, encoded as bytes * using the specified character encoding. *

* Character encoding names can be found at * IANA. * * @param input the string to convert * @param charsetName the name of the requested charset, null means platform default * @return an input stream * @throws java.nio.charset.UnsupportedCharsetException thrown instead of {@link java.io * .UnsupportedEncodingException} in version 2.2 if the * encoding is not supported. * @since 1.1 */ public static InputStream toInputStream(final String input, final String charsetName) { final byte[] bytes = input.getBytes(Charsets.toCharset(charsetName)); return new ByteArrayInputStream(bytes); } /** * Gets the contents of a {@code byte[]} as a String * using the default character encoding of the platform. * * @param input the byte array to read from * @return the requested String * @throws NullPointerException if the input is null * @deprecated 2.5 Use {@link String#String(byte[])} instead */ @Deprecated public static String toString(final byte[] input) { // make explicit the use of the default charset return new String(input, Charset.defaultCharset()); } /** * Gets the contents of a {@code byte[]} as a String * using the specified character encoding. *

* Character encoding names can be found at * IANA. * * @param input the byte array to read from * @param charsetName the name of the requested charset, null means platform default * @return the requested String * @throws NullPointerException if the input is null */ public static String toString(final byte[] input, final String charsetName) { return new String(input, Charsets.toCharset(charsetName)); } /** * Gets the contents of an {@code InputStream} as a String * using the default character encoding of the platform. *

* This method buffers the input internally, so there is no need to use a * {@code BufferedInputStream}. * * @param input the {@code InputStream} to read from * @return the requested String * @throws NullPointerException if the input is null * @throws IOException if an I/O error occurs * @deprecated 2.5 use {@link #toString(InputStream, Charset)} instead */ @Deprecated public static String toString(final InputStream input) throws IOException { return toString(input, Charset.defaultCharset()); } /** * Gets the contents of an {@code InputStream} as a String * using the specified character encoding. *

* This method buffers the input internally, so there is no need to use a * {@code BufferedInputStream}. *

* * @param input the {@code InputStream} to read from * @param charset the charset to use, null means platform default * @return the requested String * @throws NullPointerException if the input is null * @throws IOException if an I/O error occurs * @since 2.3 */ public static String toString(final InputStream input, final Charset charset) throws IOException { try (final StringBuilderWriter sw = new StringBuilderWriter()) { copy(input, sw, charset); return sw.toString(); } } /** * Gets the contents of an {@code InputStream} as a String * using the specified character encoding. *

* Character encoding names can be found at * IANA. *

* This method buffers the input internally, so there is no need to use a * {@code BufferedInputStream}. * * @param input the {@code InputStream} to read from * @param charsetName the name of the requested charset, null means platform default * @return the requested String * @throws NullPointerException if the input is null * @throws IOException if an I/O error occurs * @throws java.nio.charset.UnsupportedCharsetException thrown instead of {@link java.io * .UnsupportedEncodingException} in version 2.2 if the * encoding is not supported. */ public static String toString(final InputStream input, final String charsetName) throws IOException { return toString(input, Charsets.toCharset(charsetName)); } /** * Gets the contents of a {@code Reader} as a String. *

* This method buffers the input internally, so there is no need to use a * {@code BufferedReader}. * * @param reader the {@code Reader} to read from * @return the requested String * @throws NullPointerException if the input is null * @throws IOException if an I/O error occurs */ public static String toString(final Reader reader) throws IOException { try (final StringBuilderWriter sw = new StringBuilderWriter()) { copy(reader, sw); return sw.toString(); } } /** * Gets the contents at the given URI. * * @param uri The URI source. * @return The contents of the URL as a String. * @throws IOException if an I/O exception occurs. * @since 2.1 * @deprecated 2.5 use {@link #toString(URI, Charset)} instead */ @Deprecated public static String toString(final URI uri) throws IOException { return toString(uri, Charset.defaultCharset()); } /** * Gets the contents at the given URI. * * @param uri The URI source. * @param encoding The encoding name for the URL contents. * @return The contents of the URL as a String. * @throws IOException if an I/O exception occurs. * @since 2.3. */ public static String toString(final URI uri, final Charset encoding) throws IOException { return toString(uri.toURL(), Charsets.toCharset(encoding)); } /** * Gets the contents at the given URI. * * @param uri The URI source. * @param charsetName The encoding name for the URL contents. * @return The contents of the URL as a String. * @throws IOException if an I/O exception occurs. * @throws java.nio.charset.UnsupportedCharsetException thrown instead of {@link java.io * .UnsupportedEncodingException} in version 2.2 if the * encoding is not supported. * @since 2.1 */ public static String toString(final URI uri, final String charsetName) throws IOException { return toString(uri, Charsets.toCharset(charsetName)); } /** * Gets the contents at the given URL. * * @param url The URL source. * @return The contents of the URL as a String. * @throws IOException if an I/O exception occurs. * @since 2.1 * @deprecated 2.5 use {@link #toString(URL, Charset)} instead */ @Deprecated public static String toString(final URL url) throws IOException { return toString(url, Charset.defaultCharset()); } /** * Gets the contents at the given URL. * * @param url The URL source. * @param encoding The encoding name for the URL contents. * @return The contents of the URL as a String. * @throws IOException if an I/O exception occurs. * @since 2.3 */ public static String toString(final URL url, final Charset encoding) throws IOException { try (InputStream inputStream = url.openStream()) { return toString(inputStream, encoding); } } /** * Gets the contents at the given URL. * * @param url The URL source. * @param charsetName The encoding name for the URL contents. * @return The contents of the URL as a String. * @throws IOException if an I/O exception occurs. * @throws java.nio.charset.UnsupportedCharsetException thrown instead of {@link java.io * .UnsupportedEncodingException} in version 2.2 if the * encoding is not supported. * @since 2.1 */ public static String toString(final URL url, final String charsetName) throws IOException { return toString(url, Charsets.toCharset(charsetName)); } /** * Writes bytes from a {@code byte[]} to an {@code OutputStream}. * * @param data the byte array to write, do not modify during output, * null ignored * @param output the {@code OutputStream} to write to * @throws NullPointerException if output is null * @throws IOException if an I/O error occurs * @since 1.1 */ public static void write(final byte[] data, final OutputStream output) throws IOException { if (data != null) { output.write(data); } } /** * Writes bytes from a {@code byte[]} to chars on a {@code Writer} * using the default character encoding of the platform. *

* This method uses {@link String#String(byte[])}. * * @param data the byte array to write, do not modify during output, * null ignored * @param writer the {@code Writer} to write to * @throws NullPointerException if output is null * @throws IOException if an I/O error occurs * @since 1.1 * @deprecated 2.5 use {@link #write(byte[], Writer, Charset)} instead */ @Deprecated public static void write(final byte[] data, final Writer writer) throws IOException { write(data, writer, Charset.defaultCharset()); } /** * Writes bytes from a {@code byte[]} to chars on a {@code Writer} * using the specified character encoding. *

* This method uses {@link String#String(byte[], String)}. * * @param data the byte array to write, do not modify during output, * null ignored * @param writer the {@code Writer} to write to * @param charset the charset to use, null means platform default * @throws NullPointerException if output is null * @throws IOException if an I/O error occurs * @since 2.3 */ public static void write(final byte[] data, final Writer writer, final Charset charset) throws IOException { if (data != null) { writer.write(new String(data, Charsets.toCharset(charset))); } } /** * Writes bytes from a {@code byte[]} to chars on a {@code Writer} * using the specified character encoding. *

* Character encoding names can be found at * IANA. *

* This method uses {@link String#String(byte[], String)}. * * @param data the byte array to write, do not modify during output, * null ignored * @param writer the {@code Writer} to write to * @param charsetName the name of the requested charset, null means platform default * @throws NullPointerException if output is null * @throws IOException if an I/O error occurs * @throws java.nio.charset.UnsupportedCharsetException thrown instead of {@link java.io * .UnsupportedEncodingException} in version 2.2 if the * encoding is not supported. * @since 1.1 */ public static void write(final byte[] data, final Writer writer, final String charsetName) throws IOException { write(data, writer, Charsets.toCharset(charsetName)); } /** * Writes chars from a {@code char[]} to bytes on an * {@code OutputStream}. *

* This method uses {@link String#String(char[])} and * {@link String#getBytes()}. * * @param data the char array to write, do not modify during output, * null ignored * @param output the {@code OutputStream} to write to * @throws NullPointerException if output is null * @throws IOException if an I/O error occurs * @since 1.1 * @deprecated 2.5 use {@link #write(char[], OutputStream, Charset)} instead */ @Deprecated public static void write(final char[] data, final OutputStream output) throws IOException { write(data, output, Charset.defaultCharset()); } /** * Writes chars from a {@code char[]} to bytes on an * {@code OutputStream} using the specified character encoding. *

* This method uses {@link String#String(char[])} and * {@link String#getBytes(String)}. * * @param data the char array to write, do not modify during output, * null ignored * @param output the {@code OutputStream} to write to * @param charset the charset to use, null means platform default * @throws NullPointerException if output is null * @throws IOException if an I/O error occurs * @since 2.3 */ public static void write(final char[] data, final OutputStream output, final Charset charset) throws IOException { if (data != null) { output.write(new String(data).getBytes(Charsets.toCharset(charset))); } } /** * Writes chars from a {@code char[]} to bytes on an * {@code OutputStream} using the specified character encoding. *

* Character encoding names can be found at * IANA. *

* This method uses {@link String#String(char[])} and * {@link String#getBytes(String)}. * * @param data the char array to write, do not modify during output, * null ignored * @param output the {@code OutputStream} to write to * @param charsetName the name of the requested charset, null means platform default * @throws NullPointerException if output is null * @throws IOException if an I/O error occurs * @throws java.nio.charset.UnsupportedCharsetException thrown instead of {@link java.io * .UnsupportedEncodingException} in version 2.2 if the encoding is not supported. * @since 1.1 */ public static void write(final char[] data, final OutputStream output, final String charsetName) throws IOException { write(data, output, Charsets.toCharset(charsetName)); } /** * Writes chars from a {@code char[]} to a {@code Writer} * * @param data the char array to write, do not modify during output, * null ignored * @param writer the {@code Writer} to write to * @throws NullPointerException if output is null * @throws IOException if an I/O error occurs * @since 1.1 */ public static void write(final char[] data, final Writer writer) throws IOException { if (data != null) { writer.write(data); } } /** * Writes chars from a {@code CharSequence} to bytes on an * {@code OutputStream} using the default character encoding of the * platform. *

* This method uses {@link String#getBytes()}. * * @param data the {@code CharSequence} to write, null ignored * @param output the {@code OutputStream} to write to * @throws NullPointerException if output is null * @throws IOException if an I/O error occurs * @since 2.0 * @deprecated 2.5 use {@link #write(CharSequence, OutputStream, Charset)} instead */ @Deprecated public static void write(final CharSequence data, final OutputStream output) throws IOException { write(data, output, Charset.defaultCharset()); } /** * Writes chars from a {@code CharSequence} to bytes on an * {@code OutputStream} using the specified character encoding. *

* This method uses {@link String#getBytes(String)}. * * @param data the {@code CharSequence} to write, null ignored * @param output the {@code OutputStream} to write to * @param charset the charset to use, null means platform default * @throws NullPointerException if output is null * @throws IOException if an I/O error occurs * @since 2.3 */ public static void write(final CharSequence data, final OutputStream output, final Charset charset) throws IOException { if (data != null) { write(data.toString(), output, charset); } } /** * Writes chars from a {@code CharSequence} to bytes on an * {@code OutputStream} using the specified character encoding. *

* Character encoding names can be found at * IANA. *

* This method uses {@link String#getBytes(String)}. * * @param data the {@code CharSequence} to write, null ignored * @param output the {@code OutputStream} to write to * @param charsetName the name of the requested charset, null means platform default * @throws NullPointerException if output is null * @throws IOException if an I/O error occurs * @throws java.nio.charset.UnsupportedCharsetException thrown instead of {@link java.io * .UnsupportedEncodingException} in version 2.2 if the encoding is not supported. * @since 2.0 */ public static void write(final CharSequence data, final OutputStream output, final String charsetName) throws IOException { write(data, output, Charsets.toCharset(charsetName)); } /** * Writes chars from a {@code CharSequence} to a {@code Writer}. * * @param data the {@code CharSequence} to write, null ignored * @param writer the {@code Writer} to write to * @throws NullPointerException if output is null * @throws IOException if an I/O error occurs * @since 2.0 */ public static void write(final CharSequence data, final Writer writer) throws IOException { if (data != null) { write(data.toString(), writer); } } /** * Writes chars from a {@code String} to bytes on an * {@code OutputStream} using the default character encoding of the * platform. *

* This method uses {@link String#getBytes()}. * * @param data the {@code String} to write, null ignored * @param output the {@code OutputStream} to write to * @throws NullPointerException if output is null * @throws IOException if an I/O error occurs * @since 1.1 * @deprecated 2.5 use {@link #write(String, OutputStream, Charset)} instead */ @Deprecated public static void write(final String data, final OutputStream output) throws IOException { write(data, output, Charset.defaultCharset()); } /** * Writes chars from a {@code String} to bytes on an * {@code OutputStream} using the specified character encoding. *

* This method uses {@link String#getBytes(String)}. * * @param data the {@code String} to write, null ignored * @param output the {@code OutputStream} to write to * @param charset the charset to use, null means platform default * @throws NullPointerException if output is null * @throws IOException if an I/O error occurs * @since 2.3 */ public static void write(final String data, final OutputStream output, final Charset charset) throws IOException { if (data != null) { output.write(data.getBytes(Charsets.toCharset(charset))); } } /** * Writes chars from a {@code String} to bytes on an * {@code OutputStream} using the specified character encoding. *

* Character encoding names can be found at * IANA. *

* This method uses {@link String#getBytes(String)}. * * @param data the {@code String} to write, null ignored * @param output the {@code OutputStream} to write to * @param charsetName the name of the requested charset, null means platform default * @throws NullPointerException if output is null * @throws IOException if an I/O error occurs * @throws java.nio.charset.UnsupportedCharsetException thrown instead of {@link java.io * .UnsupportedEncodingException} in version 2.2 if the encoding is not supported. * @since 1.1 */ public static void write(final String data, final OutputStream output, final String charsetName) throws IOException { write(data, output, Charsets.toCharset(charsetName)); } /** * Writes chars from a {@code String} to a {@code Writer}. * * @param data the {@code String} to write, null ignored * @param writer the {@code Writer} to write to * @throws NullPointerException if output is null * @throws IOException if an I/O error occurs * @since 1.1 */ public static void write(final String data, final Writer writer) throws IOException { if (data != null) { writer.write(data); } } /** * Writes chars from a {@code StringBuffer} to bytes on an * {@code OutputStream} using the default character encoding of the * platform. *

* This method uses {@link String#getBytes()}. * * @param data the {@code StringBuffer} to write, null ignored * @param output the {@code OutputStream} to write to * @throws NullPointerException if output is null * @throws IOException if an I/O error occurs * @since 1.1 * @deprecated replaced by write(CharSequence, OutputStream) */ @Deprecated public static void write(final StringBuffer data, final OutputStream output) //NOSONAR throws IOException { write(data, output, (String) null); } /** * Writes chars from a {@code StringBuffer} to bytes on an * {@code OutputStream} using the specified character encoding. *

* Character encoding names can be found at * IANA. *

* This method uses {@link String#getBytes(String)}. * * @param data the {@code StringBuffer} to write, null ignored * @param output the {@code OutputStream} to write to * @param charsetName the name of the requested charset, null means platform default * @throws NullPointerException if output is null * @throws IOException if an I/O error occurs * @throws java.nio.charset.UnsupportedCharsetException thrown instead of {@link java.io * .UnsupportedEncodingException} in version 2.2 if the encoding is not supported. * @since 1.1 * @deprecated replaced by write(CharSequence, OutputStream, String) */ @Deprecated public static void write(final StringBuffer data, final OutputStream output, final String charsetName) //NOSONAR throws IOException { if (data != null) { output.write(data.toString().getBytes(Charsets.toCharset(charsetName))); } } /** * Writes chars from a {@code StringBuffer} to a {@code Writer}. * * @param data the {@code StringBuffer} to write, null ignored * @param writer the {@code Writer} to write to * @throws NullPointerException if output is null * @throws IOException if an I/O error occurs * @since 1.1 * @deprecated replaced by write(CharSequence, Writer) */ @Deprecated public static void write(final StringBuffer data, final Writer writer) //NOSONAR throws IOException { if (data != null) { writer.write(data.toString()); } } /** * Writes bytes from a {@code byte[]} to an {@code OutputStream} using chunked writes. * This is intended for writing very large byte arrays which might otherwise cause excessive * memory usage if the native code has to allocate a copy. * * @param data the byte array to write, do not modify during output, * null ignored * @param output the {@code OutputStream} to write to * @throws NullPointerException if output is null * @throws IOException if an I/O error occurs * @since 2.5 */ public static void writeChunked(final byte[] data, final OutputStream output) throws IOException { if (data != null) { int bytes = data.length; int offset = 0; while (bytes > 0) { final int chunk = Math.min(bytes, DEFAULT_BUFFER_SIZE); output.write(data, offset, chunk); bytes -= chunk; offset += chunk; } } } /** * Writes chars from a {@code char[]} to a {@code Writer} using chunked writes. * This is intended for writing very large byte arrays which might otherwise cause excessive * memory usage if the native code has to allocate a copy. * * @param data the char array to write, do not modify during output, * null ignored * @param writer the {@code Writer} to write to * @throws NullPointerException if output is null * @throws IOException if an I/O error occurs * @since 2.5 */ public static void writeChunked(final char[] data, final Writer writer) throws IOException { if (data != null) { int bytes = data.length; int offset = 0; while (bytes > 0) { final int chunk = Math.min(bytes, DEFAULT_BUFFER_SIZE); writer.write(data, offset, chunk); bytes -= chunk; offset += chunk; } } } /** * Writes the {@code toString()} value of each item in a collection to * an {@code OutputStream} line by line, using the default character * encoding of the platform and the specified line ending. * * @param lines the lines to write, null entries produce blank lines * @param lineEnding the line separator to use, null is system default * @param output the {@code OutputStream} to write to, not null, not closed * @throws NullPointerException if the output is null * @throws IOException if an I/O error occurs * @since 1.1 * @deprecated 2.5 use {@link #writeLines(Collection, String, OutputStream, Charset)} instead */ @Deprecated public static void writeLines(final Collection lines, final String lineEnding, final OutputStream output) throws IOException { writeLines(lines, lineEnding, output, Charset.defaultCharset()); } /** * Writes the {@code toString()} value of each item in a collection to * an {@code OutputStream} line by line, using the specified character * encoding and the specified line ending. * * @param lines the lines to write, null entries produce blank lines * @param lineEnding the line separator to use, null is system default * @param output the {@code OutputStream} to write to, not null, not closed * @param charset the charset to use, null means platform default * @throws NullPointerException if the output is null * @throws IOException if an I/O error occurs * @since 2.3 */ public static void writeLines(final Collection lines, String lineEnding, final OutputStream output, final Charset charset) throws IOException { if (lines == null) { return; } if (lineEnding == null) { lineEnding = System.lineSeparator(); } final Charset cs = Charsets.toCharset(charset); for (final Object line : lines) { if (line != null) { output.write(line.toString().getBytes(cs)); } output.write(lineEnding.getBytes(cs)); } } /** * Writes the {@code toString()} value of each item in a collection to * an {@code OutputStream} line by line, using the specified character * encoding and the specified line ending. *

* Character encoding names can be found at * IANA. * * @param lines the lines to write, null entries produce blank lines * @param lineEnding the line separator to use, null is system default * @param output the {@code OutputStream} to write to, not null, not closed * @param charsetName the name of the requested charset, null means platform default * @throws NullPointerException if the output is null * @throws IOException if an I/O error occurs * @throws java.nio.charset.UnsupportedCharsetException thrown instead of {@link java.io * .UnsupportedEncodingException} in version 2.2 if the * encoding is not supported. * @since 1.1 */ public static void writeLines(final Collection lines, final String lineEnding, final OutputStream output, final String charsetName) throws IOException { writeLines(lines, lineEnding, output, Charsets.toCharset(charsetName)); } /** * Writes the {@code toString()} value of each item in a collection to * a {@code Writer} line by line, using the specified line ending. * * @param lines the lines to write, null entries produce blank lines * @param lineEnding the line separator to use, null is system default * @param writer the {@code Writer} to write to, not null, not closed * @throws NullPointerException if the input is null * @throws IOException if an I/O error occurs * @since 1.1 */ public static void writeLines(final Collection lines, String lineEnding, final Writer writer) throws IOException { if (lines == null) { return; } if (lineEnding == null) { lineEnding = System.lineSeparator(); } for (final Object line : lines) { if (line != null) { writer.write(line.toString()); } writer.write(lineEnding); } } /** * Returns the given Appendable if it is already a {@link Writer}, otherwise creates a Writer wrapper around the * given Appendable. * * @param appendable the Appendable to wrap or return (not null) * @return the given Appendable or a Writer wrapper around the given Appendable * @throws NullPointerException if the input parameter is null * @since 2.7 */ public static Writer writer(final Appendable appendable) { Objects.requireNonNull(appendable, "appendable"); if (appendable instanceof Writer) { return (Writer) appendable; } if (appendable instanceof StringBuilder) { return new StringBuilderWriter((StringBuilder) appendable); } return new AppendableWriter<>(appendable); } /** * Instances should NOT be constructed in standard programming. */ public IOUtils() { //NOSONAR } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/LineIterator.java0100644 0000000 0000000 00000013570 13612062727 027005 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import java.io.BufferedReader; import java.io.Closeable; import java.io.IOException; import java.io.Reader; import java.util.Iterator; import java.util.NoSuchElementException; /** * An Iterator over the lines in a {@code Reader}. *

* {@code LineIterator} holds a reference to an open {@code Reader}. * When you have finished with the iterator you should close the reader * to free internal resources. This can be done by closing the reader directly, * or by calling the {@link #close()} or {@link #closeQuietly(LineIterator)} * method on the iterator. *

* The recommended usage pattern is: *

 * LineIterator it = FileUtils.lineIterator(file, "UTF-8");
 * try {
 *   while (it.hasNext()) {
 *     String line = it.nextLine();
 *     // do something with line
 *   }
 * } finally {
 *   it.close();
 * }
 * 
* * @since 1.2 */ public class LineIterator implements Iterator, Closeable { // N.B. This class deliberately does not implement Iterable, see https://issues.apache.org/jira/browse/IO-181 /** The reader that is being read. */ private final BufferedReader bufferedReader; /** The current line. */ private String cachedLine; /** A flag indicating if the iterator has been fully read. */ private boolean finished; /** * Constructs an iterator of the lines for a {@code Reader}. * * @param reader the {@code Reader} to read from, not null * @throws IllegalArgumentException if the reader is null */ public LineIterator(final Reader reader) throws IllegalArgumentException { if (reader == null) { throw new IllegalArgumentException("Reader must not be null"); } if (reader instanceof BufferedReader) { bufferedReader = (BufferedReader) reader; } else { bufferedReader = new BufferedReader(reader); } } /** * Indicates whether the {@code Reader} has more lines. * If there is an {@code IOException} then {@link #close()} will * be called on this instance. * * @return {@code true} if the Reader has more lines * @throws IllegalStateException if an IO exception occurs */ @Override public boolean hasNext() { if (cachedLine != null) { return true; } if (finished) { return false; } try { while (true) { final String line = bufferedReader.readLine(); if (line == null) { finished = true; return false; } if (isValidLine(line)) { cachedLine = line; return true; } } } catch(final IOException ioe) { IOUtils.closeQuietly(this, ioe::addSuppressed); throw new IllegalStateException(ioe); } } /** * Overridable method to validate each line that is returned. * This implementation always returns true. * @param line the line that is to be validated * @return true if valid, false to remove from the iterator */ protected boolean isValidLine(final String line) { return true; } /** * Returns the next line in the wrapped {@code Reader}. * * @return the next line from the input * @throws NoSuchElementException if there is no line to return */ @Override public String next() { return nextLine(); } /** * Returns the next line in the wrapped {@code Reader}. * * @return the next line from the input * @throws NoSuchElementException if there is no line to return */ public String nextLine() { if (!hasNext()) { throw new NoSuchElementException("No more lines"); } final String currentLine = cachedLine; cachedLine = null; return currentLine; } /** * Closes the underlying {@code Reader}. * This method is useful if you only want to process the first few * lines of a larger file. If you do not close the iterator * then the {@code Reader} remains open. * This method can safely be called multiple times. * * @throws IOException if closing the underlying {@code Reader} fails. */ @Override public void close() throws IOException { finished = true; cachedLine = null; IOUtils.close(bufferedReader); } /** * Unsupported. * * @throws UnsupportedOperationException always */ @Override public void remove() { throw new UnsupportedOperationException("remove not supported"); } /** * Closes a {@code LineIterator} quietly. * * @param iterator The iterator to close, or {@code null}. * @deprecated As of 2.6 deprecated without replacement. Please use the try-with-resources statement or handle * suppressed exceptions manually. * @see Throwable#addSuppressed(java.lang.Throwable) */ @Deprecated public static void closeQuietly(final LineIterator iterator) { IOUtils.closeQuietly(iterator); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/StandardLineSeparator.java0100644 0000000 0000000 00000004261 13612062727 030632 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import java.nio.charset.Charset; import java.util.Objects; /** * Enumerates standard line separators: {@link #CR}, {@link #CRLF}, {@link #LF}. * * @since 2.9.0 */ public enum StandardLineSeparator { /** * Carriage return. This is the line ending used on Macos 9 and earlier. */ CR("\r"), /** * Carriage return followed by line feed. This is the line ending used on Windows. */ CRLF("\r\n"), /** * Line feed. This is the line ending used on Linux and Macos X and later. */ LF("\n"); private final String lineSeparator; /** * Constructs a new instance for a non-null line separator. * * @param lineSeparator a non-null line separator. */ StandardLineSeparator(final String lineSeparator) { this.lineSeparator = Objects.requireNonNull(lineSeparator, "lineSeparator"); } /** * Gets the bytes for this instance encoded using the given Charset. * * @param charset the encoding Charset. * @return the bytes for this instance encoded using the given Charset. */ public byte[] getBytes(final Charset charset) { return lineSeparator.getBytes(charset); } /** * Gets the String value of this instance. * * @return the String value of this instance. */ public String getString() { return lineSeparator; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/StreamIterator.java0100644 0000000 0000000 00000005042 13612062727 027344 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import java.io.Closeable; import java.util.Iterator; import java.util.Objects; import java.util.stream.Stream; /** * Wraps and presents a stream as a closable iterator resource that automatically closes itself when reaching the end * of stream. * * @param The stream and iterator type. * @since 2.9.0 */ class StreamIterator implements Iterator, Closeable { /** * Wraps and presents a stream as a closable resource that automatically closes itself when reaching the end of * stream. *

Warning

*

* In order to close the stream, the call site MUST either close the stream it allocated OR call the iterator until * the end. *

* * @param The stream and iterator type. * @param stream The stream iterate. * @return A new iterator. */ @SuppressWarnings("resource") // Caller MUST close or iterate to the end. public static Iterator iterator(final Stream stream) { return new StreamIterator<>(stream).iterator; } private StreamIterator(final Stream stream) { this.stream = Objects.requireNonNull(stream, "stream"); this.iterator = stream.iterator(); } private final Iterator iterator; private final Stream stream; @Override public boolean hasNext() { final boolean hasNext = iterator.hasNext(); if (!hasNext) { close(); } return hasNext; } @Override public E next() { final E next = iterator.next(); if (next == null) { close(); } return next; } /** * Closes the underlying stream. */ @Override public void close() { stream.close(); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/TaggedIOException.java0100644 0000000 0000000 00000010763 13612062727 027707 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import java.io.IOException; import java.io.Serializable; /** * An {@link IOException} decorator that adds a serializable tag to the * wrapped exception. Both the tag and the original exception can be used * to determine further processing when this exception is caught. * * @since 2.0 */ @SuppressWarnings("deprecation") // needs to extend deprecated IOExceptionWithCause to preserve binary compatibility public class TaggedIOException extends IOExceptionWithCause { /** * Generated serial version UID. */ private static final long serialVersionUID = -6994123481142850163L; /** * Checks whether the given throwable is tagged with the given tag. *

* This check can only succeed if the throwable is a * {@link TaggedIOException} and the tag is {@link Serializable}, but * the argument types are intentionally more generic to make it easier * to use this method without type casts. *

* A typical use for this method is in a {@code catch} block to * determine how a caught exception should be handled: *

     * Serializable tag = ...;
     * try {
     *     ...;
     * } catch (Throwable t) {
     *     if (TaggedIOException.isTaggedWith(t, tag)) {
     *         // special processing for tagged exception
     *     } else {
     *         // handling of other kinds of exceptions
     *     }
     * }
     * 
* * @param throwable The Throwable object to check * @param tag tag object * @return {@code true} if the throwable has the specified tag, * otherwise {@code false} */ public static boolean isTaggedWith(final Throwable throwable, final Object tag) { return tag != null && throwable instanceof TaggedIOException && tag.equals(((TaggedIOException) throwable).tag); } /** * Throws the original {@link IOException} if the given throwable is * a {@link TaggedIOException} decorator the given tag. Does nothing * if the given throwable is of a different type or if it is tagged * with some other tag. *

* This method is typically used in a {@code catch} block to * selectively rethrow tagged exceptions. *

     * Serializable tag = ...;
     * try {
     *     ...;
     * } catch (Throwable t) {
     *     TaggedIOException.throwCauseIfTagged(t, tag);
     *     // handle other kinds of exceptions
     * }
     * 
* * @param throwable an exception * @param tag tag object * @throws IOException original exception from the tagged decorator, if any */ public static void throwCauseIfTaggedWith(final Throwable throwable, final Object tag) throws IOException { if (isTaggedWith(throwable, tag)) { throw ((TaggedIOException) throwable).getCause(); } } /** * The tag of this exception. */ private final Serializable tag; /** * Creates a tagged wrapper for the given exception. * * @param original the exception to be tagged * @param tag tag of this exception */ public TaggedIOException(final IOException original, final Serializable tag) { super(original.getMessage(), original); this.tag = tag; } /** * Returns the serializable tag object. * * @return tag object */ public Serializable getTag() { return tag; } /** * Returns the wrapped exception. The only difference to the overridden * {@link Throwable#getCause()} method is the narrower return type. * * @return wrapped exception */ @Override public synchronized IOException getCause() { return (IOException) super.getCause(); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/ThreadMonitor.java0100644 0000000 0000000 00000010674 13612062727 027165 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import java.time.Duration; /** * Monitors a thread, interrupting it if it reaches the specified timeout. *

* This works by sleeping until the specified timeout amount and then * interrupting the thread being monitored. If the thread being monitored * completes its work before being interrupted, it should {@code interrupt()} * the monitor thread. *

* *
 *       long timeoutInMillis = 1000;
 *       try {
 *           Thread monitor = ThreadMonitor.start(timeoutInMillis);
 *           // do some work here
 *           ThreadMonitor.stop(monitor);
 *       } catch (InterruptedException e) {
 *           // timed amount was reached
 *       }
 * 
* */ class ThreadMonitor implements Runnable { private final Thread thread; private final Duration timeout; /** * Start monitoring the current thread. * * @param timeout The timeout amount in milliseconds * or no timeout if the value is zero or less * @return The monitor thread or {@code null} * if the timeout amount is not greater than zero */ static Thread start(final Duration timeout) { return start(Thread.currentThread(), timeout); } /** * Start monitoring the specified thread. * * @param thread The thread The thread to monitor * @param timeout The timeout amount in milliseconds * or no timeout if the value is zero or less * @return The monitor thread or {@code null} * if the timeout amount is not greater than zero */ static Thread start(final Thread thread, final Duration timeout) { if (timeout.isZero() || timeout.isNegative()) { return null; } final ThreadMonitor timout = new ThreadMonitor(thread, timeout); final Thread monitor = new Thread(timout, ThreadMonitor.class.getSimpleName()); monitor.setDaemon(true); monitor.start(); return monitor; } /** * Stop monitoring the specified thread. * * @param thread The monitor thread, may be {@code null} */ static void stop(final Thread thread) { if (thread != null) { thread.interrupt(); } } /** * Constructs a new monitor. * * @param thread The thread to monitor * @param timeout The timeout amount in milliseconds */ private ThreadMonitor(final Thread thread, final Duration timeout) { this.thread = thread; this.timeout = timeout; } /** * Sleep until the specified timeout amount and then * interrupt the thread being monitored. * * @see Runnable#run() */ @Override public void run() { try { sleep(timeout); thread.interrupt(); } catch (final InterruptedException e) { // timeout not reached } } /** * Sleeps for a guaranteed minimum duration unless interrupted. * * This method exists because Thread.sleep(100) can sleep for 0, 70, 100 or 200ms or anything else * it deems appropriate. Read the docs on Thread.sleep for further interesting details. * * @param duration the sleep duration. * @throws InterruptedException if interrupted */ private static void sleep(final Duration duration) throws InterruptedException { // Ignore nanos for now. final long millis = duration.toMillis(); final long finishAtMillis = System.currentTimeMillis() + millis; long remainingMillis = millis; do { Thread.sleep(remainingMillis); remainingMillis = finishAtMillis - System.currentTimeMillis(); } while (remainingMillis > 0); } }commons-io-2.11.0-src/src/main/java/org/apache/commons/io/comparator/AbstractFileComparator.java0100644 0000000 0000000 00000004301 13612062727 033136 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.comparator; import java.io.File; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; /** * Abstract file {@link Comparator} which provides sorting for file arrays and lists. * * @since 2.0 */ abstract class AbstractFileComparator implements Comparator { /** * Sort an array of files. *

* This method uses {@link Arrays#sort(Object[], Comparator)} and returns the original array. *

* * @param files The files to sort, may be null * @return The sorted array * @since 2.0 */ public File[] sort(final File... files) { if (files != null) { Arrays.sort(files, this); } return files; } /** * Sort a List of files. *

* This method uses {@link Collections#sort(List, Comparator)} and returns the original list. *

* * @param files The files to sort, may be null * @return The sorted list * @since 2.0 */ public List sort(final List files) { if (files != null) { files.sort(this); } return files; } /** * String representation of this file comparator. * * @return String representation of this file comparator */ @Override public String toString() { return getClass().getSimpleName(); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/comparator/CompositeFileComparator.java0100644 0000000 0000000 00000010704 13612062727 033341 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.comparator; import java.io.File; import java.io.Serializable; import java.util.ArrayList; import java.util.Comparator; import java.util.List; /** * Compare two files using a set of delegate file {@link Comparator}. *

* This comparator can be used to sort lists or arrays of files * by combining a number other comparators. *

* Example of sorting a list of files by type (i.e. directory or file) * and then by name: *

 *       CompositeFileComparator comparator =
 *                       new CompositeFileComparator(
 *                                 (AbstractFileComparator) DirectoryFileComparator.DIRECTORY_COMPARATOR,
 *                                 (AbstractFileComparator) NameFileComparator.NAME_COMPARATOR);
 *       List<File> list = ...
 *       comparator.sort(list);
 * 
* * @since 2.0 */ public class CompositeFileComparator extends AbstractFileComparator implements Serializable { private static final Comparator[] EMPTY_COMPARATOR_ARRAY = {}; private static final long serialVersionUID = -2224170307287243428L; private static final Comparator[] NO_COMPARATORS = {}; private final Comparator[] delegates; /** * Create a composite comparator for the set of delegate comparators. * * @param delegates The delegate file comparators */ @SuppressWarnings("unchecked") // casts 1 & 2 must be OK because types are already correct public CompositeFileComparator(final Comparator... delegates) { if (delegates == null) { this.delegates = (Comparator[]) NO_COMPARATORS;//1 } else { this.delegates = (Comparator[]) new Comparator[delegates.length];//2 System.arraycopy(delegates, 0, this.delegates, 0, delegates.length); } } /** * Create a composite comparator for the set of delegate comparators. * * @param delegates The delegate file comparators */ @SuppressWarnings("unchecked") // casts 1 & 2 must be OK because types are already correct public CompositeFileComparator(final Iterable> delegates) { if (delegates == null) { this.delegates = (Comparator[]) NO_COMPARATORS; //1 } else { final List> list = new ArrayList<>(); for (final Comparator comparator : delegates) { list.add(comparator); } this.delegates = (Comparator[]) list.toArray(EMPTY_COMPARATOR_ARRAY); //2 } } /** * Compare the two files using delegate comparators. * * @param file1 The first file to compare * @param file2 The second file to compare * @return the first non-zero result returned from * the delegate comparators or zero. */ @Override public int compare(final File file1, final File file2) { int result = 0; for (final Comparator delegate : delegates) { result = delegate.compare(file1, file2); if (result != 0) { break; } } return result; } /** * String representation of this file comparator. * * @return String representation of this file comparator */ @Override public String toString() { final StringBuilder builder = new StringBuilder(); builder.append(super.toString()); builder.append('{'); for (int i = 0; i < delegates.length; i++) { if (i > 0) { builder.append(','); } builder.append(delegates[i]); } builder.append('}'); return builder.toString(); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/comparator/DefaultFileComparator.java0100644 0000000 0000000 00000005000 13612062727 032754 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.comparator; import java.io.File; import java.io.Serializable; import java.util.Comparator; /** * Compare two files using the default {@link File#compareTo(File)} method. *

* This comparator can be used to sort lists or arrays of files * by using the default file comparison. *

* Example of sorting a list of files using the * {@link #DEFAULT_COMPARATOR} singleton instance: *

 *       List<File> list = ...
 *       ((AbstractFileComparator) DefaultFileComparator.DEFAULT_COMPARATOR).sort(list);
 * 
*

* Example of doing a reverse sort of an array of files using the * {@link #DEFAULT_REVERSE} singleton instance: *

 *       File[] array = ...
 *       ((AbstractFileComparator) DefaultFileComparator.DEFAULT_REVERSE).sort(array);
 * 
*

* * @since 1.4 */ public class DefaultFileComparator extends AbstractFileComparator implements Serializable { private static final long serialVersionUID = 3260141861365313518L; /** Singleton default comparator instance */ public static final Comparator DEFAULT_COMPARATOR = new DefaultFileComparator(); /** Singleton reverse default comparator instance */ public static final Comparator DEFAULT_REVERSE = new ReverseFileComparator(DEFAULT_COMPARATOR); /** * Compare the two files using the {@link File#compareTo(File)} method. * * @param file1 The first file to compare * @param file2 The second file to compare * @return the result of calling file1's * {@link File#compareTo(File)} with file2 as the parameter. */ @Override public int compare(final File file1, final File file2) { return file1.compareTo(file2); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/comparator/DirectoryFileComparator.java0100644 0000000 0000000 00000005546 13612062727 033353 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.comparator; import java.io.File; import java.io.Serializable; import java.util.Comparator; /** * Compare two files using the {@link File#isDirectory()} method. *

* This comparator can be used to sort lists or arrays by directories and files. *

* Example of sorting a list of files/directories using the * {@link #DIRECTORY_COMPARATOR} singleton instance: *

 *       List<File> list = ...
 *       ((AbstractFileComparator) DirectoryFileComparator.DIRECTORY_COMPARATOR).sort(list);
 * 
*

* Example of doing a reverse sort of an array of files/directories using the * {@link #DIRECTORY_REVERSE} singleton instance: *

 *       File[] array = ...
 *       ((AbstractFileComparator) DirectoryFileComparator.DIRECTORY_REVERSE).sort(array);
 * 
*

* * @since 2.0 */ public class DirectoryFileComparator extends AbstractFileComparator implements Serializable { private static final int TYPE_FILE = 2; private static final int TYPE_DIRECTORY = 1; private static final long serialVersionUID = 296132640160964395L; /** Singleton default comparator instance */ public static final Comparator DIRECTORY_COMPARATOR = new DirectoryFileComparator(); /** Singleton reverse default comparator instance */ public static final Comparator DIRECTORY_REVERSE = new ReverseFileComparator(DIRECTORY_COMPARATOR); /** * Compare the two files using the {@link File#isDirectory()} method. * * @param file1 The first file to compare * @param file2 The second file to compare * @return the result of calling file1's * {@link File#compareTo(File)} with file2 as the parameter. */ @Override public int compare(final File file1, final File file2) { return getType(file1) - getType(file2); } /** * Convert type to numeric value. * * @param file The file * @return 1 for directories and 2 for files */ private int getType(final File file) { return file.isDirectory() ? TYPE_DIRECTORY : TYPE_FILE; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/comparator/ExtensionFileComparator.java0100644 0000000 0000000 00000012136 13612062727 033354 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.comparator; import java.io.File; import java.io.Serializable; import java.util.Comparator; import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.IOCase; /** * Compare the file name extensions for order * (see {@link FilenameUtils#getExtension(String)}). *

* This comparator can be used to sort lists or arrays of files * by their file extension either in a case-sensitive, case-insensitive or * system dependent case sensitive way. A number of singleton instances * are provided for the various case sensitivity options (using {@link IOCase}) * and the reverse of those options. *

* Example of a case-sensitive file extension sort using the * {@link #EXTENSION_COMPARATOR} singleton instance: *

 *       List<File> list = ...
 *       ((AbstractFileComparator) ExtensionFileComparator.EXTENSION_COMPARATOR).sort(list);
 * 
*

* Example of a reverse case-insensitive file extension sort using the * {@link #EXTENSION_INSENSITIVE_REVERSE} singleton instance: *

 *       File[] array = ...
 *       ((AbstractFileComparator) ExtensionFileComparator.EXTENSION_INSENSITIVE_REVERSE).sort(array);
 * 
*

* * @since 1.4 */ public class ExtensionFileComparator extends AbstractFileComparator implements Serializable { private static final long serialVersionUID = 1928235200184222815L; /** Case-sensitive extension comparator instance (see {@link IOCase#SENSITIVE}) */ public static final Comparator EXTENSION_COMPARATOR = new ExtensionFileComparator(); /** Reverse case-sensitive extension comparator instance (see {@link IOCase#SENSITIVE}) */ public static final Comparator EXTENSION_REVERSE = new ReverseFileComparator(EXTENSION_COMPARATOR); /** Case-insensitive extension comparator instance (see {@link IOCase#INSENSITIVE}) */ public static final Comparator EXTENSION_INSENSITIVE_COMPARATOR = new ExtensionFileComparator(IOCase.INSENSITIVE); /** Reverse case-insensitive extension comparator instance (see {@link IOCase#INSENSITIVE}) */ public static final Comparator EXTENSION_INSENSITIVE_REVERSE = new ReverseFileComparator(EXTENSION_INSENSITIVE_COMPARATOR); /** System sensitive extension comparator instance (see {@link IOCase#SYSTEM}) */ public static final Comparator EXTENSION_SYSTEM_COMPARATOR = new ExtensionFileComparator(IOCase.SYSTEM); /** Reverse system sensitive path comparator instance (see {@link IOCase#SYSTEM}) */ public static final Comparator EXTENSION_SYSTEM_REVERSE = new ReverseFileComparator(EXTENSION_SYSTEM_COMPARATOR); /** Whether the comparison is case sensitive. */ private final IOCase caseSensitivity; /** * Construct a case sensitive file extension comparator instance. */ public ExtensionFileComparator() { this.caseSensitivity = IOCase.SENSITIVE; } /** * Construct a file extension comparator instance with the specified case-sensitivity. * * @param caseSensitivity how to handle case sensitivity, null means case-sensitive */ public ExtensionFileComparator(final IOCase caseSensitivity) { this.caseSensitivity = caseSensitivity == null ? IOCase.SENSITIVE : caseSensitivity; } /** * Compare the extensions of two files the specified case sensitivity. * * @param file1 The first file to compare * @param file2 The second file to compare * @return a negative value if the first file's extension * is less than the second, zero if the extensions are the * same and a positive value if the first files extension * is greater than the second file. * */ @Override public int compare(final File file1, final File file2) { final String suffix1 = FilenameUtils.getExtension(file1.getName()); final String suffix2 = FilenameUtils.getExtension(file2.getName()); return caseSensitivity.checkCompareTo(suffix1, suffix2); } /** * String representation of this file comparator. * * @return String representation of this file comparator */ @Override public String toString() { return super.toString() + "[caseSensitivity=" + caseSensitivity + "]"; } } ././@LongLink0100644 0000000 0000000 00000000145 13612062727 011641 Lustar 0000000 0000000 commons-io-2.11.0-src/src/main/java/org/apache/commons/io/comparator/LastModifiedFileComparator.javacommons-io-2.11.0-src/src/main/java/org/apache/commons/io/comparator/LastModifiedFileComparator.java0100644 0000000 0000000 00000005755 13612062727 033755 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.comparator; import java.io.File; import java.io.Serializable; import java.util.Comparator; import org.apache.commons.io.FileUtils; /** * Compare the last modified date/time of two files for order * (see {@link FileUtils#lastModifiedUnchecked(File)}). *

* This comparator can be used to sort lists or arrays of files * by their last modified date/time. *

* Example of sorting a list of files using the * {@link #LASTMODIFIED_COMPARATOR} singleton instance: *

 *       List<File> list = ...
 *       ((AbstractFileComparator) LastModifiedFileComparator.LASTMODIFIED_COMPARATOR).sort(list);
 * 
*

* Example of doing a reverse sort of an array of files using the * {@link #LASTMODIFIED_REVERSE} singleton instance: *

 *       File[] array = ...
 *       ((AbstractFileComparator) LastModifiedFileComparator.LASTMODIFIED_REVERSE).sort(array);
 * 
*

* * @since 1.4 */ public class LastModifiedFileComparator extends AbstractFileComparator implements Serializable { private static final long serialVersionUID = 7372168004395734046L; /** Last modified comparator instance. */ public static final Comparator LASTMODIFIED_COMPARATOR = new LastModifiedFileComparator(); /** Reverse last modified comparator instance. */ public static final Comparator LASTMODIFIED_REVERSE = new ReverseFileComparator(LASTMODIFIED_COMPARATOR); /** * Compares the last the last modified date/time of two files. * * @param file1 The first file to compare. * @param file2 The second file to compare. * @return a negative value if the first file's last modified date/time is less than the second, zero if the last * modified date/time are the same and a positive value if the first files last modified date/time is * greater than the second file. */ @Override public int compare(final File file1, final File file2) { final long result = FileUtils.lastModifiedUnchecked(file1) - FileUtils.lastModifiedUnchecked(file2); if (result < 0) { return -1; } if (result > 0) { return 1; } return 0; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/comparator/NameFileComparator.java0100644 0000000 0000000 00000011174 13612062727 032261 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.comparator; import java.io.File; import java.io.Serializable; import java.util.Comparator; import org.apache.commons.io.IOCase; /** * Compare the names of two files for order (see {@link File#getName()}). *

* This comparator can be used to sort lists or arrays of files * by their name either in a case-sensitive, case-insensitive or * system dependent case sensitive way. A number of singleton instances * are provided for the various case sensitivity options (using {@link IOCase}) * and the reverse of those options. *

* Example of a case-sensitive file name sort using the * {@link #NAME_COMPARATOR} singleton instance: *

 *       List<File> list = ...
 *       ((AbstractFileComparator) NameFileComparator.NAME_COMPARATOR).sort(list);
 * 
*

* Example of a reverse case-insensitive file name sort using the * {@link #NAME_INSENSITIVE_REVERSE} singleton instance: *

 *       File[] array = ...
 *       ((AbstractFileComparator) NameFileComparator.NAME_INSENSITIVE_REVERSE).sort(array);
 * 
*

* * @since 1.4 */ public class NameFileComparator extends AbstractFileComparator implements Serializable { private static final long serialVersionUID = 8397947749814525798L; /** Case-sensitive name comparator instance (see {@link IOCase#SENSITIVE}) */ public static final Comparator NAME_COMPARATOR = new NameFileComparator(); /** Reverse case-sensitive name comparator instance (see {@link IOCase#SENSITIVE}) */ public static final Comparator NAME_REVERSE = new ReverseFileComparator(NAME_COMPARATOR); /** Case-insensitive name comparator instance (see {@link IOCase#INSENSITIVE}) */ public static final Comparator NAME_INSENSITIVE_COMPARATOR = new NameFileComparator(IOCase.INSENSITIVE); /** Reverse case-insensitive name comparator instance (see {@link IOCase#INSENSITIVE}) */ public static final Comparator NAME_INSENSITIVE_REVERSE = new ReverseFileComparator(NAME_INSENSITIVE_COMPARATOR); /** System sensitive name comparator instance (see {@link IOCase#SYSTEM}) */ public static final Comparator NAME_SYSTEM_COMPARATOR = new NameFileComparator(IOCase.SYSTEM); /** Reverse system sensitive name comparator instance (see {@link IOCase#SYSTEM}) */ public static final Comparator NAME_SYSTEM_REVERSE = new ReverseFileComparator(NAME_SYSTEM_COMPARATOR); /** Whether the comparison is case sensitive. */ private final IOCase caseSensitivity; /** * Construct a case sensitive file name comparator instance. */ public NameFileComparator() { this.caseSensitivity = IOCase.SENSITIVE; } /** * Construct a file name comparator instance with the specified case-sensitivity. * * @param caseSensitivity how to handle case sensitivity, null means case-sensitive */ public NameFileComparator(final IOCase caseSensitivity) { this.caseSensitivity = caseSensitivity == null ? IOCase.SENSITIVE : caseSensitivity; } /** * Compare the names of two files with the specified case sensitivity. * * @param file1 The first file to compare * @param file2 The second file to compare * @return a negative value if the first file's name * is less than the second, zero if the names are the * same and a positive value if the first files name * is greater than the second file. */ @Override public int compare(final File file1, final File file2) { return caseSensitivity.checkCompareTo(file1.getName(), file2.getName()); } /** * String representation of this file comparator. * * @return String representation of this file comparator */ @Override public String toString() { return super.toString() + "[caseSensitivity=" + caseSensitivity + "]"; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/comparator/PathFileComparator.java0100644 0000000 0000000 00000011175 13612062727 032276 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.comparator; import java.io.File; import java.io.Serializable; import java.util.Comparator; import org.apache.commons.io.IOCase; /** * Compare the path of two files for order (see {@link File#getPath()}). *

* This comparator can be used to sort lists or arrays of files * by their path either in a case-sensitive, case-insensitive or * system dependent case sensitive way. A number of singleton instances * are provided for the various case sensitivity options (using {@link IOCase}) * and the reverse of those options. *

* Example of a case-sensitive file path sort using the * {@link #PATH_COMPARATOR} singleton instance: *

 *       List<File> list = ...
 *       ((AbstractFileComparator) PathFileComparator.PATH_COMPARATOR).sort(list);
 * 
*

* Example of a reverse case-insensitive file path sort using the * {@link #PATH_INSENSITIVE_REVERSE} singleton instance: *

 *       File[] array = ...
 *       ((AbstractFileComparator) PathFileComparator.PATH_INSENSITIVE_REVERSE).sort(array);
 * 
*

* * @since 1.4 */ public class PathFileComparator extends AbstractFileComparator implements Serializable { private static final long serialVersionUID = 6527501707585768673L; /** Case-sensitive path comparator instance (see {@link IOCase#SENSITIVE}) */ public static final Comparator PATH_COMPARATOR = new PathFileComparator(); /** Reverse case-sensitive path comparator instance (see {@link IOCase#SENSITIVE}) */ public static final Comparator PATH_REVERSE = new ReverseFileComparator(PATH_COMPARATOR); /** Case-insensitive path comparator instance (see {@link IOCase#INSENSITIVE}) */ public static final Comparator PATH_INSENSITIVE_COMPARATOR = new PathFileComparator(IOCase.INSENSITIVE); /** Reverse case-insensitive path comparator instance (see {@link IOCase#INSENSITIVE}) */ public static final Comparator PATH_INSENSITIVE_REVERSE = new ReverseFileComparator(PATH_INSENSITIVE_COMPARATOR); /** System sensitive path comparator instance (see {@link IOCase#SYSTEM}) */ public static final Comparator PATH_SYSTEM_COMPARATOR = new PathFileComparator(IOCase.SYSTEM); /** Reverse system sensitive path comparator instance (see {@link IOCase#SYSTEM}) */ public static final Comparator PATH_SYSTEM_REVERSE = new ReverseFileComparator(PATH_SYSTEM_COMPARATOR); /** Whether the comparison is case sensitive. */ private final IOCase caseSensitivity; /** * Construct a case sensitive file path comparator instance. */ public PathFileComparator() { this.caseSensitivity = IOCase.SENSITIVE; } /** * Construct a file path comparator instance with the specified case-sensitivity. * * @param caseSensitivity how to handle case sensitivity, null means case-sensitive */ public PathFileComparator(final IOCase caseSensitivity) { this.caseSensitivity = caseSensitivity == null ? IOCase.SENSITIVE : caseSensitivity; } /** * Compare the paths of two files the specified case sensitivity. * * @param file1 The first file to compare * @param file2 The second file to compare * @return a negative value if the first file's path * is less than the second, zero if the paths are the * same and a positive value if the first files path * is greater than the second file. * */ @Override public int compare(final File file1, final File file2) { return caseSensitivity.checkCompareTo(file1.getPath(), file2.getPath()); } /** * String representation of this file comparator. * * @return String representation of this file comparator */ @Override public String toString() { return super.toString() + "[caseSensitivity=" + caseSensitivity + "]"; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/comparator/ReverseFileComparator.java0100644 0000000 0000000 00000004576 13612062727 033024 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.comparator; import java.io.File; import java.io.Serializable; import java.util.Comparator; /** * Reverses the result of comparing two {@link File} objects using the delegate {@link Comparator}. * * @since 1.4 */ class ReverseFileComparator extends AbstractFileComparator implements Serializable { private static final long serialVersionUID = -4808255005272229056L; private final Comparator delegate; /** * Construct an instance with the specified delegate {@link Comparator}. * * @param delegate The comparator to delegate to. */ public ReverseFileComparator(final Comparator delegate) { if (delegate == null) { throw new IllegalArgumentException("Delegate comparator is missing"); } this.delegate = delegate; } /** * Compares using the delegate Comparator, reversing the result. * * @param file1 The first file to compare. * @param file2 The second file to compare. * @return the result from the delegate {@link Comparator#compare(Object, Object)} reversing the value (i.e. * positive becomes negative and vice versa). */ @Override public int compare(final File file1, final File file2) { return delegate.compare(file2, file1); // parameters switched round } /** * Returns the String representation of this file comparator. * * @return String representation of this file comparator. */ @Override public String toString() { return super.toString() + "[" + delegate.toString() + "]"; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/comparator/SizeFileComparator.java0100644 0000000 0000000 00000012172 13612062727 032312 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.comparator; import java.io.File; import java.io.Serializable; import java.util.Comparator; import org.apache.commons.io.FileUtils; /** * Compare the length/size of two files for order (see * {@link File#length()} and {@link FileUtils#sizeOfDirectory(File)}). *

* This comparator can be used to sort lists or arrays of files * by their length/size. *

* Example of sorting a list of files using the * {@link #SIZE_COMPARATOR} singleton instance: *

 *       List<File> list = ...
 *       ((AbstractFileComparator) SizeFileComparator.SIZE_COMPARATOR).sort(list);
 * 
*

* Example of doing a reverse sort of an array of files using the * {@link #SIZE_REVERSE} singleton instance: *

 *       File[] array = ...
 *       ((AbstractFileComparator) SizeFileComparator.SIZE_REVERSE).sort(array);
 * 
*

* N.B. Directories are treated as zero size unless * {@code sumDirectoryContents} is {@code true}. * * @since 1.4 */ public class SizeFileComparator extends AbstractFileComparator implements Serializable { private static final long serialVersionUID = -1201561106411416190L; /** Size comparator instance - directories are treated as zero size */ public static final Comparator SIZE_COMPARATOR = new SizeFileComparator(); /** Reverse size comparator instance - directories are treated as zero size */ public static final Comparator SIZE_REVERSE = new ReverseFileComparator(SIZE_COMPARATOR); /** * Size comparator instance which sums the size of a directory's contents * using {@link FileUtils#sizeOfDirectory(File)} */ public static final Comparator SIZE_SUMDIR_COMPARATOR = new SizeFileComparator(true); /** * Reverse size comparator instance which sums the size of a directory's contents * using {@link FileUtils#sizeOfDirectory(File)} */ public static final Comparator SIZE_SUMDIR_REVERSE = new ReverseFileComparator(SIZE_SUMDIR_COMPARATOR); /** Whether the sum of the directory's contents should be calculated. */ private final boolean sumDirectoryContents; /** * Construct a file size comparator instance (directories treated as zero size). */ public SizeFileComparator() { this.sumDirectoryContents = false; } /** * Construct a file size comparator instance specifying whether the size of * the directory contents should be aggregated. *

* If the {@code sumDirectoryContents} is {@code true} The size of * directories is calculated using {@link FileUtils#sizeOfDirectory(File)}. * * @param sumDirectoryContents {@code true} if the sum of the directories' contents * should be calculated, otherwise {@code false} if directories should be treated * as size zero (see {@link FileUtils#sizeOfDirectory(File)}). */ public SizeFileComparator(final boolean sumDirectoryContents) { this.sumDirectoryContents = sumDirectoryContents; } /** * Compare the length of two files. * * @param file1 The first file to compare * @param file2 The second file to compare * @return a negative value if the first file's length * is less than the second, zero if the lengths are the * same and a positive value if the first files length * is greater than the second file. * */ @Override public int compare(final File file1, final File file2) { final long size1; if (file1.isDirectory()) { size1 = sumDirectoryContents && file1.exists() ? FileUtils.sizeOfDirectory(file1) : 0; } else { size1 = file1.length(); } final long size2; if (file2.isDirectory()) { size2 = sumDirectoryContents && file2.exists() ? FileUtils.sizeOfDirectory(file2) : 0; } else { size2 = file2.length(); } final long result = size1 - size2; if (result < 0) { return -1; } if (result > 0) { return 1; } return 0; } /** * String representation of this file comparator. * * @return String representation of this file comparator */ @Override public String toString() { return super.toString() + "[sumDirectoryContents=" + sumDirectoryContents + "]"; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/comparator/package.html0100644 0000000 0000000 00000021360 13612062727 030165 0ustar00rootroot0000000 0000000

This package provides various {@link java.util.Comparator} implementations for {@link java.io.File}s.

Sorting

All the compartors include convenience utility sort(File...) and sort(List) methods.

For example, to sort the files in a directory by name:

        File[] files = dir.listFiles();
        NameFileComparator.NAME_COMPARATOR.sort(files);
  

...alternatively you can do this in one line:

      File[] files = NameFileComparator.NAME_COMPARATOR.sort(dir.listFiles());

Composite Comparator

The CompositeFileComparator can be used to compare (and sort lists or arrays of files) by combining a number other comparators.

For example, to sort an array of files by type (i.e. directory or file) and then by name:

      CompositeFileComparator comparator =
                      new CompositeFileComparator(
                                  DirectoryFileComparator.DIRECTORY_COMPARATOR,
                                  NameFileComparator.NAME_COMPARATOR);
      File[] files = dir.listFiles();
      comparator.sort(files);

Singleton Instances (thread-safe)

The {@link java.util.Comparator} implementations have some convenience singleton(thread-safe) instances ready to use:

commons-io-2.11.0-src/src/main/java/org/apache/commons/io/file/AccumulatorPathVisitor.java0100644 0000000 0000000 00000016355 13612062727 032003 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.file; import java.io.IOException; import java.nio.file.Path; import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.Objects; import org.apache.commons.io.file.Counters.PathCounters; /** * Accumulates normalized paths during visitation. *

* Use with care on large file trees as each visited Path element is remembered. *

*

Example

* *
 * Path dir = Paths.get("");
 * // We are interested in files older than one day
 * long cutoff = System.currentTimeMillis() - (24 * 60 * 60 * 1000);
 * AccumulatorPathVisitor visitor = AccumulatorPathVisitor.withLongCounters(new AgeFileFilter(cutoff));
 * //
 * // Walk one dir
 * Files.walkFileTree(dir, Collections.emptySet(), 1, visitor);
 * System.out.println(visitor.getPathCounters());
 * System.out.println(visitor.getFileList());
 * //
 * visitor.getPathCounters().reset();
 * //
 * // Walk dir tree
 * Files.walkFileTree(dir, visitor);
 * System.out.println(visitor.getPathCounters());
 * System.out.println(visitor.getDirList());
 * System.out.println(visitor.getFileList());
 * 
* * @since 2.7 */ public class AccumulatorPathVisitor extends CountingPathVisitor { /** * Creates a new instance configured with a BigInteger {@link PathCounters}. * * @return a new instance configured with a BigInteger {@link PathCounters}. */ public static AccumulatorPathVisitor withBigIntegerCounters() { return new AccumulatorPathVisitor(Counters.bigIntegerPathCounters()); } /** * Creates a new instance configured with a BigInteger {@link PathCounters}. * * @param fileFilter Filters files to accumulate and count. * @param dirFilter Filters directories to accumulate and count. * @return a new instance configured with a long {@link PathCounters}. * @since 2.9.0 */ public static AccumulatorPathVisitor withBigIntegerCounters(final PathFilter fileFilter, final PathFilter dirFilter) { return new AccumulatorPathVisitor(Counters.bigIntegerPathCounters(), fileFilter, dirFilter); } /** * Creates a new instance configured with a long {@link PathCounters}. * * @return a new instance configured with a long {@link PathCounters}. */ public static AccumulatorPathVisitor withLongCounters() { return new AccumulatorPathVisitor(Counters.longPathCounters()); } /** * Creates a new instance configured with a long {@link PathCounters}. * * @param fileFilter Filters files to accumulate and count. * @param dirFilter Filters directories to accumulate and count. * @return a new instance configured with a long {@link PathCounters}. * @since 2.9.0 */ public static AccumulatorPathVisitor withLongCounters(final PathFilter fileFilter, final PathFilter dirFilter) { return new AccumulatorPathVisitor(Counters.longPathCounters(), fileFilter, dirFilter); } private final List dirList = new ArrayList<>(); private final List fileList = new ArrayList<>(); /** * Constructs a new instance. * * @since 2.9.0 */ public AccumulatorPathVisitor() { super(Counters.noopPathCounters()); } /** * Constructs a new instance that counts file system elements. * * @param pathCounter How to count path visits. */ public AccumulatorPathVisitor(final PathCounters pathCounter) { super(pathCounter); } /** * Constructs a new instance. * * @param pathCounter How to count path visits. * @param fileFilter Filters which files to count. * @param dirFilter Filters which directories to count. * @since 2.9.0 */ public AccumulatorPathVisitor(final PathCounters pathCounter, final PathFilter fileFilter, final PathFilter dirFilter) { super(pathCounter, fileFilter, dirFilter); } private void add(final List list, final Path dir) { list.add(dir.normalize()); } @Override public boolean equals(final Object obj) { if (this == obj) { return true; } if (!super.equals(obj)) { return false; } if (!(obj instanceof AccumulatorPathVisitor)) { return false; } final AccumulatorPathVisitor other = (AccumulatorPathVisitor) obj; return Objects.equals(dirList, other.dirList) && Objects.equals(fileList, other.fileList); } /** * Gets the list of visited directories. * * @return the list of visited directories. */ public List getDirList() { return dirList; } /** * Gets the list of visited files. * * @return the list of visited files. */ public List getFileList() { return fileList; } @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); result = prime * result + Objects.hash(dirList, fileList); return result; } /** * Relativizes each directory path with {@link Path#relativize(Path)} against the given {@code parent}, optionally * sorting the result. * * @param parent A parent path * @param sort Whether to sort * @param comparator How to sort, null uses default sorting. * @return A new list */ public List relativizeDirectories(final Path parent, final boolean sort, final Comparator comparator) { return PathUtils.relativize(getDirList(), parent, sort, comparator); } /** * Relativizes each file path with {@link Path#relativize(Path)} against the given {@code parent}, optionally * sorting the result. * * @param parent A parent path * @param sort Whether to sort * @param comparator How to sort, null uses default sorting. * @return A new list */ public List relativizeFiles(final Path parent, final boolean sort, final Comparator comparator) { return PathUtils.relativize(getFileList(), parent, sort, comparator); } @Override protected void updateDirCounter(final Path dir, final IOException exc) { super.updateDirCounter(dir, exc); add(dirList, dir); } @Override protected void updateFileCounters(final Path file, final BasicFileAttributes attributes) { super.updateFileCounters(file, attributes); add(fileList, file); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/file/CleaningPathVisitor.java0100644 0000000 0000000 00000011571 13612062727 031237 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.file; import java.io.IOException; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.LinkOption; import java.nio.file.Path; import java.nio.file.attribute.BasicFileAttributes; import java.util.Arrays; import java.util.Objects; import org.apache.commons.io.file.Counters.PathCounters; /** * Deletes files but not directories as a visit proceeds. * * @since 2.7 */ public class CleaningPathVisitor extends CountingPathVisitor { /** * Creates a new instance configured with a BigInteger {@link PathCounters}. * * @return a new instance configured with a BigInteger {@link PathCounters}. */ public static CountingPathVisitor withBigIntegerCounters() { return new CleaningPathVisitor(Counters.bigIntegerPathCounters()); } /** * Creates a new instance configured with a long {@link PathCounters}. * * @return a new instance configured with a long {@link PathCounters}. */ public static CountingPathVisitor withLongCounters() { return new CleaningPathVisitor(Counters.longPathCounters()); } private final String[] skip; private final boolean overrideReadOnly; /** * Constructs a new visitor that deletes files except for the files and directories explicitly given. * * @param pathCounter How to count visits. * @param deleteOption How deletion is handled. * @param skip The files to skip deleting. * @since 2.8.0 */ public CleaningPathVisitor(final PathCounters pathCounter, final DeleteOption[] deleteOption, final String... skip) { super(pathCounter); final String[] temp = skip != null ? skip.clone() : EMPTY_STRING_ARRAY; Arrays.sort(temp); this.skip = temp; this.overrideReadOnly = StandardDeleteOption.overrideReadOnly(deleteOption); } /** * Constructs a new visitor that deletes files except for the files and directories explicitly given. * * @param pathCounter How to count visits. * @param skip The files to skip deleting. */ public CleaningPathVisitor(final PathCounters pathCounter, final String... skip) { this(pathCounter, PathUtils.EMPTY_DELETE_OPTION_ARRAY, skip); } /** * Returns true to process the given path, false if not. * * @param path the path to test. * @return true to process the given path, false if not. */ private boolean accept(final Path path) { return Arrays.binarySearch(skip, Objects.toString(path.getFileName(), null)) < 0; } @Override public boolean equals(final Object obj) { if (this == obj) { return true; } if (!super.equals(obj)) { return false; } if (getClass() != obj.getClass()) { return false; } final CleaningPathVisitor other = (CleaningPathVisitor) obj; return overrideReadOnly == other.overrideReadOnly && Arrays.equals(skip, other.skip); } @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); result = prime * result + Arrays.hashCode(skip); result = prime * result + Objects.hash(overrideReadOnly); return result; } @Override public FileVisitResult preVisitDirectory(final Path dir, final BasicFileAttributes attributes) throws IOException { super.preVisitDirectory(dir, attributes); return accept(dir) ? FileVisitResult.CONTINUE : FileVisitResult.SKIP_SUBTREE; } @Override public FileVisitResult visitFile(final Path file, final BasicFileAttributes attributes) throws IOException { // Files.deleteIfExists() never follows links, so use LinkOption.NOFOLLOW_LINKS in other calls to Files. if (accept(file) && Files.exists(file, LinkOption.NOFOLLOW_LINKS)) { if (overrideReadOnly) { PathUtils.setReadOnly(file, false, LinkOption.NOFOLLOW_LINKS); } Files.deleteIfExists(file); } updateFileCounters(file, attributes); return FileVisitResult.CONTINUE; } }commons-io-2.11.0-src/src/main/java/org/apache/commons/io/file/CopyDirectoryVisitor.java0100644 0000000 0000000 00000014232 13612062727 031476 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.file; import java.io.IOException; import java.nio.file.CopyOption; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.ProviderMismatchException; import java.nio.file.attribute.BasicFileAttributes; import java.util.Arrays; import java.util.Objects; import org.apache.commons.io.file.Counters.PathCounters; /** * Copies a source directory to a target directory. * * @since 2.7 */ public class CopyDirectoryVisitor extends CountingPathVisitor { private final CopyOption[] copyOptions; private final Path sourceDirectory; private final Path targetDirectory; /** * Constructs a new visitor that deletes files except for the files and directories explicitly given. * * @param pathCounter How to count visits. * @param sourceDirectory The source directory * @param targetDirectory The target directory * @param copyOptions Specifies how the copying should be done. */ public CopyDirectoryVisitor(final PathCounters pathCounter, final Path sourceDirectory, final Path targetDirectory, final CopyOption... copyOptions) { super(pathCounter); this.sourceDirectory = sourceDirectory; this.targetDirectory = targetDirectory; this.copyOptions = copyOptions == null ? PathUtils.EMPTY_COPY_OPTIONS : copyOptions.clone(); } /** * Constructs a new visitor that deletes files except for the files and directories explicitly given. * * @param pathCounter How to count visits. * @param fileFilter How to filter file paths. * @param dirFilter How to filter directory paths. * @param sourceDirectory The source directory * @param targetDirectory The target directory * @param copyOptions Specifies how the copying should be done. * @since 2.9.0 */ public CopyDirectoryVisitor(final PathCounters pathCounter, final PathFilter fileFilter, final PathFilter dirFilter, final Path sourceDirectory, final Path targetDirectory, final CopyOption... copyOptions) { super(pathCounter, fileFilter, dirFilter); this.sourceDirectory = sourceDirectory; this.targetDirectory = targetDirectory; this.copyOptions = copyOptions == null ? PathUtils.EMPTY_COPY_OPTIONS : copyOptions.clone(); } /** * Copies the sourceFile to the targetFile. * * @param sourceFile the source file. * @param targetFile the target file. * @throws IOException if an I/O error occurs. * @since 2.8.0 */ protected void copy(final Path sourceFile, final Path targetFile) throws IOException { Files.copy(sourceFile, targetFile, copyOptions); } @Override public boolean equals(final Object obj) { if (this == obj) { return true; } if (!super.equals(obj)) { return false; } if (getClass() != obj.getClass()) { return false; } final CopyDirectoryVisitor other = (CopyDirectoryVisitor) obj; return Arrays.equals(copyOptions, other.copyOptions) && Objects.equals(sourceDirectory, other.sourceDirectory) && Objects.equals(targetDirectory, other.targetDirectory); } /** * Gets the copy options. * * @return the copy options. * @since 2.8.0 */ public CopyOption[] getCopyOptions() { return copyOptions.clone(); } /** * Gets the source directory. * * @return the source directory. * @since 2.8.0 */ public Path getSourceDirectory() { return sourceDirectory; } /** * Gets the target directory. * * @return the target directory. * @since 2.8.0 */ public Path getTargetDirectory() { return targetDirectory; } @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); result = prime * result + Arrays.hashCode(copyOptions); result = prime * result + Objects.hash(sourceDirectory, targetDirectory); return result; } @Override public FileVisitResult preVisitDirectory(final Path directory, final BasicFileAttributes attributes) throws IOException { final Path newTargetDir = resolveRelativeAsString(directory); if (Files.notExists(newTargetDir)) { Files.createDirectory(newTargetDir); } return super.preVisitDirectory(directory, attributes); } /** * Relativizes against {@code sourceDirectory}, then resolves against {@code targetDirectory}. * * We have to call {@link Path#toString()} relative value because we cannot use paths belonging to different * FileSystems in the Path methods, usually this leads to {@link ProviderMismatchException}. * * @param directory the directory to relativize. * @return a new path, relativized against sourceDirectory, then resolved against targetDirectory. */ private Path resolveRelativeAsString(final Path directory) { return targetDirectory.resolve(sourceDirectory.relativize(directory).toString()); } @Override public FileVisitResult visitFile(final Path sourceFile, final BasicFileAttributes attributes) throws IOException { final Path targetFile = resolveRelativeAsString(sourceFile); copy(sourceFile, targetFile); return super.visitFile(targetFile, attributes); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/file/Counters.java0100644 0000000 0000000 00000025025 13612062727 027123 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.file; import java.math.BigInteger; import java.util.Objects; /** * Provides counters for files, directories, and sizes, as a visit proceeds. * * @since 2.7 */ public class Counters { /** * Counts files, directories, and sizes, as a visit proceeds. */ private static class AbstractPathCounters implements PathCounters { private final Counter byteCounter; private final Counter directoryCounter; private final Counter fileCounter; /** * Constructs a new instance. * * @param byteCounter the byte counter. * @param directoryCounter the directory counter. * @param fileCounter the file counter. */ protected AbstractPathCounters(final Counter byteCounter, final Counter directoryCounter, final Counter fileCounter) { this.byteCounter = byteCounter; this.directoryCounter = directoryCounter; this.fileCounter = fileCounter; } @Override public boolean equals(final Object obj) { if (this == obj) { return true; } if (!(obj instanceof AbstractPathCounters)) { return false; } final AbstractPathCounters other = (AbstractPathCounters) obj; return Objects.equals(byteCounter, other.byteCounter) && Objects.equals(directoryCounter, other.directoryCounter) && Objects.equals(fileCounter, other.fileCounter); } @Override public Counter getByteCounter() { return byteCounter; } @Override public Counter getDirectoryCounter() { return directoryCounter; } /** * Gets the count of visited files. * * @return the byte count of visited files. */ @Override public Counter getFileCounter() { return this.fileCounter; } @Override public int hashCode() { return Objects.hash(byteCounter, directoryCounter, fileCounter); } @Override public void reset() { byteCounter.reset(); directoryCounter.reset(); fileCounter.reset(); } @Override public String toString() { return String.format("%,d files, %,d directories, %,d bytes", Long.valueOf(fileCounter.get()), Long.valueOf(directoryCounter.get()), Long.valueOf(byteCounter.get())); } } /** * Counts using a BigInteger number. */ private static final class BigIntegerCounter implements Counter { private BigInteger value = BigInteger.ZERO; @Override public void add(final long val) { value = value.add(BigInteger.valueOf(val)); } @Override public boolean equals(final Object obj) { if (this == obj) { return true; } if (!(obj instanceof Counter)) { return false; } final Counter other = (Counter) obj; return Objects.equals(value, other.getBigInteger()); } @Override public long get() { return value.longValueExact(); } @Override public BigInteger getBigInteger() { return value; } @Override public Long getLong() { return Long.valueOf(value.longValueExact()); } @Override public int hashCode() { return Objects.hash(value); } @Override public void increment() { value = value.add(BigInteger.ONE); } @Override public String toString() { return value.toString(); } @Override public void reset() { value = BigInteger.ZERO; } } /** * Counts files, directories, and sizes, as a visit proceeds, using BigInteger numbers. */ private final static class BigIntegerPathCounters extends AbstractPathCounters { /** * Constructs a new initialized instance. */ protected BigIntegerPathCounters() { super(Counters.bigIntegerCounter(), Counters.bigIntegerCounter(), Counters.bigIntegerCounter()); } } /** * Counts using a number. */ public interface Counter { /** * Adds the given number to this counter. * * @param val the value to add. */ void add(long val); /** * Gets the counter as a long. * * @return the counter as a long. */ long get(); /** * Gets the counter as a BigInteger. * * @return the counter as a BigInteger. */ BigInteger getBigInteger(); /** * Gets the counter as a Long. * * @return the counter as a Long. */ Long getLong(); /** * Adds one to this counter. */ void increment(); /** * Resets this count to 0. */ default void reset() { // binary compat, do nothing } } /** * Counts using a long number. */ private final static class LongCounter implements Counter { private long value; @Override public void add(final long add) { value += add; } @Override public boolean equals(final Object obj) { if (this == obj) { return true; } if (!(obj instanceof Counter)) { return false; } final Counter other = (Counter) obj; return value == other.get(); } @Override public long get() { return value; } @Override public BigInteger getBigInteger() { return BigInteger.valueOf(value); } @Override public Long getLong() { return Long.valueOf(value); } @Override public int hashCode() { return Objects.hash(value); } @Override public void increment() { value++; } @Override public String toString() { return Long.toString(value); } @Override public void reset() { value = 0L; } } /** * Counts files, directories, and sizes, as a visit proceeds, using long numbers. */ private final static class LongPathCounters extends AbstractPathCounters { /** * Constructs a new initialized instance. */ protected LongPathCounters() { super(Counters.longCounter(), Counters.longCounter(), Counters.longCounter()); } } /** * Counts nothing. */ private final static class NoopCounter implements Counter { static final NoopCounter INSTANCE = new NoopCounter(); @Override public void add(final long add) { // noop } @Override public long get() { return 0; } @Override public BigInteger getBigInteger() { return BigInteger.ZERO; } @Override public Long getLong() { return 0L; } @Override public void increment() { // noop } } /** * Counts nothing. */ private static final class NoopPathCounters extends AbstractPathCounters { static final NoopPathCounters INSTANCE = new NoopPathCounters(); /** * Constructs a new initialized instance. */ private NoopPathCounters() { super(Counters.noopCounter(), Counters.noopCounter(), Counters.noopCounter()); } } /** * Counts files, directories, and sizes, as a visit proceeds. */ public interface PathCounters { /** * Gets the byte counter. * * @return the byte counter. */ Counter getByteCounter(); /** * Gets the directory counter. * * @return the directory counter. */ Counter getDirectoryCounter(); /** * Gets the file counter. * * @return the file counter. */ Counter getFileCounter(); /** * Resets the counts to 0. */ default void reset() { // binary compat, do nothing } } /** * Returns a new BigInteger Counter. * * @return a new BigInteger Counter. */ public static Counter bigIntegerCounter() { return new BigIntegerCounter(); } /** * Returns a new BigInteger PathCounters. * * @return a new BigInteger PathCounters. */ public static PathCounters bigIntegerPathCounters() { return new BigIntegerPathCounters(); } /** * Returns a new long Counter. * * @return a new long Counter. */ public static Counter longCounter() { return new LongCounter(); } /** * Returns a new BigInteger PathCounters. * * @return a new BigInteger PathCounters. */ public static PathCounters longPathCounters() { return new LongPathCounters(); } /** * Returns the NOOP Counter. * * @return the NOOP Counter. * @since 2.9.0 */ public static Counter noopCounter() { return NoopCounter.INSTANCE; } /** * Returns the NOOP PathCounters. * * @return the NOOP PathCounters. * @since 2.9.0 */ public static PathCounters noopPathCounters() { return NoopPathCounters.INSTANCE; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/file/CountingPathVisitor.java0100644 0000000 0000000 00000012231 13612062727 031277 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.file; import java.io.IOException; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.attribute.BasicFileAttributes; import java.util.Objects; import org.apache.commons.io.file.Counters.PathCounters; import org.apache.commons.io.filefilter.TrueFileFilter; /** * Counts files, directories, and sizes, as a visit proceeds. * * @since 2.7 */ public class CountingPathVisitor extends SimplePathVisitor { static final String[] EMPTY_STRING_ARRAY = {}; /** * Creates a new instance configured with a BigInteger {@link PathCounters}. * * @return a new instance configured with a BigInteger {@link PathCounters}. */ public static CountingPathVisitor withBigIntegerCounters() { return new CountingPathVisitor(Counters.bigIntegerPathCounters()); } /** * Creates a new instance configured with a long {@link PathCounters}. * * @return a new instance configured with a long {@link PathCounters}. */ public static CountingPathVisitor withLongCounters() { return new CountingPathVisitor(Counters.longPathCounters()); } private final PathCounters pathCounters; private final PathFilter fileFilter; private final PathFilter dirFilter; /** * Constructs a new instance. * * @param pathCounter How to count path visits. */ public CountingPathVisitor(final PathCounters pathCounter) { this(pathCounter, TrueFileFilter.INSTANCE, TrueFileFilter.INSTANCE); } /** * Constructs a new instance. * * @param pathCounter How to count path visits. * @param fileFilter Filters which files to count. * @param dirFilter Filters which directories to count. * @since 2.9.0 */ public CountingPathVisitor(final PathCounters pathCounter, final PathFilter fileFilter, final PathFilter dirFilter) { this.pathCounters = Objects.requireNonNull(pathCounter, "pathCounter"); this.fileFilter = Objects.requireNonNull(fileFilter, "fileFilter"); this.dirFilter = Objects.requireNonNull(dirFilter, "dirFilter"); } @Override public boolean equals(final Object obj) { if (this == obj) { return true; } if (!(obj instanceof CountingPathVisitor)) { return false; } final CountingPathVisitor other = (CountingPathVisitor) obj; return Objects.equals(pathCounters, other.pathCounters); } /** * Gets the visitation counts. * * @return the visitation counts. */ public PathCounters getPathCounters() { return pathCounters; } @Override public int hashCode() { return Objects.hash(pathCounters); } @Override public FileVisitResult postVisitDirectory(final Path dir, final IOException exc) throws IOException { updateDirCounter(dir, exc); return FileVisitResult.CONTINUE; } @Override public FileVisitResult preVisitDirectory(final Path dir, final BasicFileAttributes attributes) throws IOException { final FileVisitResult accept = dirFilter.accept(dir, attributes); return accept != FileVisitResult.CONTINUE ? FileVisitResult.SKIP_SUBTREE : FileVisitResult.CONTINUE; } @Override public String toString() { return pathCounters.toString(); } /** * Updates the counter for visiting the given directory. * * @param dir the visited directory. * @param exc Encountered exception. * @since 2.9.0 */ protected void updateDirCounter(final Path dir, final IOException exc) { pathCounters.getDirectoryCounter().increment(); } /** * Updates the counters for visiting the given file. * * @param file the visited file. * @param attributes the visited file attributes. */ protected void updateFileCounters(final Path file, final BasicFileAttributes attributes) { pathCounters.getFileCounter().increment(); pathCounters.getByteCounter().add(attributes.size()); } @Override public FileVisitResult visitFile(final Path file, final BasicFileAttributes attributes) throws IOException { if (Files.exists(file) && fileFilter.accept(file, attributes) == FileVisitResult.CONTINUE) { updateFileCounters(file, attributes); } return FileVisitResult.CONTINUE; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/file/DeleteOption.java0100644 0000000 0000000 00000002110 13612062727 027702 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.file; /** * An object that configures how to delete a file. * *

* The {@link StandardDeleteOption} enumeration type defines our standard options. *

* * @see StandardDeleteOption * @since 2.8.0 */ public interface DeleteOption { // empty } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/file/DeletingPathVisitor.java0100644 0000000 0000000 00000014561 13612062727 031254 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.file; import java.io.IOException; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.LinkOption; import java.nio.file.NoSuchFileException; import java.nio.file.Path; import java.nio.file.attribute.BasicFileAttributes; import java.util.Arrays; import java.util.Objects; import org.apache.commons.io.file.Counters.PathCounters; /** * Deletes files and directories as a visit proceeds. * * @since 2.7 */ public class DeletingPathVisitor extends CountingPathVisitor { /** * Creates a new instance configured with a BigInteger {@link PathCounters}. * * @return a new instance configured with a BigInteger {@link PathCounters}. */ public static DeletingPathVisitor withBigIntegerCounters() { return new DeletingPathVisitor(Counters.bigIntegerPathCounters()); } /** * Creates a new instance configured with a long {@link PathCounters}. * * @return a new instance configured with a long {@link PathCounters}. */ public static DeletingPathVisitor withLongCounters() { return new DeletingPathVisitor(Counters.longPathCounters()); } private final String[] skip; private final boolean overrideReadOnly; private final LinkOption[] linkOptions; /** * Constructs a new visitor that deletes files except for the files and directories explicitly given. * * @param pathCounter How to count visits. * @param deleteOption How deletion is handled. * @param skip The files to skip deleting. * @since 2.8.0 */ public DeletingPathVisitor(final PathCounters pathCounter, final DeleteOption[] deleteOption, final String... skip) { this(pathCounter, PathUtils.NOFOLLOW_LINK_OPTION_ARRAY, deleteOption, skip); } /** * Constructs a new visitor that deletes files except for the files and directories explicitly given. * * @param pathCounter How to count visits. * @param linkOptions How symbolic links are handled. * @param deleteOption How deletion is handled. * @param skip The files to skip deleting. * @since 2.9.0 */ public DeletingPathVisitor(final PathCounters pathCounter, final LinkOption[] linkOptions, final DeleteOption[] deleteOption, final String... skip) { super(pathCounter); final String[] temp = skip != null ? skip.clone() : EMPTY_STRING_ARRAY; Arrays.sort(temp); this.skip = temp; this.overrideReadOnly = StandardDeleteOption.overrideReadOnly(deleteOption); // TODO Files.deleteIfExists() never follows links, so use LinkOption.NOFOLLOW_LINKS in other calls to Files. this.linkOptions = linkOptions == null ? PathUtils.NOFOLLOW_LINK_OPTION_ARRAY : linkOptions.clone(); } /** * Constructs a new visitor that deletes files except for the files and directories explicitly given. * * @param pathCounter How to count visits. * * @param skip The files to skip deleting. */ public DeletingPathVisitor(final PathCounters pathCounter, final String... skip) { this(pathCounter, PathUtils.EMPTY_DELETE_OPTION_ARRAY, skip); } /** * Returns true to process the given path, false if not. * * @param path the path to test. * @return true to process the given path, false if not. */ private boolean accept(final Path path) { return Arrays.binarySearch(skip, Objects.toString(path.getFileName(), null)) < 0; } @Override public boolean equals(final Object obj) { if (this == obj) { return true; } if (!super.equals(obj)) { return false; } if (getClass() != obj.getClass()) { return false; } final DeletingPathVisitor other = (DeletingPathVisitor) obj; return overrideReadOnly == other.overrideReadOnly && Arrays.equals(skip, other.skip); } @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); result = prime * result + Arrays.hashCode(skip); result = prime * result + Objects.hash(overrideReadOnly); return result; } @Override public FileVisitResult postVisitDirectory(final Path dir, final IOException exc) throws IOException { if (PathUtils.isEmptyDirectory(dir)) { Files.deleteIfExists(dir); } return super.postVisitDirectory(dir, exc); } @Override public FileVisitResult preVisitDirectory(final Path dir, final BasicFileAttributes attrs) throws IOException { super.preVisitDirectory(dir, attrs); return accept(dir) ? FileVisitResult.CONTINUE : FileVisitResult.SKIP_SUBTREE; } @Override public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) throws IOException { if (accept(file)) { // delete files and valid links, respecting linkOptions if (Files.exists(file, linkOptions)) { if (overrideReadOnly) { PathUtils.setReadOnly(file, false, linkOptions); } Files.deleteIfExists(file); } // invalid links will survive previous delete, different approach needed: if (Files.isSymbolicLink(file)) { try { // deleteIfExists does not work for this case Files.delete(file); } catch (final NoSuchFileException e) { // ignore } } } updateFileCounters(file, attrs); return FileVisitResult.CONTINUE; } }commons-io-2.11.0-src/src/main/java/org/apache/commons/io/file/DirectoryStreamFilter.java0100644 0000000 0000000 00000004131 13612062727 031602 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.file; import java.io.IOException; import java.nio.file.DirectoryStream; import java.nio.file.FileVisitResult; import java.nio.file.Path; import java.util.Objects; /** * A {@link java.nio.file.DirectoryStream.Filter DirectoryStream.Filter} that delegates to a {@link PathFilter}. *

* You pass this filter to {@link java.nio.file.Files#newDirectoryStream(Path, DirectoryStream.Filter) * Files#newDirectoryStream(Path, DirectoryStream.Filter)}. *

* * @since 2.9.0 */ public class DirectoryStreamFilter implements DirectoryStream.Filter { private final PathFilter pathFilter; /** * Constructs a new instance for the given path filter. * * @param pathFilter How to filter paths. */ public DirectoryStreamFilter(final PathFilter pathFilter) { // TODO Instead of NPE, we could map null to FalseFileFilter. this.pathFilter = Objects.requireNonNull(pathFilter, "pathFilter"); } @Override public boolean accept(final Path path) throws IOException { return pathFilter.accept(path, PathUtils.readBasicFileAttributes(path)) == FileVisitResult.CONTINUE; } /** * Gets the path filter. * * @return the path filter. */ public PathFilter getPathFilter() { return pathFilter; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/file/NoopPathVisitor.java0100644 0000000 0000000 00000002061 13612062727 030424 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.file; /** * A noop path visitor. * * @since 2.9.0 */ public class NoopPathVisitor extends SimplePathVisitor { /** * The singleton instance. */ public static final NoopPathVisitor INSTANCE = new NoopPathVisitor(); } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/file/PathFilter.java0100644 0000000 0000000 00000002543 13612062727 027363 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.file; import java.nio.file.FileVisitResult; import java.nio.file.Path; import java.nio.file.attribute.BasicFileAttributes; /** * A filter for {@link Path}s. * * @since 2.9.0 */ @FunctionalInterface public interface PathFilter { /** * Tests whether or not to include the specified Path in a result. * * @param path The Path to test. * @param attributes the file's basic attributes (TODO may be null). * @return a FileVisitResult */ FileVisitResult accept(Path path, BasicFileAttributes attributes); } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/file/PathUtils.java0100644 0000000 0000000 00000131325 13612062727 027237 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.file; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.UncheckedIOException; import java.net.URI; import java.net.URL; import java.nio.file.CopyOption; import java.nio.file.DirectoryStream; import java.nio.file.FileVisitOption; import java.nio.file.FileVisitResult; import java.nio.file.FileVisitor; import java.nio.file.Files; import java.nio.file.LinkOption; import java.nio.file.NoSuchFileException; import java.nio.file.NotDirectoryException; import java.nio.file.OpenOption; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.attribute.AclEntry; import java.nio.file.attribute.AclFileAttributeView; import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.DosFileAttributeView; import java.nio.file.attribute.FileAttribute; import java.nio.file.attribute.PosixFileAttributeView; import java.nio.file.attribute.PosixFileAttributes; import java.nio.file.attribute.PosixFilePermission; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.EnumSet; import java.util.List; import java.util.Objects; import java.util.Set; import java.util.stream.Collector; import java.util.stream.Collectors; import java.util.stream.Stream; import org.apache.commons.io.IOExceptionList; import org.apache.commons.io.IOUtils; import org.apache.commons.io.file.Counters.PathCounters; import org.apache.commons.io.filefilter.IOFileFilter; /** * NIO Path utilities. * * @since 2.7 */ public final class PathUtils { /** * Private worker/holder that computes and tracks relative path names and their equality. We reuse the sorted * relative lists when comparing directories. */ private static class RelativeSortedPaths { final boolean equals; // final List relativeDirList1; // might need later? // final List relativeDirList2; // might need later? final List relativeFileList1; final List relativeFileList2; /** * Constructs and initializes a new instance by accumulating directory and file info. * * @param dir1 First directory to compare. * @param dir2 Seconds directory to compare. * @param maxDepth See {@link Files#walkFileTree(Path,Set,int,FileVisitor)}. * @param linkOptions Options indicating how symbolic links are handled. * @param fileVisitOptions See {@link Files#walkFileTree(Path,Set,int,FileVisitor)}. * @throws IOException if an I/O error is thrown by a visitor method. */ private RelativeSortedPaths(final Path dir1, final Path dir2, final int maxDepth, final LinkOption[] linkOptions, final FileVisitOption[] fileVisitOptions) throws IOException { final List tmpRelativeDirList1; final List tmpRelativeDirList2; List tmpRelativeFileList1 = null; List tmpRelativeFileList2 = null; if (dir1 == null && dir2 == null) { equals = true; } else if (dir1 == null ^ dir2 == null) { equals = false; } else { final boolean parentDirNotExists1 = Files.notExists(dir1, linkOptions); final boolean parentDirNotExists2 = Files.notExists(dir2, linkOptions); if (parentDirNotExists1 || parentDirNotExists2) { equals = parentDirNotExists1 && parentDirNotExists2; } else { final AccumulatorPathVisitor visitor1 = accumulate(dir1, maxDepth, fileVisitOptions); final AccumulatorPathVisitor visitor2 = accumulate(dir2, maxDepth, fileVisitOptions); if (visitor1.getDirList().size() != visitor2.getDirList().size() || visitor1.getFileList().size() != visitor2.getFileList().size()) { equals = false; } else { tmpRelativeDirList1 = visitor1.relativizeDirectories(dir1, true, null); tmpRelativeDirList2 = visitor2.relativizeDirectories(dir2, true, null); if (!tmpRelativeDirList1.equals(tmpRelativeDirList2)) { equals = false; } else { tmpRelativeFileList1 = visitor1.relativizeFiles(dir1, true, null); tmpRelativeFileList2 = visitor2.relativizeFiles(dir2, true, null); equals = tmpRelativeFileList1.equals(tmpRelativeFileList2); } } } } // relativeDirList1 = tmpRelativeDirList1; // relativeDirList2 = tmpRelativeDirList2; relativeFileList1 = tmpRelativeFileList1; relativeFileList2 = tmpRelativeFileList2; } } /** * Empty {@link CopyOption} array. * * @since 2.8.0 */ public static final CopyOption[] EMPTY_COPY_OPTIONS = {}; /** * Empty {@link LinkOption} array. * * @since 2.8.0 */ public static final DeleteOption[] EMPTY_DELETE_OPTION_ARRAY = {}; /** * Empty {@link FileVisitOption} array. */ public static final FileVisitOption[] EMPTY_FILE_VISIT_OPTION_ARRAY = {}; /** * Empty {@link LinkOption} array. */ public static final LinkOption[] EMPTY_LINK_OPTION_ARRAY = {}; /** * {@link LinkOption} array for {@link LinkOption#NOFOLLOW_LINKS}. * * @since 2.9.0 */ public static final LinkOption[] NOFOLLOW_LINK_OPTION_ARRAY = {LinkOption.NOFOLLOW_LINKS}; /** * Empty {@link OpenOption} array. */ public static final OpenOption[] EMPTY_OPEN_OPTION_ARRAY = {}; /** * Empty {@link Path} array. * * @since 2.9.0 */ public static final Path[] EMPTY_PATH_ARRAY = {}; /** * Accumulates file tree information in a {@link AccumulatorPathVisitor}. * * @param directory The directory to accumulate information. * @param maxDepth See {@link Files#walkFileTree(Path,Set,int,FileVisitor)}. * @param fileVisitOptions See {@link Files#walkFileTree(Path,Set,int,FileVisitor)}. * @throws IOException if an I/O error is thrown by a visitor method. * @return file tree information. */ private static AccumulatorPathVisitor accumulate(final Path directory, final int maxDepth, final FileVisitOption[] fileVisitOptions) throws IOException { return visitFileTree(AccumulatorPathVisitor.withLongCounters(), directory, toFileVisitOptionSet(fileVisitOptions), maxDepth); } /** * Cleans a directory including sub-directories without deleting directories. * * @param directory directory to clean. * @return The visitation path counters. * @throws IOException if an I/O error is thrown by a visitor method. */ public static PathCounters cleanDirectory(final Path directory) throws IOException { return cleanDirectory(directory, EMPTY_DELETE_OPTION_ARRAY); } /** * Cleans a directory including sub-directories without deleting directories. * * @param directory directory to clean. * @param deleteOptions How to handle deletion. * @return The visitation path counters. * @throws IOException if an I/O error is thrown by a visitor method. * @since 2.8.0 */ public static PathCounters cleanDirectory(final Path directory, final DeleteOption... deleteOptions) throws IOException { return visitFileTree(new CleaningPathVisitor(Counters.longPathCounters(), deleteOptions), directory) .getPathCounters(); } /** * Copies a directory to another directory. * * @param sourceDirectory The source directory. * @param targetDirectory The target directory. * @param copyOptions Specifies how the copying should be done. * @return The visitation path counters. * @throws IOException if an I/O error is thrown by a visitor method. */ public static PathCounters copyDirectory(final Path sourceDirectory, final Path targetDirectory, final CopyOption... copyOptions) throws IOException { final Path absoluteSource = sourceDirectory.toAbsolutePath(); return visitFileTree( new CopyDirectoryVisitor(Counters.longPathCounters(), absoluteSource, targetDirectory, copyOptions), absoluteSource).getPathCounters(); } /** * Copies a URL to a directory. * * @param sourceFile The source URL. * @param targetFile The target file. * @param copyOptions Specifies how the copying should be done. * @return The target file * @throws IOException if an I/O error occurs. * @see Files#copy(InputStream, Path, CopyOption...) */ public static Path copyFile(final URL sourceFile, final Path targetFile, final CopyOption... copyOptions) throws IOException { try (final InputStream inputStream = sourceFile.openStream()) { Files.copy(inputStream, targetFile, copyOptions); return targetFile; } } /** * Copies a file to a directory. * * @param sourceFile The source file. * @param targetDirectory The target directory. * @param copyOptions Specifies how the copying should be done. * @return The target file * @throws IOException if an I/O error occurs. * @see Files#copy(Path, Path, CopyOption...) */ public static Path copyFileToDirectory(final Path sourceFile, final Path targetDirectory, final CopyOption... copyOptions) throws IOException { return Files.copy(sourceFile, targetDirectory.resolve(sourceFile.getFileName()), copyOptions); } /** * Copies a URL to a directory. * * @param sourceFile The source URL. * @param targetDirectory The target directory. * @param copyOptions Specifies how the copying should be done. * @return The target file * @throws IOException if an I/O error occurs. * @see Files#copy(InputStream, Path, CopyOption...) */ public static Path copyFileToDirectory(final URL sourceFile, final Path targetDirectory, final CopyOption... copyOptions) throws IOException { try (final InputStream inputStream = sourceFile.openStream()) { Files.copy(inputStream, targetDirectory.resolve(sourceFile.getFile()), copyOptions); return targetDirectory; } } /** * Counts aspects of a directory including sub-directories. * * @param directory directory to delete. * @return The visitor used to count the given directory. * @throws IOException if an I/O error is thrown by a visitor method. */ public static PathCounters countDirectory(final Path directory) throws IOException { return visitFileTree(new CountingPathVisitor(Counters.longPathCounters()), directory).getPathCounters(); } /** * Creates the parent directories for the given {@code path}. * * @param path The path to a file (or directory). * @param attrs An optional list of file attributes to set atomically when creating the directories. * @return The Path for the {@code path}'s parent directory or null if the given path has no parent. * @throws IOException if an I/O error occurs. * @since 2.9.0 */ public static Path createParentDirectories(final Path path, final FileAttribute... attrs) throws IOException { final Path parent = path.getParent(); if (parent == null) { return null; } return Files.createDirectories(parent, attrs); } /** * Gets the current directory. * * @return the current directory. * * @since 2.9.0 */ public static Path current() { return Paths.get(""); } /** * Deletes a file or directory. If the path is a directory, delete it and all sub-directories. *

* The difference between File.delete() and this method are: *

*
    *
  • A directory to delete does not have to be empty.
  • *
  • You get exceptions when a file or directory cannot be deleted; {@link java.io.File#delete()} returns a * boolean. *
* * @param path file or directory to delete, must not be {@code null} * @return The visitor used to delete the given directory. * @throws NullPointerException if the directory is {@code null} * @throws IOException if an I/O error is thrown by a visitor method or if an I/O error occurs. */ public static PathCounters delete(final Path path) throws IOException { return delete(path, EMPTY_DELETE_OPTION_ARRAY); } /** * Deletes a file or directory. If the path is a directory, delete it and all sub-directories. *

* The difference between File.delete() and this method are: *

*
    *
  • A directory to delete does not have to be empty.
  • *
  • You get exceptions when a file or directory cannot be deleted; {@link java.io.File#delete()} returns a * boolean. *
* * @param path file or directory to delete, must not be {@code null} * @param deleteOptions How to handle deletion. * @return The visitor used to delete the given directory. * @throws NullPointerException if the directory is {@code null} * @throws IOException if an I/O error is thrown by a visitor method or if an I/O error occurs. * @since 2.8.0 */ public static PathCounters delete(final Path path, final DeleteOption... deleteOptions) throws IOException { // File deletion through Files deletes links, not targets, so use LinkOption.NOFOLLOW_LINKS. return Files.isDirectory(path, LinkOption.NOFOLLOW_LINKS) ? deleteDirectory(path, deleteOptions) : deleteFile(path, deleteOptions); } /** * Deletes a file or directory. If the path is a directory, delete it and all sub-directories. *

* The difference between File.delete() and this method are: *

*
    *
  • A directory to delete does not have to be empty.
  • *
  • You get exceptions when a file or directory cannot be deleted; {@link java.io.File#delete()} returns a * boolean. *
* * @param path file or directory to delete, must not be {@code null} * @param linkOptions How to handle symbolic links. * @param deleteOptions How to handle deletion. * @return The visitor used to delete the given directory. * @throws NullPointerException if the directory is {@code null} * @throws IOException if an I/O error is thrown by a visitor method or if an I/O error occurs. * @since 2.9.0 */ public static PathCounters delete(final Path path, final LinkOption[] linkOptions, final DeleteOption... deleteOptions) throws IOException { // File deletion through Files deletes links, not targets, so use LinkOption.NOFOLLOW_LINKS. return Files.isDirectory(path, linkOptions) ? deleteDirectory(path, linkOptions, deleteOptions) : deleteFile(path, linkOptions, deleteOptions); } /** * Deletes a directory including sub-directories. * * @param directory directory to delete. * @return The visitor used to delete the given directory. * @throws IOException if an I/O error is thrown by a visitor method. */ public static PathCounters deleteDirectory(final Path directory) throws IOException { return deleteDirectory(directory, EMPTY_DELETE_OPTION_ARRAY); } /** * Deletes a directory including sub-directories. * * @param directory directory to delete. * @param deleteOptions How to handle deletion. * @return The visitor used to delete the given directory. * @throws IOException if an I/O error is thrown by a visitor method. * @since 2.8.0 */ public static PathCounters deleteDirectory(final Path directory, final DeleteOption... deleteOptions) throws IOException { return visitFileTree( new DeletingPathVisitor(Counters.longPathCounters(), PathUtils.NOFOLLOW_LINK_OPTION_ARRAY, deleteOptions), directory).getPathCounters(); } /** * Deletes a directory including sub-directories. * * @param directory directory to delete. * @param linkOptions How to handle symbolic links. * @param deleteOptions How to handle deletion. * @return The visitor used to delete the given directory. * @throws IOException if an I/O error is thrown by a visitor method. * @since 2.9.0 */ public static PathCounters deleteDirectory(final Path directory, final LinkOption[] linkOptions, final DeleteOption... deleteOptions) throws IOException { return visitFileTree(new DeletingPathVisitor(Counters.longPathCounters(), linkOptions, deleteOptions), directory).getPathCounters(); } /** * Deletes the given file. * * @param file The file to delete. * @return A visitor with path counts set to 1 file, 0 directories, and the size of the deleted file. * @throws IOException if an I/O error occurs. * @throws NoSuchFileException if the file is a directory. */ public static PathCounters deleteFile(final Path file) throws IOException { return deleteFile(file, EMPTY_DELETE_OPTION_ARRAY); } /** * Deletes the given file. * * @param file The file to delete. * @param deleteOptions How to handle deletion. * @return A visitor with path counts set to 1 file, 0 directories, and the size of the deleted file. * @throws IOException if an I/O error occurs. * @throws NoSuchFileException if the file is a directory. * @since 2.8.0 */ public static PathCounters deleteFile(final Path file, final DeleteOption... deleteOptions) throws IOException { // Files.deleteIfExists() never follows links, so use LinkOption.NOFOLLOW_LINKS in other calls to Files. return deleteFile(file, NOFOLLOW_LINK_OPTION_ARRAY, deleteOptions); } /** * Deletes the given file. * * @param file The file to delete. * @param linkOptions How to handle symbolic links. * @param deleteOptions How to handle deletion. * @return A visitor with path counts set to 1 file, 0 directories, and the size of the deleted file. * @throws IOException if an I/O error occurs. * @throws NoSuchFileException if the file is a directory. * @since 2.9.0 */ public static PathCounters deleteFile(final Path file, final LinkOption[] linkOptions, final DeleteOption... deleteOptions) throws NoSuchFileException, IOException { if (Files.isDirectory(file, linkOptions)) { throw new NoSuchFileException(file.toString()); } final PathCounters pathCounts = Counters.longPathCounters(); final boolean exists = Files.exists(file, linkOptions); final long size = exists && !Files.isSymbolicLink(file) ? Files.size(file) : 0; if (overrideReadOnly(deleteOptions) && exists) { setReadOnly(file, false, linkOptions); } if (Files.deleteIfExists(file)) { pathCounts.getFileCounter().increment(); pathCounts.getByteCounter().add(size); } return pathCounts; } /** * Compares the file sets of two Paths to determine if they are equal or not while considering file contents. The * comparison includes all files in all sub-directories. * * @param path1 The first directory. * @param path2 The second directory. * @return Whether the two directories contain the same files while considering file contents. * @throws IOException if an I/O error is thrown by a visitor method */ public static boolean directoryAndFileContentEquals(final Path path1, final Path path2) throws IOException { return directoryAndFileContentEquals(path1, path2, EMPTY_LINK_OPTION_ARRAY, EMPTY_OPEN_OPTION_ARRAY, EMPTY_FILE_VISIT_OPTION_ARRAY); } /** * Compares the file sets of two Paths to determine if they are equal or not while considering file contents. The * comparison includes all files in all sub-directories. * * @param path1 The first directory. * @param path2 The second directory. * @param linkOptions options to follow links. * @param openOptions options to open files. * @param fileVisitOption options to configure traversal. * @return Whether the two directories contain the same files while considering file contents. * @throws IOException if an I/O error is thrown by a visitor method */ public static boolean directoryAndFileContentEquals(final Path path1, final Path path2, final LinkOption[] linkOptions, final OpenOption[] openOptions, final FileVisitOption[] fileVisitOption) throws IOException { // First walk both file trees and gather normalized paths. if (path1 == null && path2 == null) { return true; } if (path1 == null || path2 == null) { return false; } if (Files.notExists(path1) && Files.notExists(path2)) { return true; } final RelativeSortedPaths relativeSortedPaths = new RelativeSortedPaths(path1, path2, Integer.MAX_VALUE, linkOptions, fileVisitOption); // If the normalized path names and counts are not the same, no need to compare contents. if (!relativeSortedPaths.equals) { return false; } // Both visitors contain the same normalized paths, we can compare file contents. final List fileList1 = relativeSortedPaths.relativeFileList1; final List fileList2 = relativeSortedPaths.relativeFileList2; for (final Path path : fileList1) { final int binarySearch = Collections.binarySearch(fileList2, path); if (binarySearch <= -1) { throw new IllegalStateException("Unexpected mismatch."); } if (!fileContentEquals(path1.resolve(path), path2.resolve(path), linkOptions, openOptions)) { return false; } } return true; } /** * Compares the file sets of two Paths to determine if they are equal or not without considering file contents. The * comparison includes all files in all sub-directories. * * @param path1 The first directory. * @param path2 The second directory. * @return Whether the two directories contain the same files without considering file contents. * @throws IOException if an I/O error is thrown by a visitor method */ public static boolean directoryContentEquals(final Path path1, final Path path2) throws IOException { return directoryContentEquals(path1, path2, Integer.MAX_VALUE, EMPTY_LINK_OPTION_ARRAY, EMPTY_FILE_VISIT_OPTION_ARRAY); } /** * Compares the file sets of two Paths to determine if they are equal or not without considering file contents. The * comparison includes all files in all sub-directories. * * @param path1 The first directory. * @param path2 The second directory. * @param maxDepth See {@link Files#walkFileTree(Path,Set,int,FileVisitor)}. * @param linkOptions options to follow links. * @param fileVisitOptions options to configure the traversal * @return Whether the two directories contain the same files without considering file contents. * @throws IOException if an I/O error is thrown by a visitor method */ public static boolean directoryContentEquals(final Path path1, final Path path2, final int maxDepth, final LinkOption[] linkOptions, final FileVisitOption[] fileVisitOptions) throws IOException { return new RelativeSortedPaths(path1, path2, maxDepth, linkOptions, fileVisitOptions).equals; } /** * Compares the file contents of two Paths to determine if they are equal or not. *

* File content is accessed through {@link Files#newInputStream(Path,OpenOption...)}. *

* * @param path1 the first stream. * @param path2 the second stream. * @return true if the content of the streams are equal or they both don't exist, false otherwise. * @throws NullPointerException if either input is null. * @throws IOException if an I/O error occurs. * @see org.apache.commons.io.FileUtils#contentEquals(java.io.File, java.io.File) */ public static boolean fileContentEquals(final Path path1, final Path path2) throws IOException { return fileContentEquals(path1, path2, EMPTY_LINK_OPTION_ARRAY, EMPTY_OPEN_OPTION_ARRAY); } /** * Compares the file contents of two Paths to determine if they are equal or not. *

* File content is accessed through {@link Files#newInputStream(Path,OpenOption...)}. *

* * @param path1 the first stream. * @param path2 the second stream. * @param linkOptions options specifying how files are followed. * @param openOptions options specifying how files are opened. * @return true if the content of the streams are equal or they both don't exist, false otherwise. * @throws NullPointerException if either input is null. * @throws IOException if an I/O error occurs. * @see org.apache.commons.io.FileUtils#contentEquals(java.io.File, java.io.File) */ public static boolean fileContentEquals(final Path path1, final Path path2, final LinkOption[] linkOptions, final OpenOption[] openOptions) throws IOException { if (path1 == null && path2 == null) { return true; } if (path1 == null || path2 == null) { return false; } final Path nPath1 = path1.normalize(); final Path nPath2 = path2.normalize(); final boolean path1Exists = Files.exists(nPath1, linkOptions); if (path1Exists != Files.exists(nPath2, linkOptions)) { return false; } if (!path1Exists) { // Two not existing files are equal? // Same as FileUtils return true; } if (Files.isDirectory(nPath1, linkOptions)) { // don't compare directory contents. throw new IOException("Can't compare directories, only files: " + nPath1); } if (Files.isDirectory(nPath2, linkOptions)) { // don't compare directory contents. throw new IOException("Can't compare directories, only files: " + nPath2); } if (Files.size(nPath1) != Files.size(nPath2)) { // lengths differ, cannot be equal return false; } if (path1.equals(path2)) { // same file return true; } try (final InputStream inputStream1 = Files.newInputStream(nPath1, openOptions); final InputStream inputStream2 = Files.newInputStream(nPath2, openOptions)) { return IOUtils.contentEquals(inputStream1, inputStream2); } } /** *

* Applies an {@link IOFileFilter} to the provided {@link File} objects. The resulting array is a subset of the * original file list that matches the provided filter. *

* *

* The {@link Set} returned by this method is not guaranteed to be thread safe. *

* *
     * Set<File> allFiles = ...
     * Set<File> javaFiles = FileFilterUtils.filterSet(allFiles,
     *     FileFilterUtils.suffixFileFilter(".java"));
     * 
* * @param filter the filter to apply to the set of files. * @param paths the array of files to apply the filter to. * * @return a subset of {@code files} that is accepted by the file filter. * @throws IllegalArgumentException if the filter is {@code null} or {@code files} contains a {@code null} * value. * * @since 2.9.0 */ public static Path[] filter(final PathFilter filter, final Path... paths) { Objects.requireNonNull(filter, "filter"); if (paths == null) { return EMPTY_PATH_ARRAY; } return filterPaths(filter, Stream.of(paths), Collectors.toList()).toArray(EMPTY_PATH_ARRAY); } private static R filterPaths(final PathFilter filter, final Stream stream, final Collector collector) { Objects.requireNonNull(filter, "filter"); Objects.requireNonNull(collector, "collector"); if (stream == null) { return Stream.empty().collect(collector); } return stream.filter(p -> { try { return p != null && filter.accept(p, readBasicFileAttributes(p)) == FileVisitResult.CONTINUE; } catch (final IOException e) { return false; } }).collect(collector); } /** * Reads the access control list from a file attribute view. * * @param sourcePath the path to the file. * @return a file attribute view of the specified type, or null if the attribute view type is not available. * @throws IOException if an I/O error occurs. * @since 2.8.0 */ public static List getAclEntryList(final Path sourcePath) throws IOException { final AclFileAttributeView fileAttributeView = Files.getFileAttributeView(sourcePath, AclFileAttributeView.class); return fileAttributeView == null ? null : fileAttributeView.getAcl(); } /** * Tests whether the specified {@code Path} is a directory or not. Implemented as a * null-safe delegate to {@code Files.isDirectory(Path path, LinkOption... options)}. * * @param path the path to the file. * @param options options indicating how symbolic links are handled * @return {@code true} if the file is a directory; {@code false} if * the path is null, the file does not exist, is not a directory, or it cannot * be determined if the file is a directory or not. * @throws SecurityException In the case of the default provider, and a security manager is installed, the * {@link SecurityManager#checkRead(String) checkRead} method is invoked to check read * access to the directory. * @since 2.9.0 */ public static boolean isDirectory(final Path path, final LinkOption... options) { return path != null && Files.isDirectory(path, options); } /** * Tests whether the given file or directory is empty. * * @param path the file or directory to query. * @return whether the file or directory is empty. * @throws IOException if an I/O error occurs. */ public static boolean isEmpty(final Path path) throws IOException { return Files.isDirectory(path) ? isEmptyDirectory(path) : isEmptyFile(path); } /** * Tests whether the directory is empty. * * @param directory the directory to query. * @return whether the directory is empty. * @throws NotDirectoryException if the file could not otherwise be opened because it is not a directory * (optional specific exception). * @throws IOException if an I/O error occurs. * @throws SecurityException In the case of the default provider, and a security manager is installed, the * {@link SecurityManager#checkRead(String) checkRead} method is invoked to check read * access to the directory. */ public static boolean isEmptyDirectory(final Path directory) throws IOException { try (DirectoryStream directoryStream = Files.newDirectoryStream(directory)) { return !directoryStream.iterator().hasNext(); } } /** * Tests whether the given file is empty. * * @param file the file to query. * @return whether the file is empty. * @throws IOException if an I/O error occurs. * @throws SecurityException In the case of the default provider, and a security manager is installed, its * {@link SecurityManager#checkRead(String) checkRead} method denies read access to the * file. */ public static boolean isEmptyFile(final Path file) throws IOException { return Files.size(file) <= 0; } /** * Tests if the specified {@code Path} is newer than the specified time reference. * * @param file the {@code Path} of which the modification date must be compared * @param timeMillis the time reference measured in milliseconds since the epoch (00:00:00 GMT, January 1, 1970) * @param options options indicating how symbolic links are handled * @return true if the {@code Path} exists and * has been modified after the given time reference. * @return true if the {@code Path} exists and has been modified after the given time reference. * @throws IOException if an I/O error occurs. * @throws NullPointerException if the file is {@code null} * @since 2.9.0 */ public static boolean isNewer(final Path file, final long timeMillis, final LinkOption... options) throws IOException { Objects.requireNonNull(file, "file"); if (Files.notExists(file)) { return false; } return Files.getLastModifiedTime(file, options).toMillis() > timeMillis; } /** * Tests whether the specified {@code Path} is a regular file or not. Implemented as a * null-safe delegate to {@code Files.isRegularFile(Path path, LinkOption... options)}. * * @param path the path to the file. * @param options options indicating how symbolic links are handled * @return {@code true} if the file is a regular file; {@code false} if * the path is null, the file does not exist, is not a directory, or it cannot * be determined if the file is a regular file or not. * @throws SecurityException In the case of the default provider, and a security manager is installed, the * {@link SecurityManager#checkRead(String) checkRead} method is invoked to check read * access to the directory. * @since 2.9.0 */ public static boolean isRegularFile(final Path path, final LinkOption... options) { return path != null && Files.isRegularFile(path, options); } /** * Creates a new DirectoryStream for Paths rooted at the given directory. * * @param dir the path to the directory to stream. * @param pathFilter the directory stream filter. * @return a new instance. * @throws IOException if an I/O error occurs. */ public static DirectoryStream newDirectoryStream(final Path dir, final PathFilter pathFilter) throws IOException { return Files.newDirectoryStream(dir, new DirectoryStreamFilter(pathFilter)); } /** * Returns true if the given options contain {@link StandardDeleteOption#OVERRIDE_READ_ONLY}. * * @param deleteOptions the array to test * @return true if the given options contain {@link StandardDeleteOption#OVERRIDE_READ_ONLY}. */ private static boolean overrideReadOnly(final DeleteOption... deleteOptions) { if (deleteOptions == null) { return false; } return Stream.of(deleteOptions).anyMatch(e -> e == StandardDeleteOption.OVERRIDE_READ_ONLY); } /** * Shorthand for {@code Files.readAttributes(path, BasicFileAttributes.class)} * * @param path the path to read. * @return the path attributes. * @throws IOException if an I/O error occurs. * @since 2.9.0 */ public static BasicFileAttributes readBasicFileAttributes(final Path path) throws IOException { return Files.readAttributes(path, BasicFileAttributes.class); } /** * Shorthand for {@code Files.readAttributes(path, BasicFileAttributes.class)} while wrapping {@link IOException} * as {@link UncheckedIOException}. * * @param path the path to read. * @return the path attributes. * @throws UncheckedIOException if an I/O error occurs * @since 2.9.0 */ public static BasicFileAttributes readBasicFileAttributesUnchecked(final Path path) { try { return readBasicFileAttributes(path); } catch (final IOException e) { throw new UncheckedIOException(e); } } /** * Relativizes all files in the given {@code collection} against a {@code parent}. * * @param collection The collection of paths to relativize. * @param parent relativizes against this parent path. * @param sort Whether to sort the result. * @param comparator How to sort. * @return A collection of relativized paths, optionally sorted. */ static List relativize(final Collection collection, final Path parent, final boolean sort, final Comparator comparator) { Stream stream = collection.stream().map(parent::relativize); if (sort) { stream = comparator == null ? stream.sorted() : stream.sorted(comparator); } return stream.collect(Collectors.toList()); } /** * Sets the given Path to the {@code readOnly} value. *

* This behavior is OS dependent. *

* * @param path The path to set. * @param readOnly true for read-only, false for not read-only. * @param linkOptions options indicating how symbolic links are handled. * @return The given path. * @throws IOException if an I/O error occurs. * @since 2.8.0 */ public static Path setReadOnly(final Path path, final boolean readOnly, final LinkOption... linkOptions) throws IOException { final List causeList = new ArrayList<>(2); final DosFileAttributeView fileAttributeView = Files.getFileAttributeView(path, DosFileAttributeView.class, linkOptions); if (fileAttributeView != null) { try { fileAttributeView.setReadOnly(readOnly); return path; } catch (final IOException e) { // ignore for now, retry with PosixFileAttributeView causeList.add(e); } } final PosixFileAttributeView posixFileAttributeView = Files.getFileAttributeView(path, PosixFileAttributeView.class, linkOptions); if (posixFileAttributeView != null) { // Works on Windows but not on Ubuntu: // Files.setAttribute(path, "unix:readonly", readOnly, options); // java.lang.IllegalArgumentException: 'unix:readonly' not recognized final PosixFileAttributes readAttributes = posixFileAttributeView.readAttributes(); final Set permissions = readAttributes.permissions(); permissions.remove(PosixFilePermission.OWNER_WRITE); permissions.remove(PosixFilePermission.GROUP_WRITE); permissions.remove(PosixFilePermission.OTHERS_WRITE); try { return Files.setPosixFilePermissions(path, permissions); } catch (final IOException e) { causeList.add(e); } } if (!causeList.isEmpty()) { throw new IOExceptionList(path.toString(), causeList); } throw new IOException( String.format("No DosFileAttributeView or PosixFileAttributeView for '%s' (linkOptions=%s)", path, Arrays.toString(linkOptions))); } /** * Converts an array of {@link FileVisitOption} to a {@link Set}. * * @param fileVisitOptions input array. * @return a new Set. */ static Set toFileVisitOptionSet(final FileVisitOption... fileVisitOptions) { return fileVisitOptions == null ? EnumSet.noneOf(FileVisitOption.class) : Stream.of(fileVisitOptions).collect(Collectors.toSet()); } /** * Performs {@link Files#walkFileTree(Path,FileVisitor)} and returns the given visitor. * * Note that {@link Files#walkFileTree(Path,FileVisitor)} returns the given path. * * @param visitor See {@link Files#walkFileTree(Path,FileVisitor)}. * @param directory See {@link Files#walkFileTree(Path,FileVisitor)}. * @param See {@link Files#walkFileTree(Path,FileVisitor)}. * @return the given visitor. * * @throws IOException if an I/O error is thrown by a visitor method */ public static > T visitFileTree(final T visitor, final Path directory) throws IOException { Files.walkFileTree(directory, visitor); return visitor; } /** * Performs {@link Files#walkFileTree(Path,FileVisitor)} and returns the given visitor. * * Note that {@link Files#walkFileTree(Path,FileVisitor)} returns the given path. * * @param start See {@link Files#walkFileTree(Path,Set,int,FileVisitor)}. * @param options See {@link Files#walkFileTree(Path,Set,int,FileVisitor)}. * @param maxDepth See {@link Files#walkFileTree(Path,Set,int,FileVisitor)}. * @param visitor See {@link Files#walkFileTree(Path,Set,int,FileVisitor)}. * @param See {@link Files#walkFileTree(Path,Set,int,FileVisitor)}. * @return the given visitor. * * @throws IOException if an I/O error is thrown by a visitor method */ public static > T visitFileTree(final T visitor, final Path start, final Set options, final int maxDepth) throws IOException { Files.walkFileTree(start, options, maxDepth, visitor); return visitor; } /** * Performs {@link Files#walkFileTree(Path,FileVisitor)} and returns the given visitor. * * Note that {@link Files#walkFileTree(Path,FileVisitor)} returns the given path. * * @param visitor See {@link Files#walkFileTree(Path,FileVisitor)}. * @param first See {@link Paths#get(String,String[])}. * @param more See {@link Paths#get(String,String[])}. * @param See {@link Files#walkFileTree(Path,FileVisitor)}. * @return the given visitor. * * @throws IOException if an I/O error is thrown by a visitor method */ public static > T visitFileTree(final T visitor, final String first, final String... more) throws IOException { return visitFileTree(visitor, Paths.get(first, more)); } /** * Performs {@link Files#walkFileTree(Path,FileVisitor)} and returns the given visitor. * * Note that {@link Files#walkFileTree(Path,FileVisitor)} returns the given path. * * @param visitor See {@link Files#walkFileTree(Path,FileVisitor)}. * @param uri See {@link Paths#get(URI)}. * @param See {@link Files#walkFileTree(Path,FileVisitor)}. * @return the given visitor. * * @throws IOException if an I/O error is thrown by a visitor method */ public static > T visitFileTree(final T visitor, final URI uri) throws IOException { return visitFileTree(visitor, Paths.get(uri)); } /** * Returns a stream of filtered paths. * * @param start the start path * @param pathFilter the path filter * @param maxDepth the maximum depth of directories to walk. * @param readAttributes whether to call the filters with file attributes (false passes null). * @param options the options to configure the walk. * @return a filtered stream of paths. * @throws IOException if an I/O error is thrown when accessing the starting file. * @since 2.9.0 */ public static Stream walk(final Path start, final PathFilter pathFilter, final int maxDepth, final boolean readAttributes, final FileVisitOption... options) throws IOException { return Files.walk(start, maxDepth, options).filter(path -> pathFilter.accept(path, readAttributes ? readBasicFileAttributesUnchecked(path) : null) == FileVisitResult.CONTINUE); } /** * Does allow to instantiate. */ private PathUtils() { // do not instantiate. } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/file/PathVisitor.java0100644 0000000 0000000 00000002034 13612062727 027570 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.file; import java.nio.file.FileVisitor; import java.nio.file.Path; /** * A {@link FileVisitor} typed to a {@link Path}. * * @since 2.9.0 */ public interface PathVisitor extends FileVisitor { // empty } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/file/SimplePathVisitor.java0100644 0000000 0000000 00000002237 13612062727 030747 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.file; import java.nio.file.Path; import java.nio.file.SimpleFileVisitor; /** * A {@link SimpleFileVisitor} typed to a {@link Path}. * * @since 2.7 */ public abstract class SimplePathVisitor extends SimpleFileVisitor implements PathVisitor { /** * Constructs a new instance. */ protected SimplePathVisitor() { } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/file/StandardDeleteOption.java0100644 0000000 0000000 00000003402 13612062727 031370 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.file; import org.apache.commons.io.IOUtils; /** * Defines the standard delete options. * * @since 2.8.0 */ public enum StandardDeleteOption implements DeleteOption { /** * Overrides the read-only attribute to allow deletion. */ OVERRIDE_READ_ONLY; /** * Returns true if the given options contain {@link StandardDeleteOption#OVERRIDE_READ_ONLY}. * * For now, assume the array is not sorted. * * @param options the array to test * @return true if the given options contain {@link StandardDeleteOption#OVERRIDE_READ_ONLY}. */ public static boolean overrideReadOnly(final DeleteOption[] options) { if (IOUtils.length(options) == 0) { return false; } for (final DeleteOption deleteOption : options) { if (deleteOption == StandardDeleteOption.OVERRIDE_READ_ONLY) { return true; } } return false; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/file/package.html0100644 0000000 0000000 00000001643 13612062727 026737 0ustar00rootroot0000000 0000000

This package provides extensions in the realm of java.nio.file.

commons-io-2.11.0-src/src/main/java/org/apache/commons/io/file/spi/FileSystemProviders.java0100644 0000000 0000000 00000007353 13612062727 032102 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.file.spi; import java.net.URI; import java.net.URL; import java.nio.file.FileSystems; import java.nio.file.Path; import java.nio.file.spi.FileSystemProvider; import java.util.List; import java.util.Objects; /** * Helps working with {@link FileSystemProvider}. * * @since 2.9.0 */ public class FileSystemProviders { private static final FileSystemProviders INSTALLED = new FileSystemProviders(FileSystemProvider.installedProviders()); /** * Gets the {@link FileSystemProvider} for the given Path. * * @param path The Path to query * @return the {@link FileSystemProvider} for the given Path. */ @SuppressWarnings("resource") // FileSystem is not allocated here. public static FileSystemProvider getFileSystemProvider(final Path path) { return Objects.requireNonNull(path, "path").getFileSystem().provider(); } /** * Returns the instance for the installed providers. * * @return the instance for the installed providers. * @see FileSystemProvider#installedProviders() */ public static FileSystemProviders installed() { return INSTALLED; } private final List providers; /* * Might make public later. */ private FileSystemProviders(final List providers) { this.providers = providers; } /** * Gets the {@link FileSystemProvider} for the given scheme. * * @param scheme The scheme to query. * @return the {@link FileSystemProvider} for the given URI or null. */ @SuppressWarnings("resource") // FileSystems.getDefault() returns a constant. public FileSystemProvider getFileSystemProvider(final String scheme) { Objects.requireNonNull(scheme, "scheme"); // Check default provider first to avoid loading of installed providers. if (scheme.equalsIgnoreCase("file")) { return FileSystems.getDefault().provider(); } // Find provider. if (providers != null) { for (final FileSystemProvider provider : providers) { if (provider.getScheme().equalsIgnoreCase(scheme)) { return provider; } } } return null; } /** * Gets the {@link FileSystemProvider} for the given URI. * * @param uri The URI to query * @return the {@link FileSystemProvider} for the given URI or null. */ public FileSystemProvider getFileSystemProvider(final URI uri) { return getFileSystemProvider(Objects.requireNonNull(uri, "uri").getScheme()); } /** * Gets the {@link FileSystemProvider} for the given URL. * * @param url The URL to query * @return the {@link FileSystemProvider} for the given URI or null. */ public FileSystemProvider getFileSystemProvider(final URL url) { return getFileSystemProvider(Objects.requireNonNull(url, "url").getProtocol()); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/file/spi/package.html0100644 0000000 0000000 00000001647 13612062727 027536 0ustar00rootroot0000000 0000000

This package provides extensions in the realm of java.nio.file.spi.

commons-io-2.11.0-src/src/main/java/org/apache/commons/io/filefilter/AbstractFileFilter.java0100644 0000000 0000000 00000007231 13612062727 032237 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.filefilter; import java.io.File; import java.io.FileFilter; import java.io.FilenameFilter; import java.io.IOException; import java.nio.file.FileVisitResult; import java.nio.file.Path; import java.nio.file.attribute.BasicFileAttributes; import java.util.Objects; import org.apache.commons.io.file.PathFilter; import org.apache.commons.io.file.PathVisitor; /** * Abstracts the implementation of the {@link FileFilter} (IO), {@link FilenameFilter} (IO), {@link PathFilter} (NIO) * interfaces via our own {@link IOFileFilter} interface. *

* Note that a subclass MUST override one of the {@code accept} methods, otherwise that subclass will infinitely loop. *

* * @since 1.0 */ public abstract class AbstractFileFilter implements IOFileFilter, PathVisitor { static FileVisitResult toFileVisitResult(final boolean accept, final Path path) { return accept ? FileVisitResult.CONTINUE : FileVisitResult.TERMINATE; } /** * Checks to see if the File should be accepted by this filter. * * @param file the File to check * @return true if this file matches the test */ @Override public boolean accept(final File file) { Objects.requireNonNull(file, "file"); return accept(file.getParentFile(), file.getName()); } /** * Checks to see if the File should be accepted by this filter. * * @param dir the directory File to check * @param name the file name within the directory to check * @return true if this file matches the test */ @Override public boolean accept(final File dir, final String name) { Objects.requireNonNull(name, "name"); return accept(new File(dir, name)); } /** * Handles exceptions caught while accepting. * * @param t the caught Throwable. * @return the given Throwable. * @since 2.9.0 */ protected FileVisitResult handle(final Throwable t) { return FileVisitResult.TERMINATE; } @Override public FileVisitResult postVisitDirectory(final Path dir, final IOException exc) throws IOException { return FileVisitResult.CONTINUE; } @Override public FileVisitResult preVisitDirectory(final Path dir, final BasicFileAttributes attributes) throws IOException { return accept(dir, attributes); } /** * Provides a String representation of this file filter. * * @return a String representation */ @Override public String toString() { return getClass().getSimpleName(); } @Override public FileVisitResult visitFile(final Path file, final BasicFileAttributes attributes) throws IOException { return accept(file, attributes); } @Override public FileVisitResult visitFileFailed(final Path file, final IOException exc) throws IOException { return FileVisitResult.CONTINUE; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/filefilter/AgeFileFilter.java0100644 0000000 0000000 00000016411 13612062727 031170 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.filefilter; import java.io.File; import java.io.IOException; import java.io.Serializable; import java.nio.file.FileVisitResult; import java.nio.file.Path; import java.nio.file.attribute.BasicFileAttributes; import java.util.Date; import org.apache.commons.io.FileUtils; import org.apache.commons.io.file.PathUtils; /** * Filters files based on a cutoff time, can filter either newer files or files equal to or older. *

* For example, to print all files and directories in the current directory older than one day: *

*

Using Classic IO

*
 * Path dir = Paths.get("");
 * // We are interested in files older than one day
 * long cutoff = System.currentTimeMillis() - (24 * 60 * 60 * 1000);
 * String[] files = dir.list(new AgeFileFilter(cutoff));
 * for (String file : files) {
 *     System.out.println(file);
 * }
 * 
* *

Using NIO

*
 * Path dir = Paths.get("");
 * // We are interested in files older than one day
 * long cutoff = System.currentTimeMillis() - (24 * 60 * 60 * 1000);
 * AccumulatorPathVisitor visitor = AccumulatorPathVisitor.withLongCounters(new AgeFileFilter(cutoff));
 * //
 * // Walk one dir
 * Files.walkFileTree(dir, Collections.emptySet(), 1, visitor);
 * System.out.println(visitor.getPathCounters());
 * System.out.println(visitor.getFileList());
 * //
 * visitor.getPathCounters().reset();
 * //
 * // Walk dir tree
 * Files.walkFileTree(dir, visitor);
 * System.out.println(visitor.getPathCounters());
 * System.out.println(visitor.getDirList());
 * System.out.println(visitor.getFileList());
 * 
* * @see FileFilterUtils#ageFileFilter(Date) * @see FileFilterUtils#ageFileFilter(File) * @see FileFilterUtils#ageFileFilter(long) * @see FileFilterUtils#ageFileFilter(Date, boolean) * @see FileFilterUtils#ageFileFilter(File, boolean) * @see FileFilterUtils#ageFileFilter(long, boolean) * @since 1.2 */ public class AgeFileFilter extends AbstractFileFilter implements Serializable { private static final long serialVersionUID = -2132740084016138541L; /** Whether the files accepted will be older or newer. */ private final boolean acceptOlder; /** The cutoff time threshold measured in milliseconds since the epoch (00:00:00 GMT, January 1, 1970). */ private final long cutoffMillis; /** * Constructs a new age file filter for files older than (at or before) a certain cutoff date. * * @param cutoffDate the threshold age of the files */ public AgeFileFilter(final Date cutoffDate) { this(cutoffDate, true); } /** * Constructs a new age file filter for files on any one side of a certain cutoff date. * * @param cutoffDate the threshold age of the files * @param acceptOlder if true, older files (at or before the cutoff) are accepted, else newer ones (after the * cutoff). */ public AgeFileFilter(final Date cutoffDate, final boolean acceptOlder) { this(cutoffDate.getTime(), acceptOlder); } /** * Constructs a new age file filter for files older than (at or before) a certain File (whose last modification time * will be used as reference). * * @param cutoffReference the file whose last modification time is used as the threshold age of the files */ public AgeFileFilter(final File cutoffReference) { this(cutoffReference, true); } /** * Constructs a new age file filter for files on any one side of a certain File (whose last modification time will * be used as reference). * * @param cutoffReference the file whose last modification time is used as the threshold age of the files * @param acceptOlder if true, older files (at or before the cutoff) are accepted, else newer ones (after the * cutoff). */ public AgeFileFilter(final File cutoffReference, final boolean acceptOlder) { this(FileUtils.lastModifiedUnchecked(cutoffReference), acceptOlder); } /** * Constructs a new age file filter for files equal to or older than a certain cutoff * * @param cutoffMillis The cutoff time threshold measured in milliseconds since the epoch (00:00:00 GMT, January 1, * 1970). */ public AgeFileFilter(final long cutoffMillis) { this(cutoffMillis, true); } /** * Constructs a new age file filter for files on any one side of a certain cutoff. * * @param cutoffMillis The cutoff time threshold measured in milliseconds since the epoch (00:00:00 GMT, January 1, * 1970). * @param acceptOlder if true, older files (at or before the cutoff) are accepted, else newer ones (after the * cutoff). */ public AgeFileFilter(final long cutoffMillis, final boolean acceptOlder) { this.acceptOlder = acceptOlder; this.cutoffMillis = cutoffMillis; } /** * Checks to see if the last modification of the file matches cutoff favorably. *

* If last modification time equals cutoff and newer files are required, file IS NOT selected. If last * modification time equals cutoff and older files are required, file IS selected. *

* * @param file the File to check * @return true if the file name matches */ @Override public boolean accept(final File file) { final boolean newer = FileUtils.isFileNewer(file, cutoffMillis); return acceptOlder != newer; } /** * Checks to see if the last modification of the file matches cutoff favorably. *

* If last modification time equals cutoff and newer files are required, file IS NOT selected. If last * modification time equals cutoff and older files are required, file IS selected. *

* @param file the File to check * * @return true if the file name matches * @since 2.9.0 */ @Override public FileVisitResult accept(final Path file, final BasicFileAttributes attributes) { final boolean newer; try { newer = PathUtils.isNewer(file, cutoffMillis); } catch (final IOException e) { return handle(e); } return toFileVisitResult(acceptOlder != newer, file); } /** * Provide a String representation of this file filter. * * @return a String representation */ @Override public String toString() { final String condition = acceptOlder ? "<=" : ">"; return super.toString() + "(" + condition + cutoffMillis + ")"; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/filefilter/AndFileFilter.java0100644 0000000 0000000 00000014626 13612062727 031204 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.filefilter; import java.io.File; import java.io.Serializable; import java.nio.file.FileVisitResult; import java.nio.file.Path; import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Objects; /** * A {@link java.io.FileFilter} providing conditional AND logic across a list of * file filters. This filter returns {@code true} if all filters in the * list return {@code true}. Otherwise, it returns {@code false}. * Checking of the file filter list stops when the first filter returns * {@code false}. * * @since 1.0 * @see FileFilterUtils#and(IOFileFilter...) */ public class AndFileFilter extends AbstractFileFilter implements ConditionalFileFilter, Serializable { private static final long serialVersionUID = 7215974688563965257L; /** The list of file filters. */ private final List fileFilters; /** * Constructs a new empty instance. * * @since 1.1 */ public AndFileFilter() { this(0); } /** * Constructs a new instance with the given initial list. * * @param initialList the initial list. */ private AndFileFilter(final ArrayList initialList) { this.fileFilters = Objects.requireNonNull(initialList, "initialList"); } /** * Constructs a new instance with the given initial capacity. * * @param initialCapacity the initial capacity. */ private AndFileFilter(final int initialCapacity) { this(new ArrayList<>(initialCapacity)); } /** * Constructs a new file filter that ANDs the result of other filters. * * @param filter1 the first filter, must second be null * @param filter2 the first filter, must not be null * @throws IllegalArgumentException if either filter is null */ public AndFileFilter(final IOFileFilter filter1, final IOFileFilter filter2) { this(2); addFileFilter(filter1); addFileFilter(filter2); } /** * Constructs a new instance for the give filters. * @param fileFilters filters to OR. * * @since 2.9.0 */ public AndFileFilter(final IOFileFilter... fileFilters) { this(Objects.requireNonNull(fileFilters, "fileFilters").length); addFileFilter(fileFilters); } /** * Constructs a new instance of {@code AndFileFilter} * with the specified list of filters. * * @param fileFilters a List of IOFileFilter instances, copied. * @since 1.1 */ public AndFileFilter(final List fileFilters) { this(new ArrayList<>(Objects.requireNonNull(fileFilters, "fileFilters"))); } /** * {@inheritDoc} */ @Override public boolean accept(final File file) { if (isEmpty()) { return false; } for (final IOFileFilter fileFilter : fileFilters) { if (!fileFilter.accept(file)) { return false; } } return true; } /** * {@inheritDoc} */ @Override public boolean accept(final File file, final String name) { if (isEmpty()) { return false; } for (final IOFileFilter fileFilter : fileFilters) { if (!fileFilter.accept(file, name)) { return false; } } return true; } /** * {@inheritDoc} * @since 2.9.0 */ @Override public FileVisitResult accept(final Path file, final BasicFileAttributes attributes) { if (isEmpty()) { return FileVisitResult.TERMINATE; } for (final IOFileFilter fileFilter : fileFilters) { if (fileFilter.accept(file, attributes) != FileVisitResult.CONTINUE) { return FileVisitResult.TERMINATE; } } return FileVisitResult.CONTINUE; } /** * {@inheritDoc} */ @Override public void addFileFilter(final IOFileFilter fileFilter) { this.fileFilters.add(Objects.requireNonNull(fileFilter, "fileFilter")); } /** * Adds the given file filters. * * @param fileFilters the filters to add. * @since 2.9.0 */ public void addFileFilter(final IOFileFilter... fileFilters) { for (final IOFileFilter fileFilter : Objects.requireNonNull(fileFilters, "fileFilters")) { addFileFilter(fileFilter); } } /** * {@inheritDoc} */ @Override public List getFileFilters() { return Collections.unmodifiableList(this.fileFilters); } private boolean isEmpty() { return this.fileFilters.isEmpty(); } /** * {@inheritDoc} */ @Override public boolean removeFileFilter(final IOFileFilter ioFileFilter) { return this.fileFilters.remove(ioFileFilter); } /** * {@inheritDoc} */ @Override public void setFileFilters(final List fileFilters) { this.fileFilters.clear(); this.fileFilters.addAll(fileFilters); } /** * Provide a String representation of this file filter. * * @return a String representation */ @Override public String toString() { final StringBuilder buffer = new StringBuilder(); buffer.append(super.toString()); buffer.append("("); for (int i = 0; i < fileFilters.size(); i++) { if (i > 0) { buffer.append(","); } buffer.append(fileFilters.get(i)); } buffer.append(")"); return buffer.toString(); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/filefilter/CanExecuteFileFilter.java0100644 0000000 0000000 00000005707 13612062727 032526 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.filefilter; import java.io.File; import java.io.Serializable; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.attribute.BasicFileAttributes; /** * This filter accepts {@code File}s that can be executed. *

* Example, showing how to print out a list of the * current directory's executable files: *

*

Using Classic IO

*
 * File dir = new File(".");
 * String[] files = dir.list(CanExecuteFileFilter.CAN_EXECUTE);
 * for (String file : files) {
 *     System.out.println(file);
 * }
 * 
* *

* Example, showing how to print out a list of the * current directory's non-executable files: *

* *
 * File dir = new File(".");
 * String[] files = dir.list(CanExecuteFileFilter.CANNOT_EXECUTE);
 * for (int i = 0; i < files.length; i++) {
 *     System.out.println(files[i]);
 * }
 * 
* * @since 2.7 */ public class CanExecuteFileFilter extends AbstractFileFilter implements Serializable { /** Singleton instance of executable filter */ public static final IOFileFilter CAN_EXECUTE = new CanExecuteFileFilter(); /** Singleton instance of not executable filter */ public static final IOFileFilter CANNOT_EXECUTE = CAN_EXECUTE.negate(); private static final long serialVersionUID = 3179904805251622989L; /** * Restrictive constructor. */ protected CanExecuteFileFilter() { // empty. } /** * Checks to see if the file can be executed. * * @param file the File to check. * @return {@code true} if the file can be executed, otherwise {@code false}. */ @Override public boolean accept(final File file) { return file.canExecute(); } /** * Checks to see if the file can be executed. * @param file the File to check. * * @return {@code true} if the file can be executed, otherwise {@code false}. * @since 2.9.0 */ @Override public FileVisitResult accept(final Path file, final BasicFileAttributes attributes) { return toFileVisitResult(Files.isExecutable(file), file); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/filefilter/CanReadFileFilter.java0100644 0000000 0000000 00000006407 13612062727 031775 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.filefilter; import java.io.File; import java.io.Serializable; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.attribute.BasicFileAttributes; /** * This filter accepts {@code File}s that can be read. *

* Example, showing how to print out a list of the current directory's readable files: *

*

Using Classic IO

*
 * File dir = new File(".");
 * String[] files = dir.list(CanReadFileFilter.CAN_READ);
 * for (String file : files) {
 *     System.out.println(file);
 * }
 * 
* *

* Example, showing how to print out a list of the current directory's un-readable files: * *

 * File dir = new File(".");
 * String[] files = dir.list(CanReadFileFilter.CANNOT_READ);
 * for (String file : files) {
 *     System.out.println(file);
 * }
 * 
* *

* Example, showing how to print out a list of the current directory's read-only files: * *

 * File dir = new File(".");
 * String[] files = dir.list(CanReadFileFilter.READ_ONLY);
 * for (String file : files) {
 *     System.out.println(file);
 * }
 * 
* * @since 1.3 */ public class CanReadFileFilter extends AbstractFileFilter implements Serializable { /** Singleton instance of readable filter */ public static final IOFileFilter CAN_READ = new CanReadFileFilter(); /** Singleton instance of not readable filter */ public static final IOFileFilter CANNOT_READ = CAN_READ.negate(); /** Singleton instance of read-only filter */ public static final IOFileFilter READ_ONLY = CAN_READ.and(CanWriteFileFilter.CANNOT_WRITE); private static final long serialVersionUID = 3179904805251622989L; /** * Restrictive constructor. */ protected CanReadFileFilter() { } /** * Checks to see if the file can be read. * * @param file the File to check. * @return {@code true} if the file can be read, otherwise {@code false}. */ @Override public boolean accept(final File file) { return file.canRead(); } /** * Checks to see if the file can be read. * @param file the File to check. * * @return {@code true} if the file can be read, otherwise {@code false}. * @since 2.9.0 */ @Override public FileVisitResult accept(final Path file, final BasicFileAttributes attributes) { return toFileVisitResult(Files.isReadable(file), file); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/filefilter/CanWriteFileFilter.java0100644 0000000 0000000 00000005717 13612062727 032217 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.filefilter; import java.io.File; import java.io.Serializable; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.attribute.BasicFileAttributes; /** * This filter accepts {@code File}s that can be written to. *

* Example, showing how to print out a list of the current directory's writable files: *

*

Using Classic IO

*
 * File dir = new File(".");
 * String[] files = dir.list(CanWriteFileFilter.CAN_WRITE);
 * for (String file : files) {
 *     System.out.println(file);
 * }
 * 
* *

* Example, showing how to print out a list of the current directory's un-writable files: * *

 * File dir = new File(".");
 * String[] files = dir.list(CanWriteFileFilter.CANNOT_WRITE);
 * for (String file : files) {
 *     System.out.println(file);
 * }
 * 
* *

* N.B. For read-only files, use {@code CanReadFileFilter.READ_ONLY}. * * @since 1.3 */ public class CanWriteFileFilter extends AbstractFileFilter implements Serializable { /** Singleton instance of writable filter */ public static final IOFileFilter CAN_WRITE = new CanWriteFileFilter(); /** Singleton instance of not writable filter */ public static final IOFileFilter CANNOT_WRITE = CAN_WRITE.negate(); private static final long serialVersionUID = 5132005214688990379L; /** * Restrictive constructor. */ protected CanWriteFileFilter() { } /** * Checks to see if the file can be written to. * * @param file the File to check * @return {@code true} if the file can be written to, otherwise {@code false}. */ @Override public boolean accept(final File file) { return file.canWrite(); } /** * Checks to see if the file can be written to. * @param file the File to check * * @return {@code true} if the file can be written to, otherwise {@code false}. * @since 2.9.0 */ @Override public FileVisitResult accept(final Path file, final BasicFileAttributes attributes) { return toFileVisitResult(Files.isWritable(file), file); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/filefilter/ConditionalFileFilter.java0100644 0000000 0000000 00000003643 13612062727 032742 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.filefilter; import java.util.List; /** * Defines operations for conditional file filters. * * @since 1.1 */ public interface ConditionalFileFilter { /** * Adds the specified file filter to the list of file filters at the end of * the list. * * @param ioFileFilter the filter to be added * @since 1.1 */ void addFileFilter(IOFileFilter ioFileFilter); /** * Gets this conditional file filter's list of file filters. * * @return the file filter list * @since 1.1 */ List getFileFilters(); /** * Removes the specified file filter. * * @param ioFileFilter filter to be removed * @return {@code true} if the filter was found in the list, * {@code false} otherwise * @since 1.1 */ boolean removeFileFilter(IOFileFilter ioFileFilter); /** * Sets the list of file filters, replacing any previously configured * file filters on this filter. * * @param fileFilters the list of filters * @since 1.1 */ void setFileFilters(List fileFilters); } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/filefilter/DelegateFileFilter.java0100644 0000000 0000000 00000006400 13612062727 032203 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.filefilter; import java.io.File; import java.io.FileFilter; import java.io.FilenameFilter; import java.io.Serializable; /** * This class turns a Java FileFilter or FilenameFilter into an IO FileFilter. * * @since 1.0 * @see FileFilterUtils#asFileFilter(FileFilter) * @see FileFilterUtils#asFileFilter(FilenameFilter) */ public class DelegateFileFilter extends AbstractFileFilter implements Serializable { private static final long serialVersionUID = -8723373124984771318L; /** The File filter */ private final FileFilter fileFilter; /** The Filename filter */ private final FilenameFilter filenameFilter; /** * Constructs a delegate file filter around an existing FileFilter. * * @param filter the filter to decorate */ public DelegateFileFilter(final FileFilter filter) { if (filter == null) { throw new IllegalArgumentException("The FileFilter must not be null"); } this.fileFilter = filter; this.filenameFilter = null; } /** * Constructs a delegate file filter around an existing FilenameFilter. * * @param filter the filter to decorate */ public DelegateFileFilter(final FilenameFilter filter) { if (filter == null) { throw new IllegalArgumentException("The FilenameFilter must not be null"); } this.filenameFilter = filter; this.fileFilter = null; } /** * Checks the filter. * * @param file the file to check * @return true if the filter matches */ @Override public boolean accept(final File file) { if (fileFilter != null) { return fileFilter.accept(file); } return super.accept(file); } /** * Checks the filter. * * @param dir the directory * @param name the file name in the directory * @return true if the filter matches */ @Override public boolean accept(final File dir, final String name) { if (filenameFilter != null) { return filenameFilter.accept(dir, name); } return super.accept(dir, name); } /** * Provide a String representation of this file filter. * * @return a String representation */ @Override public String toString() { final String delegate = fileFilter != null ? fileFilter.toString() : filenameFilter.toString(); return super.toString() + "(" + delegate + ")"; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/filefilter/DirectoryFileFilter.java0100644 0000000 0000000 00000006623 13612062727 032444 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.filefilter; import java.io.File; import java.io.Serializable; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.attribute.BasicFileAttributes; /** * This filter accepts {@code File}s that are directories. *

* For example, here is how to print out a list of the current directory's subdirectories: *

*

Using Classic IO

* *
 * File dir = new File(".");
 * String[] files = dir.list(DirectoryFileFilter.INSTANCE);
 * for (String file : files) {
 *     System.out.println(file);
 * }
 * 
* *

Using NIO

* *
 * final Path dir = Paths.get("");
 * final AccumulatorPathVisitor visitor = AccumulatorPathVisitor.withLongCounters(DirectoryFileFilter.INSTANCE);
 * //
 * // Walk one dir
 * Files.walkFileTree(dir, Collections.emptySet(), 1, visitor);
 * System.out.println(visitor.getPathCounters());
 * System.out.println(visitor.getFileList());
 * //
 * visitor.getPathCounters().reset();
 * //
 * // Walk dir tree
 * Files.walkFileTree(dir, visitor);
 * System.out.println(visitor.getPathCounters());
 * System.out.println(visitor.getDirList());
 * System.out.println(visitor.getFileList());
 * 
* * @since 1.0 * @see FileFilterUtils#directoryFileFilter() */ public class DirectoryFileFilter extends AbstractFileFilter implements Serializable { /** * Singleton instance of directory filter. * * @since 1.3 */ public static final IOFileFilter DIRECTORY = new DirectoryFileFilter(); /** * Singleton instance of directory filter. Please use the identical DirectoryFileFilter.DIRECTORY constant. The new * name is more JDK 1.5 friendly as it doesn't clash with other values when using static imports. */ public static final IOFileFilter INSTANCE = DIRECTORY; private static final long serialVersionUID = -5148237843784525732L; /** * Restrictive constructor. */ protected DirectoryFileFilter() { // empty. } /** * Checks to see if the file is a directory. * * @param file the File to check * @return true if the file is a directory */ @Override public boolean accept(final File file) { return file.isDirectory(); } /** * Checks to see if the file is a directory. * @param file the File to check * * @return true if the file is a directory * @since 2.9.0 */ @Override public FileVisitResult accept(final Path file, final BasicFileAttributes attributes) { return toFileVisitResult(Files.isDirectory(file), file); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/filefilter/EmptyFileFilter.java0100644 0000000 0000000 00000010201 13612062727 031561 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.filefilter; import java.io.File; import java.io.IOException; import java.io.Serializable; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.attribute.BasicFileAttributes; import java.util.stream.Stream; import org.apache.commons.io.IOUtils; /** * This filter accepts files or directories that are empty. *

* If the {@code File} is a directory it checks that it contains no files. *

*

* Example, showing how to print out a list of the current directory's empty files/directories: *

*

Using Classic IO

*
 * File dir = new File(".");
 * String[] files = dir.list(EmptyFileFilter.EMPTY);
 * for (String file : files) {
 *     System.out.println(file);
 * }
 * 
* *

* Example, showing how to print out a list of the current directory's non-empty files/directories: *

* *
 * File dir = new File(".");
 * String[] files = dir.list(EmptyFileFilter.NOT_EMPTY);
 * for (String file : files) {
 *     System.out.println(file);
 * }
 * 
* *

Using NIO

*
 * final Path dir = Paths.get("");
 * final AccumulatorPathVisitor visitor = AccumulatorPathVisitor.withLongCounters(EmptyFileFilter.EMPTY);
 * //
 * // Walk one dir
 * Files.walkFileTree(dir, Collections.emptySet(), 1, visitor);
 * System.out.println(visitor.getPathCounters());
 * System.out.println(visitor.getFileList());
 * //
 * visitor.getPathCounters().reset();
 * //
 * // Walk dir tree
 * Files.walkFileTree(dir, visitor);
 * System.out.println(visitor.getPathCounters());
 * System.out.println(visitor.getDirList());
 * System.out.println(visitor.getFileList());
 * 
* * @since 1.3 */ public class EmptyFileFilter extends AbstractFileFilter implements Serializable { /** Singleton instance of empty filter */ public static final IOFileFilter EMPTY = new EmptyFileFilter(); /** Singleton instance of not-empty filter */ public static final IOFileFilter NOT_EMPTY = EMPTY.negate(); private static final long serialVersionUID = 3631422087512832211L; /** * Restrictive constructor. */ protected EmptyFileFilter() { } /** * Checks to see if the file is empty. * * @param file the file or directory to check * @return {@code true} if the file or directory is empty, otherwise {@code false}. */ @Override public boolean accept(final File file) { if (file.isDirectory()) { final File[] files = file.listFiles(); return IOUtils.length(files) == 0; } return file.length() == 0; } /** * Checks to see if the file is empty. * @param file the file or directory to check * * @return {@code true} if the file or directory is empty, otherwise {@code false}. * @since 2.9.0 */ @Override public FileVisitResult accept(final Path file, final BasicFileAttributes attributes) { try { if (Files.isDirectory(file)) { try (Stream stream = Files.list(file)) { return toFileVisitResult(!stream.findFirst().isPresent(), file); } } return toFileVisitResult(Files.size(file) == 0, file); } catch (final IOException e) { return handle(e); } } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/filefilter/FalseFileFilter.java0100644 0000000 0000000 00000006035 13612062727 031527 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.filefilter; import java.io.File; import java.io.Serializable; import java.nio.file.FileVisitResult; import java.nio.file.Path; import java.nio.file.attribute.BasicFileAttributes; /** * A file filter that always returns false. * * @since 1.0 * @see FileFilterUtils#falseFileFilter() */ public class FalseFileFilter implements IOFileFilter, Serializable { private static final String TO_STRING = Boolean.FALSE.toString(); /** * Singleton instance of false filter. * * @since 1.3 */ public static final IOFileFilter FALSE = new FalseFileFilter(); /** * Singleton instance of false filter. Please use the identical FalseFileFilter.FALSE constant. The new name is more * JDK 1.5 friendly as it doesn't clash with other values when using static imports. */ public static final IOFileFilter INSTANCE = FALSE; private static final long serialVersionUID = 6210271677940926200L; /** * Restrictive constructor. */ protected FalseFileFilter() { } /** * Returns false. * * @param file the file to check (ignored) * @return false */ @Override public boolean accept(final File file) { return false; } /** * Returns false. * * @param dir the directory to check (ignored) * @param name the file name (ignored) * @return false */ @Override public boolean accept(final File dir, final String name) { return false; } /** * Returns false. * * @param file the file to check (ignored) * * @return false * @since 2.9.0 */ @Override public FileVisitResult accept(final Path file, final BasicFileAttributes attributes) { return FileVisitResult.TERMINATE; } @Override public IOFileFilter negate() { return TrueFileFilter.INSTANCE; } @Override public String toString() { return TO_STRING; } @Override public IOFileFilter and(final IOFileFilter fileFilter) { // FALSE AND expression <=> FALSE return INSTANCE; } @Override public IOFileFilter or(final IOFileFilter fileFilter) { // FALSE OR expression <=> expression return fileFilter; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/filefilter/FileEqualsFileFilter.java0100644 0000000 0000000 00000003701 13612062727 032524 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.filefilter; import java.io.File; import java.nio.file.FileVisitResult; import java.nio.file.Path; import java.nio.file.attribute.BasicFileAttributes; import java.util.Objects; /** * Accepts only an exact {@link File} object match. You can use this filter to visit the start directory when walking a * file tree with * {@link java.nio.file.Files#walkFileTree(java.nio.file.Path, java.util.Set, int, java.nio.file.FileVisitor)}. * * @since 2.9.0 */ public class FileEqualsFileFilter extends AbstractFileFilter { private final File file; private final Path path; /** * Constructs a new instance for the given {@link File}. * * @param file The file to match. */ public FileEqualsFileFilter(final File file) { this.file = Objects.requireNonNull(file, "file"); this.path = file.toPath(); } @Override public boolean accept(final File file) { return Objects.equals(this.file, file); } @Override public FileVisitResult accept(final Path path, final BasicFileAttributes attributes) { return toFileVisitResult(Objects.equals(this.path, path), path); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/filefilter/FileFileFilter.java0100644 0000000 0000000 00000006337 13612062727 031361 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.filefilter; import java.io.File; import java.io.Serializable; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.attribute.BasicFileAttributes; /** * This filter accepts {@code File}s that are files (not directories). *

* For example, here is how to print out a list of the real files * within the current directory: *

*

Using Classic IO

*
 * File dir = new File(".");
 * String[] files = dir.list(FileFileFilter.INSTANCE);
 * for (String file : files) {
 *     System.out.println(file);
 * }
 * 
* *

Using NIO

*
 * final Path dir = Paths.get("");
 * final AccumulatorPathVisitor visitor = AccumulatorPathVisitor.withLongCounters(FileFileFilter.INSTANCE);
 * //
 * // Walk one dir
 * Files.walkFileTree(dir, Collections.emptySet(), 1, visitor);
 * System.out.println(visitor.getPathCounters());
 * System.out.println(visitor.getFileList());
 * //
 * visitor.getPathCounters().reset();
 * //
 * // Walk dir tree
 * Files.walkFileTree(dir, visitor);
 * System.out.println(visitor.getPathCounters());
 * System.out.println(visitor.getDirList());
 * System.out.println(visitor.getFileList());
 * 
* * @since 1.3 * @see FileFilterUtils#fileFileFilter() */ public class FileFileFilter extends AbstractFileFilter implements Serializable { /** * Singleton instance of file filter. * * @since 2.9.0 */ public static final IOFileFilter INSTANCE = new FileFileFilter(); /** * Singleton instance of file filter. * * @deprecated Use {@link #INSTANCE}. */ @Deprecated public static final IOFileFilter FILE = INSTANCE; private static final long serialVersionUID = 5345244090827540862L; /** * Restrictive constructor. */ protected FileFileFilter() { } /** * Checks to see if the file is a file. * * @param file the File to check * @return true if the file is a file */ @Override public boolean accept(final File file) { return file.isFile(); } /** * Checks to see if the file is a file. * @param file the File to check * * @return true if the file is a file * @since 2.9.0 */ @Override public FileVisitResult accept(final Path file, final BasicFileAttributes attributes) { return toFileVisitResult(Files.isRegularFile(file), file); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/filefilter/FileFilterUtils.java0100644 0000000 0000000 00000064567 13612062727 031613 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.filefilter; import java.io.File; import java.io.FileFilter; import java.io.FilenameFilter; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Objects; import java.util.Set; import java.util.stream.Collector; import java.util.stream.Collectors; import java.util.stream.Stream; import java.util.stream.StreamSupport; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOCase; /** * Useful utilities for working with file filters. It provides access to all * file filter implementations in this package so you don't have to import * every class you use. * * @since 1.0 */ public class FileFilterUtils { /* Constructed on demand and then cached */ private static final IOFileFilter cvsFilter = notFileFilter( and(directoryFileFilter(), nameFileFilter("CVS"))); /* Constructed on demand and then cached */ private static final IOFileFilter svnFilter = notFileFilter( and(directoryFileFilter(), nameFileFilter(".svn"))); /** * Returns a filter that returns true if the file was last modified before * or at the specified cutoff date. * * @param cutoffDate the time threshold * @return an appropriately configured age file filter * @see AgeFileFilter * @since 1.2 */ public static IOFileFilter ageFileFilter(final Date cutoffDate) { return new AgeFileFilter(cutoffDate); } /** * Returns a filter that filters files based on a cutoff date. * * @param cutoffDate the time threshold * @param acceptOlder if true, older files get accepted, if false, newer * @return an appropriately configured age file filter * @see AgeFileFilter * @since 1.2 */ public static IOFileFilter ageFileFilter(final Date cutoffDate, final boolean acceptOlder) { return new AgeFileFilter(cutoffDate, acceptOlder); } /** * Returns a filter that returns true if the file was last modified before * or at the same time as the specified reference file. * * @param cutoffReference the file whose last modification * time is used as the threshold age of the files * @return an appropriately configured age file filter * @see AgeFileFilter * @since 1.2 */ public static IOFileFilter ageFileFilter(final File cutoffReference) { return new AgeFileFilter(cutoffReference); } /** * Returns a filter that filters files based on a cutoff reference file. * * @param cutoffReference the file whose last modification * time is used as the threshold age of the files * @param acceptOlder if true, older files get accepted, if false, newer * @return an appropriately configured age file filter * @see AgeFileFilter * @since 1.2 */ public static IOFileFilter ageFileFilter(final File cutoffReference, final boolean acceptOlder) { return new AgeFileFilter(cutoffReference, acceptOlder); } /** * Returns a filter that returns true if the file was last modified before * or at the specified cutoff time. * * @param cutoff the time threshold * @return an appropriately configured age file filter * @see AgeFileFilter * @since 1.2 */ public static IOFileFilter ageFileFilter(final long cutoff) { return new AgeFileFilter(cutoff); } /** * Returns a filter that filters files based on a cutoff time. * * @param cutoff the time threshold * @param acceptOlder if true, older files get accepted, if false, newer * @return an appropriately configured age file filter * @see AgeFileFilter * @since 1.2 */ public static IOFileFilter ageFileFilter(final long cutoff, final boolean acceptOlder) { return new AgeFileFilter(cutoff, acceptOlder); } /** * Returns a filter that ANDs the specified filters. * * @param filters the IOFileFilters that will be ANDed together. * @return a filter that ANDs the specified filters * * @throws IllegalArgumentException if the filters are null or contain a * null value. * @see AndFileFilter * @since 2.0 */ public static IOFileFilter and(final IOFileFilter... filters) { return new AndFileFilter(toList(filters)); } /** * Returns a filter that ANDs the two specified filters. * * @param filter1 the first filter * @param filter2 the second filter * @return a filter that ANDs the two specified filters * @see #and(IOFileFilter...) * @see AndFileFilter * @deprecated use {@link #and(IOFileFilter...)} */ @Deprecated public static IOFileFilter andFileFilter(final IOFileFilter filter1, final IOFileFilter filter2) { return new AndFileFilter(filter1, filter2); } /** * Returns an {@code IOFileFilter} that wraps the * {@code FileFilter} instance. * * @param filter the filter to be wrapped * @return a new filter that implements IOFileFilter * @see DelegateFileFilter */ public static IOFileFilter asFileFilter(final FileFilter filter) { return new DelegateFileFilter(filter); } /** * Returns an {@code IOFileFilter} that wraps the * {@code FilenameFilter} instance. * * @param filter the filter to be wrapped * @return a new filter that implements IOFileFilter * @see DelegateFileFilter */ public static IOFileFilter asFileFilter(final FilenameFilter filter) { return new DelegateFileFilter(filter); } /** * Returns a filter that checks if the file is a directory. * * @return file filter that accepts only directories and not files * @see DirectoryFileFilter#DIRECTORY */ public static IOFileFilter directoryFileFilter() { return DirectoryFileFilter.DIRECTORY; } /** * Returns a filter that always returns false. * * @return a false filter * @see FalseFileFilter#FALSE */ public static IOFileFilter falseFileFilter() { return FalseFileFilter.FALSE; } /** * Returns a filter that checks if the file is a file (and not a directory). * * @return file filter that accepts only files and not directories * @see FileFileFilter#INSTANCE */ public static IOFileFilter fileFileFilter() { return FileFileFilter.INSTANCE; } /** *

* Applies an {@link IOFileFilter} to the provided {@link File} * objects. The resulting array is a subset of the original file list that * matches the provided filter. *

* *
     * Set<File> allFiles = ...
     * Set<File> javaFiles = FileFilterUtils.filterSet(allFiles,
     *     FileFilterUtils.suffixFileFilter(".java"));
     * 
* @param filter the filter to apply to the set of files. * @param files the array of files to apply the filter to. * * @return a subset of {@code files} that is accepted by the * file filter. * @throws IllegalArgumentException if the filter is {@code null} * or {@code files} contains a {@code null} value. * * @since 2.0 */ public static File[] filter(final IOFileFilter filter, final File... files) { if (filter == null) { throw new IllegalArgumentException("file filter is null"); } if (files == null) { return FileUtils.EMPTY_FILE_ARRAY; } return filterFiles(filter, Stream.of(files), Collectors.toList()).toArray(FileUtils.EMPTY_FILE_ARRAY); } /** *

* Applies an {@link IOFileFilter} to the provided {@link File} stream and collects the accepted files. *

* * @param filter the filter to apply to the stream of files. * @param stream the stream of files on which to apply the filter. * @param collector how to collect the end result. * * @param the return type. * @param the mutable accumulation type of the reduction operation (often hidden as an implementation detail) * @return a subset of files from the stream that is accepted by the filter. * @throws IllegalArgumentException if the filter is {@code null}. */ private static R filterFiles(final IOFileFilter filter, final Stream stream, final Collector collector) { //Objects.requireNonNull(filter, "filter"); Objects.requireNonNull(collector, "collector"); if (filter == null) { throw new IllegalArgumentException("file filter is null"); } if (stream == null) { return Stream.empty().collect(collector); } return stream.filter(filter::accept).collect(collector); } /** *

* Applies an {@link IOFileFilter} to the provided {@link File} * objects. The resulting array is a subset of the original file list that * matches the provided filter. *

* *

* The {@link Set} returned by this method is not guaranteed to be thread safe. *

* *
     * Set<File> allFiles = ...
     * Set<File> javaFiles = FileFilterUtils.filterSet(allFiles,
     *     FileFilterUtils.suffixFileFilter(".java"));
     * 
* @param filter the filter to apply to the set of files. * @param files the array of files to apply the filter to. * * @return a subset of {@code files} that is accepted by the * file filter. * @throws IllegalArgumentException if the filter is {@code null} * or {@code files} contains a {@code null} value. * * @since 2.0 */ public static File[] filter(final IOFileFilter filter, final Iterable files) { return filterList(filter, files).toArray(FileUtils.EMPTY_FILE_ARRAY); } /** *

* Applies an {@link IOFileFilter} to the provided {@link File} * objects. The resulting list is a subset of the original files that * matches the provided filter. *

* *

* The {@link List} returned by this method is not guaranteed to be thread safe. *

* *
     * List<File> filesAndDirectories = ...
     * List<File> directories = FileFilterUtils.filterList(filesAndDirectories,
     *     FileFilterUtils.directoryFileFilter());
     * 
* @param filter the filter to apply to each files in the list. * @param files the collection of files to apply the filter to. * * @return a subset of {@code files} that is accepted by the * file filter. * @throws IllegalArgumentException if the filter is {@code null} * or {@code files} contains a {@code null} value. * @since 2.0 */ public static List filterList(final IOFileFilter filter, final File... files) { return Arrays.asList(filter(filter, files)); } /** *

* Applies an {@link IOFileFilter} to the provided {@link File} * objects. The resulting list is a subset of the original files that * matches the provided filter. *

* *

* The {@link List} returned by this method is not guaranteed to be thread safe. *

* *
     * List<File> filesAndDirectories = ...
     * List<File> directories = FileFilterUtils.filterList(filesAndDirectories,
     *     FileFilterUtils.directoryFileFilter());
     * 
* @param filter the filter to apply to each files in the list. * @param files the collection of files to apply the filter to. * * @return a subset of {@code files} that is accepted by the * file filter. * @throws IllegalArgumentException if the filter is {@code null} * @since 2.0 */ public static List filterList(final IOFileFilter filter, final Iterable files) { if (files == null) { return Collections.emptyList(); } return filterFiles(filter, StreamSupport.stream(files.spliterator(), false), Collectors.toList()); } /** *

* Applies an {@link IOFileFilter} to the provided {@link File} * objects. The resulting set is a subset of the original file list that * matches the provided filter. *

* *

* The {@link Set} returned by this method is not guaranteed to be thread safe. *

* *
     * Set<File> allFiles = ...
     * Set<File> javaFiles = FileFilterUtils.filterSet(allFiles,
     *     FileFilterUtils.suffixFileFilter(".java"));
     * 
* @param filter the filter to apply to the set of files. * @param files the collection of files to apply the filter to. * * @return a subset of {@code files} that is accepted by the * file filter. * @throws IllegalArgumentException if the filter is {@code null} * or {@code files} contains a {@code null} value. * * @since 2.0 */ public static Set filterSet(final IOFileFilter filter, final File... files) { return new HashSet<>(Arrays.asList(filter(filter, files))); } /** *

* Applies an {@link IOFileFilter} to the provided {@link File} * objects. The resulting set is a subset of the original file list that * matches the provided filter. *

* *

* The {@link Set} returned by this method is not guaranteed to be thread safe. *

* *
     * Set<File> allFiles = ...
     * Set<File> javaFiles = FileFilterUtils.filterSet(allFiles,
     *     FileFilterUtils.suffixFileFilter(".java"));
     * 
* @param filter the filter to apply to the set of files. * @param files the collection of files to apply the filter to. * * @return a subset of {@code files} that is accepted by the * file filter. * @throws IllegalArgumentException if the filter is {@code null} * * @since 2.0 */ public static Set filterSet(final IOFileFilter filter, final Iterable files) { if (files == null) { return Collections.emptySet(); } return filterFiles(filter, StreamSupport.stream(files.spliterator(), false), Collectors.toSet()); } /** * Returns a filter that accepts files that begin with the provided magic * number. * * @param magicNumber the magic number (byte sequence) to match at the * beginning of each file. * * @return an IOFileFilter that accepts files beginning with the provided * magic number. * * @throws IllegalArgumentException if {@code magicNumber} is * {@code null} or is of length zero. * @see MagicNumberFileFilter * @since 2.0 */ public static IOFileFilter magicNumberFileFilter(final byte[] magicNumber) { return new MagicNumberFileFilter(magicNumber); } /** * Returns a filter that accepts files that contains the provided magic * number at a specified offset within the file. * * @param magicNumber the magic number (byte sequence) to match at the * provided offset in each file. * @param offset the offset within the files to look for the magic number. * * @return an IOFileFilter that accepts files containing the magic number * at the specified offset. * * @throws IllegalArgumentException if {@code magicNumber} is * {@code null}, or contains no bytes, or {@code offset} * is a negative number. * @see MagicNumberFileFilter * @since 2.0 */ public static IOFileFilter magicNumberFileFilter(final byte[] magicNumber, final long offset) { return new MagicNumberFileFilter(magicNumber, offset); } /** * Returns a filter that accepts files that begin with the provided magic * number. * * @param magicNumber the magic number (byte sequence) to match at the * beginning of each file. * * @return an IOFileFilter that accepts files beginning with the provided * magic number. * * @throws IllegalArgumentException if {@code magicNumber} is * {@code null} or the empty String. * @see MagicNumberFileFilter * @since 2.0 */ public static IOFileFilter magicNumberFileFilter(final String magicNumber) { return new MagicNumberFileFilter(magicNumber); } /** * Returns a filter that accepts files that contains the provided magic * number at a specified offset within the file. * * @param magicNumber the magic number (byte sequence) to match at the * provided offset in each file. * @param offset the offset within the files to look for the magic number. * * @return an IOFileFilter that accepts files containing the magic number * at the specified offset. * * @throws IllegalArgumentException if {@code magicNumber} is * {@code null} or the empty String, or if offset is a * negative number. * @see MagicNumberFileFilter * @since 2.0 */ public static IOFileFilter magicNumberFileFilter(final String magicNumber, final long offset) { return new MagicNumberFileFilter(magicNumber, offset); } /** * Decorates a filter to make it ignore CVS directories. * Passing in {@code null} will return a filter that accepts everything * except CVS directories. * * @param filter the filter to decorate, null means an unrestricted filter * @return the decorated filter, never null * @since 1.1 (method existed but had bug in 1.0) */ public static IOFileFilter makeCVSAware(final IOFileFilter filter) { return filter == null ? cvsFilter : and(filter, cvsFilter); } /** * Decorates a filter so that it only applies to directories and not to files. * * @param filter the filter to decorate, null means an unrestricted filter * @return the decorated filter, never null * @see DirectoryFileFilter#DIRECTORY * @since 1.3 */ public static IOFileFilter makeDirectoryOnly(final IOFileFilter filter) { if (filter == null) { return DirectoryFileFilter.DIRECTORY; } return DirectoryFileFilter.DIRECTORY.and(filter); } /** * Decorates a filter so that it only applies to files and not to directories. * * @param filter the filter to decorate, null means an unrestricted filter * @return the decorated filter, never null * @see FileFileFilter#INSTANCE * @since 1.3 */ public static IOFileFilter makeFileOnly(final IOFileFilter filter) { if (filter == null) { return FileFileFilter.INSTANCE; } return FileFileFilter.INSTANCE.and(filter); } /** * Decorates a filter to make it ignore SVN directories. * Passing in {@code null} will return a filter that accepts everything * except SVN directories. * * @param filter the filter to decorate, null means an unrestricted filter * @return the decorated filter, never null * @since 1.1 */ public static IOFileFilter makeSVNAware(final IOFileFilter filter) { return filter == null ? svnFilter : and(filter, svnFilter); } /** * Returns a filter that returns true if the file name matches the specified text. * * @param name the file name * @return a name checking filter * @see NameFileFilter */ public static IOFileFilter nameFileFilter(final String name) { return new NameFileFilter(name); } /** * Returns a filter that returns true if the file name matches the specified text. * * @param name the file name * @param caseSensitivity how to handle case sensitivity, null means case-sensitive * @return a name checking filter * @see NameFileFilter * @since 2.0 */ public static IOFileFilter nameFileFilter(final String name, final IOCase caseSensitivity) { return new NameFileFilter(name, caseSensitivity); } /** * Returns a filter that NOTs the specified filter. * * @param filter the filter to invert * @return a filter that NOTs the specified filter * @see NotFileFilter */ public static IOFileFilter notFileFilter(final IOFileFilter filter) { return filter.negate(); } /** * Returns a filter that ORs the specified filters. * * @param filters the IOFileFilters that will be ORed together. * @return a filter that ORs the specified filters * * @throws IllegalArgumentException if the filters are null or contain a * null value. * @see OrFileFilter * @since 2.0 */ public static IOFileFilter or(final IOFileFilter... filters) { return new OrFileFilter(toList(filters)); } /** * Returns a filter that ORs the two specified filters. * * @param filter1 the first filter * @param filter2 the second filter * @return a filter that ORs the two specified filters * @see #or(IOFileFilter...) * @see OrFileFilter * @deprecated use {@link #or(IOFileFilter...)} */ @Deprecated public static IOFileFilter orFileFilter(final IOFileFilter filter1, final IOFileFilter filter2) { return new OrFileFilter(filter1, filter2); } /** * Returns a filter that returns true if the file name starts with the specified text. * * @param prefix the file name prefix * @return a prefix checking filter * @see PrefixFileFilter */ public static IOFileFilter prefixFileFilter(final String prefix) { return new PrefixFileFilter(prefix); } /** * Returns a filter that returns true if the file name starts with the specified text. * * @param prefix the file name prefix * @param caseSensitivity how to handle case sensitivity, null means case-sensitive * @return a prefix checking filter * @see PrefixFileFilter * @since 2.0 */ public static IOFileFilter prefixFileFilter(final String prefix, final IOCase caseSensitivity) { return new PrefixFileFilter(prefix, caseSensitivity); } /** * Returns a filter that returns true if the file is bigger than a certain size. * * @param threshold the file size threshold * @return an appropriately configured SizeFileFilter * @see SizeFileFilter * @since 1.2 */ public static IOFileFilter sizeFileFilter(final long threshold) { return new SizeFileFilter(threshold); } /** * Returns a filter that filters based on file size. * * @param threshold the file size threshold * @param acceptLarger if true, larger files get accepted, if false, smaller * @return an appropriately configured SizeFileFilter * @see SizeFileFilter * @since 1.2 */ public static IOFileFilter sizeFileFilter(final long threshold, final boolean acceptLarger) { return new SizeFileFilter(threshold, acceptLarger); } /** * Returns a filter that accepts files whose size is >= minimum size * and <= maximum size. * * @param minSizeInclusive the minimum file size (inclusive) * @param maxSizeInclusive the maximum file size (inclusive) * @return an appropriately configured IOFileFilter * @see SizeFileFilter * @since 1.3 */ public static IOFileFilter sizeRangeFileFilter(final long minSizeInclusive, final long maxSizeInclusive ) { final IOFileFilter minimumFilter = new SizeFileFilter(minSizeInclusive, true); final IOFileFilter maximumFilter = new SizeFileFilter(maxSizeInclusive + 1L, false); return minimumFilter.and(maximumFilter); } /** * Returns a filter that returns true if the file name ends with the specified text. * * @param suffix the file name suffix * @return a suffix checking filter * @see SuffixFileFilter */ public static IOFileFilter suffixFileFilter(final String suffix) { return new SuffixFileFilter(suffix); } /** * Returns a filter that returns true if the file name ends with the specified text. * * @param suffix the file name suffix * @param caseSensitivity how to handle case sensitivity, null means case-sensitive * @return a suffix checking filter * @see SuffixFileFilter * @since 2.0 */ public static IOFileFilter suffixFileFilter(final String suffix, final IOCase caseSensitivity) { return new SuffixFileFilter(suffix, caseSensitivity); } /** * Create a List of file filters. * * @param filters The file filters * @return The list of file filters * @throws IllegalArgumentException if the filters are null or contain a * null value. * @since 2.0 */ public static List toList(final IOFileFilter... filters) { if (filters == null) { throw new IllegalArgumentException("The filters must not be null"); } final List list = new ArrayList<>(filters.length); for (int i = 0; i < filters.length; i++) { if (filters[i] == null) { throw new IllegalArgumentException("The filter[" + i + "] is null"); } list.add(filters[i]); } return list; } /** * Returns a filter that always returns true. * * @return a true filter * @see TrueFileFilter#TRUE */ public static IOFileFilter trueFileFilter() { return TrueFileFilter.TRUE; } /** * FileFilterUtils is not normally instantiated. */ public FileFilterUtils() { } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/filefilter/HiddenFileFilter.java0100644 0000000 0000000 00000007136 13612062727 031673 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.filefilter; import java.io.File; import java.io.IOException; import java.io.Serializable; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.attribute.BasicFileAttributes; /** * This filter accepts {@code File}s that are hidden. *

* Example, showing how to print out a list of the * current directory's hidden files: *

*

Using Classic IO

*
 * File dir = new File(".");
 * String[] files = dir.list(HiddenFileFilter.HIDDEN);
 * for (String file : files) {
 *     System.out.println(file);
 * }
 * 
* *

* Example, showing how to print out a list of the * current directory's visible (i.e. not hidden) files: *

* *
 * File dir = new File(".");
 * String[] files = dir.list(HiddenFileFilter.VISIBLE);
 * for (String file : files) {
 *     System.out.println(file);
 * }
 * 
* *

Using NIO

*
 * final Path dir = Paths.get("");
 * final AccumulatorPathVisitor visitor = AccumulatorPathVisitor.withLongCounters(HiddenFileFilter.HIDDEN);
 * //
 * // Walk one dir
 * Files.walkFileTree(dir, Collections.emptySet(), 1, visitor);
 * System.out.println(visitor.getPathCounters());
 * System.out.println(visitor.getFileList());
 * //
 * visitor.getPathCounters().reset();
 * //
 * // Walk dir tree
 * Files.walkFileTree(dir, visitor);
 * System.out.println(visitor.getPathCounters());
 * System.out.println(visitor.getDirList());
 * System.out.println(visitor.getFileList());
 * 
* * @since 1.3 */ public class HiddenFileFilter extends AbstractFileFilter implements Serializable { /** Singleton instance of hidden filter */ public static final IOFileFilter HIDDEN = new HiddenFileFilter(); private static final long serialVersionUID = 8930842316112759062L; /** Singleton instance of visible filter */ public static final IOFileFilter VISIBLE = HIDDEN.negate(); /** * Restrictive constructor. */ protected HiddenFileFilter() { } /** * Checks to see if the file is hidden. * * @param file the File to check * @return {@code true} if the file is * hidden, otherwise {@code false}. */ @Override public boolean accept(final File file) { return file.isHidden(); } /** * Checks to see if the file is hidden. * @param file the File to check * * @return {@code true} if the file is * hidden, otherwise {@code false}. * @since 2.9.0 */ @Override public FileVisitResult accept(final Path file, final BasicFileAttributes attributes) { try { return toFileVisitResult(Files.isHidden(file), file); } catch (final IOException e) { return handle(e); } } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/filefilter/IOFileFilter.java0100644 0000000 0000000 00000006246 13612062727 031010 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.filefilter; import java.io.File; import java.io.FileFilter; import java.io.FilenameFilter; import java.nio.file.FileVisitResult; import java.nio.file.Path; import java.nio.file.attribute.BasicFileAttributes; import org.apache.commons.io.file.PathFilter; /** * An interface which brings the FileFilter, FilenameFilter, and PathFilter interfaces together. * * @since 1.0 */ public interface IOFileFilter extends FileFilter, FilenameFilter, PathFilter { /** * An empty String array. */ String[] EMPTY_STRING_ARRAY = {}; /** * Checks to see if the File should be accepted by this filter. *

* Defined in {@link java.io.FileFilter}. *

* * @param file the File to check. * @return true if this file matches the test. */ @Override boolean accept(File file); /** * Checks to see if the File should be accepted by this filter. *

* Defined in {@link java.io.FilenameFilter}. *

* * @param dir the directory File to check. * @param name the file name within the directory to check. * @return true if this file matches the test. */ @Override boolean accept(File dir, String name); /** * Checks to see if the Path should be accepted by this filter. * * @param path the Path to check. * @return true if this path matches the test. * @since 2.9.0 */ @Override default FileVisitResult accept(final Path path, final BasicFileAttributes attributes) { return AbstractFileFilter.toFileVisitResult(accept(path.toFile()), path); } /** * Creates a new "and" filter with this filter. * * @param fileFilter the filter to "and". * @return a new filter. * @since 2.9.0 */ default IOFileFilter and(final IOFileFilter fileFilter) { return new AndFileFilter(this, fileFilter); } /** * Creates a new "not" filter with this filter. * * @return a new filter. * @since 2.9.0 */ default IOFileFilter negate() { return new NotFileFilter(this); } /** * Creates a new "or" filter with this filter. * * @param fileFilter the filter to "or". * @return a new filter. * @since 2.9.0 */ default IOFileFilter or(final IOFileFilter fileFilter) { return new OrFileFilter(this, fileFilter); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/filefilter/MagicNumberFileFilter.java0100644 0000000 0000000 00000027273 13612062727 032675 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.filefilter; import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; import java.io.Serializable; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.nio.charset.Charset; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.attribute.BasicFileAttributes; import java.util.Arrays; import org.apache.commons.io.IOUtils; /** *

* File filter for matching files containing a "magic number". A magic number * is a unique series of bytes common to all files of a specific file format. * For instance, all Java class files begin with the bytes * {@code 0xCAFEBABE}. *

*

Using Classic IO

*
 * File dir = new File(".");
 * MagicNumberFileFilter javaClassFileFilter =
 *     MagicNumberFileFilter(new byte[] {(byte) 0xCA, (byte) 0xFE,
 *       (byte) 0xBA, (byte) 0xBE});
 * String[] javaClassFiles = dir.list(javaClassFileFilter);
 * for (String javaClassFile : javaClassFiles) {
 *     System.out.println(javaClassFile);
 * }
 * 
* *

* Sometimes, such as in the case of TAR files, the * magic number will be offset by a certain number of bytes in the file. In the * case of TAR archive files, this offset is 257 bytes. *

* *
 * File dir = new File(".");
 * MagicNumberFileFilter tarFileFilter =
 *     MagicNumberFileFilter("ustar", 257);
 * String[] tarFiles = dir.list(tarFileFilter);
 * for (String tarFile : tarFiles) {
 *     System.out.println(tarFile);
 * }
 * 
*

Using NIO

*
 * final Path dir = Paths.get("");
 * final AccumulatorPathVisitor visitor = AccumulatorPathVisitor.withLongCounters(MagicNumberFileFilter("ustar", 257));
 * //
 * // Walk one dir
 * Files.walkFileTree(dir, Collections.emptySet(), 1, visitor);
 * System.out.println(visitor.getPathCounters());
 * System.out.println(visitor.getFileList());
 * //
 * visitor.getPathCounters().reset();
 * //
 * // Walk dir tree
 * Files.walkFileTree(dir, visitor);
 * System.out.println(visitor.getPathCounters());
 * System.out.println(visitor.getDirList());
 * System.out.println(visitor.getFileList());
 * 
* * @since 2.0 * @see FileFilterUtils#magicNumberFileFilter(byte[]) * @see FileFilterUtils#magicNumberFileFilter(String) * @see FileFilterUtils#magicNumberFileFilter(byte[], long) * @see FileFilterUtils#magicNumberFileFilter(String, long) */ public class MagicNumberFileFilter extends AbstractFileFilter implements Serializable { /** * The serialization version unique identifier. */ private static final long serialVersionUID = -547733176983104172L; /** * The magic number to compare against the file's bytes at the provided * offset. */ private final byte[] magicNumbers; /** * The offset (in bytes) within the files that the magic number's bytes * should appear. */ private final long byteOffset; /** *

* Constructs a new MagicNumberFileFilter and associates it with the magic * number to test for in files. This constructor assumes a starting offset * of {@code 0}. *

* *

* It is important to note that the array is not cloned and that * any changes to the magic number array after construction will affect the * behavior of this file filter. *

* *
     * MagicNumberFileFilter javaClassFileFilter =
     *     MagicNumberFileFilter(new byte[] {(byte) 0xCA, (byte) 0xFE,
     *       (byte) 0xBA, (byte) 0xBE});
     * 
* * @param magicNumber the magic number to look for in the file. * * @throws IllegalArgumentException if {@code magicNumber} is * {@code null}, or contains no bytes. */ public MagicNumberFileFilter(final byte[] magicNumber) { this(magicNumber, 0); } /** *

* Constructs a new MagicNumberFileFilter and associates it with the magic * number to test for in files and the byte offset location in the file to * to look for that magic number. *

* *
     * MagicNumberFileFilter tarFileFilter =
     *     MagicNumberFileFilter(new byte[] {0x75, 0x73, 0x74, 0x61, 0x72}, 257);
     * 
* *
     * MagicNumberFileFilter javaClassFileFilter =
     *     MagicNumberFileFilter(new byte[] {0xCA, 0xFE, 0xBA, 0xBE}, 0);
     * 
* * @param magicNumber the magic number to look for in the file. * @param offset the byte offset in the file to start comparing bytes. * * @throws IllegalArgumentException if {@code magicNumber} is * {@code null}, or contains no bytes, or {@code offset} * is a negative number. */ public MagicNumberFileFilter(final byte[] magicNumber, final long offset) { if (magicNumber == null) { throw new IllegalArgumentException("The magic number cannot be null"); } if (magicNumber.length == 0) { throw new IllegalArgumentException("The magic number must contain at least one byte"); } if (offset < 0) { throw new IllegalArgumentException("The offset cannot be negative"); } this.magicNumbers = IOUtils.byteArray(magicNumber.length); System.arraycopy(magicNumber, 0, this.magicNumbers, 0, magicNumber.length); this.byteOffset = offset; } /** *

* Constructs a new MagicNumberFileFilter and associates it with the magic * number to test for in files. This constructor assumes a starting offset * of {@code 0}. *

* * Example usage: *
     * {@code
     * MagicNumberFileFilter xmlFileFilter =
     *     MagicNumberFileFilter("
     *
     * @param magicNumber the magic number to look for in the file.
     *        The string is converted to bytes using the platform default charset.
     *
     * @throws IllegalArgumentException if {@code magicNumber} is
     *         {@code null} or the empty String.
     */
    public MagicNumberFileFilter(final String magicNumber) {
        this(magicNumber, 0);
    }

    /**
     * 

* Constructs a new MagicNumberFileFilter and associates it with the magic * number to test for in files and the byte offset location in the file to * to look for that magic number. *

* *
     * MagicNumberFileFilter tarFileFilter =
     *     MagicNumberFileFilter("ustar", 257);
     * 
* * @param magicNumber the magic number to look for in the file. * The string is converted to bytes using the platform default charset. * @param offset the byte offset in the file to start comparing bytes. * * @throws IllegalArgumentException if {@code magicNumber} is * {@code null} or the empty String, or {@code offset} is * a negative number. */ public MagicNumberFileFilter(final String magicNumber, final long offset) { if (magicNumber == null) { throw new IllegalArgumentException("The magic number cannot be null"); } if (magicNumber.isEmpty()) { throw new IllegalArgumentException("The magic number must contain at least one byte"); } if (offset < 0) { throw new IllegalArgumentException("The offset cannot be negative"); } this.magicNumbers = magicNumber.getBytes(Charset.defaultCharset()); // explicitly uses the platform default // charset this.byteOffset = offset; } /** *

* Accepts the provided file if the file contains the file filter's magic * number at the specified offset. *

* *

* If any {@link IOException}s occur while reading the file, the file will * be rejected. *

* * @param file the file to accept or reject. * * @return {@code true} if the file contains the filter's magic number * at the specified offset, {@code false} otherwise. */ @Override public boolean accept(final File file) { if (file != null && file.isFile() && file.canRead()) { try { try (RandomAccessFile randomAccessFile = new RandomAccessFile(file, "r")) { final byte[] fileBytes = IOUtils.byteArray(this.magicNumbers.length); randomAccessFile.seek(byteOffset); final int read = randomAccessFile.read(fileBytes); if (read != magicNumbers.length) { return false; } return Arrays.equals(this.magicNumbers, fileBytes); } } catch (final IOException ioe) { // Do nothing, fall through and do not accept file } } return false; } /** *

* Accepts the provided file if the file contains the file filter's magic * number at the specified offset. *

* *

* If any {@link IOException}s occur while reading the file, the file will * be rejected. *

* @param file the file to accept or reject. * * @return {@code true} if the file contains the filter's magic number * at the specified offset, {@code false} otherwise. * @since 2.9.0 */ @Override public FileVisitResult accept(final Path file, final BasicFileAttributes attributes) { if (file != null && Files.isRegularFile(file) && Files.isReadable(file)) { try { try (final FileChannel fileChannel = FileChannel.open(file)) { final ByteBuffer byteBuffer = ByteBuffer.allocate(this.magicNumbers.length); final int read = fileChannel.read(byteBuffer); if (read != magicNumbers.length) { return FileVisitResult.TERMINATE; } return toFileVisitResult(Arrays.equals(this.magicNumbers, byteBuffer.array()), file); } } catch (final IOException ioe) { // Do nothing, fall through and do not accept file } } return FileVisitResult.TERMINATE; } /** * Returns a String representation of the file filter, which includes the * magic number bytes and byte offset. * * @return a String representation of the file filter. */ @Override public String toString() { final StringBuilder builder = new StringBuilder(super.toString()); builder.append("("); builder.append(new String(magicNumbers, Charset.defaultCharset()));// TODO perhaps use hex if value is not // printable builder.append(","); builder.append(this.byteOffset); builder.append(")"); return builder.toString(); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/filefilter/NameFileFilter.java0100644 0000000 0000000 00000017054 13612062727 031360 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.filefilter; import java.io.File; import java.io.Serializable; import java.nio.file.FileVisitResult; import java.nio.file.Path; import java.nio.file.attribute.BasicFileAttributes; import java.util.List; import java.util.Objects; import org.apache.commons.io.IOCase; /** * Filters file names for a certain name. *

* For example, to print all files and directories in the * current directory whose name is {@code Test}: *

*

Using Classic IO

*
 * File dir = new File(".");
 * String[] files = dir.list(new NameFileFilter("Test"));
 * for (String file : files) {
 *     System.out.println(file);
 * }
 * 
* *

Using NIO

*
 * final Path dir = Paths.get("");
 * final AccumulatorPathVisitor visitor = AccumulatorPathVisitor.withLongCounters(new NameFileFilter("Test"));
 * //
 * // Walk one dir
 * Files.walkFileTree(dir, Collections.emptySet(), 1, visitor);
 * System.out.println(visitor.getPathCounters());
 * System.out.println(visitor.getFileList());
 * //
 * visitor.getPathCounters().reset();
 * //
 * // Walk dir tree
 * Files.walkFileTree(dir, visitor);
 * System.out.println(visitor.getPathCounters());
 * System.out.println(visitor.getDirList());
 * System.out.println(visitor.getFileList());
 * 
* * @since 1.0 * @see FileFilterUtils#nameFileFilter(String) * @see FileFilterUtils#nameFileFilter(String, IOCase) */ public class NameFileFilter extends AbstractFileFilter implements Serializable { private static final long serialVersionUID = 176844364689077340L; /** The file names to search for */ private final String[] names; /** Whether the comparison is case sensitive. */ private final IOCase caseSensitivity; /** * Constructs a new case-sensitive name file filter for a list of names. * * @param names the names to allow, must not be null * @throws IllegalArgumentException if the name list is null * @throws ClassCastException if the list does not contain Strings */ public NameFileFilter(final List names) { this(names, null); } /** * Constructs a new name file filter for a list of names specifying case-sensitivity. * * @param names the names to allow, must not be null * @param caseSensitivity how to handle case sensitivity, null means case-sensitive * @throws IllegalArgumentException if the name list is null * @throws ClassCastException if the list does not contain Strings */ public NameFileFilter(final List names, final IOCase caseSensitivity) { if (names == null) { throw new IllegalArgumentException("The list of names must not be null"); } this.names = names.toArray(EMPTY_STRING_ARRAY); this.caseSensitivity = toIOCase(caseSensitivity); } /** * Constructs a new case-sensitive name file filter for a single name. * * @param name the name to allow, must not be null * @throws IllegalArgumentException if the name is null */ public NameFileFilter(final String name) { this(name, IOCase.SENSITIVE); } /** * Constructs a new case-sensitive name file filter for an array of names. *

* The array is not cloned, so could be changed after constructing the * instance. This would be inadvisable however. *

* * @param names the names to allow, must not be null * @throws IllegalArgumentException if the names array is null */ public NameFileFilter(final String... names) { this(names, IOCase.SENSITIVE); } /** * Construct a new name file filter specifying case-sensitivity. * * @param name the name to allow, must not be null * @param caseSensitivity how to handle case sensitivity, null means case-sensitive * @throws IllegalArgumentException if the name is null */ public NameFileFilter(final String name, final IOCase caseSensitivity) { if (name == null) { throw new IllegalArgumentException("The wildcard must not be null"); } this.names = new String[] {name}; this.caseSensitivity = toIOCase(caseSensitivity); } /** * Constructs a new name file filter for an array of names specifying case-sensitivity. * * @param names the names to allow, must not be null * @param caseSensitivity how to handle case sensitivity, null means case-sensitive * @throws IllegalArgumentException if the names array is null */ public NameFileFilter(final String[] names, final IOCase caseSensitivity) { if (names == null) { throw new IllegalArgumentException("The array of names must not be null"); } this.names = new String[names.length]; System.arraycopy(names, 0, this.names, 0, names.length); this.caseSensitivity = toIOCase(caseSensitivity); } /** * Checks to see if the file name matches. * * @param file the File to check * @return true if the file name matches */ @Override public boolean accept(final File file) { return acceptBaseName(file.getName()); } /** * Checks to see if the file name matches. * * @param dir the File directory (ignored) * @param name the file name * @return true if the file name matches */ @Override public boolean accept(final File dir, final String name) { return acceptBaseName(name); } /** * Checks to see if the file name matches. * @param file the File to check * * @return true if the file name matches * @since 2.9.0 */ @Override public FileVisitResult accept(final Path file, final BasicFileAttributes attributes) { return toFileVisitResult(acceptBaseName(Objects.toString(file.getFileName(), null)), file); } private boolean acceptBaseName(final String baseName) { for (final String testName : names) { if (caseSensitivity.checkEquals(baseName, testName)) { return true; } } return false; } private IOCase toIOCase(final IOCase caseSensitivity) { return caseSensitivity == null ? IOCase.SENSITIVE : caseSensitivity; } /** * Provide a String representation of this file filter. * * @return a String representation */ @Override public String toString() { final StringBuilder buffer = new StringBuilder(); buffer.append(super.toString()); buffer.append("("); if (names != null) { for (int i = 0; i < names.length; i++) { if (i > 0) { buffer.append(","); } buffer.append(names[i]); } } buffer.append(")"); return buffer.toString(); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/filefilter/NotFileFilter.java0100644 0000000 0000000 00000006267 13612062727 031244 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.filefilter; import java.io.File; import java.io.Serializable; import java.nio.file.FileVisitResult; import java.nio.file.Path; import java.nio.file.attribute.BasicFileAttributes; /** * This filter produces a logical NOT of the filters specified. * * @since 1.0 * @see FileFilterUtils#notFileFilter(IOFileFilter) */ public class NotFileFilter extends AbstractFileFilter implements Serializable { private static final long serialVersionUID = 6131563330944994230L; /** The filter */ private final IOFileFilter filter; /** * Constructs a new file filter that NOTs the result of another filter. * * @param filter the filter, must not be null * @throws IllegalArgumentException if the filter is null */ public NotFileFilter(final IOFileFilter filter) { if (filter == null) { throw new IllegalArgumentException("The filter must not be null"); } this.filter = filter; } /** * Returns the logical NOT of the underlying filter's return value for the same File. * * @param file the File to check * @return true if the filter returns false */ @Override public boolean accept(final File file) { return !filter.accept(file); } /** * Returns the logical NOT of the underlying filter's return value for the same arguments. * * @param file the File directory * @param name the file name * @return true if the filter returns false */ @Override public boolean accept(final File file, final String name) { return !filter.accept(file, name); } /** * Returns the logical NOT of the underlying filter's return value for the same File. * @param file the File to check * * @return true if the filter returns false * @since 2.9.0 */ @Override public FileVisitResult accept(final Path file, final BasicFileAttributes attributes) { return not(filter.accept(file, attributes)); } private FileVisitResult not(final FileVisitResult accept) { return accept == FileVisitResult.CONTINUE ? FileVisitResult.TERMINATE : FileVisitResult.CONTINUE; } /** * Provide a String representation of this file filter. * * @return a String representation */ @Override public String toString() { return "NOT (" + filter.toString() + ")"; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/filefilter/OrFileFilter.java0100644 0000000 0000000 00000014247 13612062727 031061 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.filefilter; import java.io.File; import java.io.Serializable; import java.nio.file.FileVisitResult; import java.nio.file.Path; import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Objects; /** * A {@link java.io.FileFilter} providing conditional OR logic across a list of file filters. This filter returns * {@code true} if any filters in the list return {@code true}. Otherwise, it returns {@code false}. Checking of the * file filter list stops when the first filter returns {@code true}. * * @since 1.0 * @see FileFilterUtils#or(IOFileFilter...) */ public class OrFileFilter extends AbstractFileFilter implements ConditionalFileFilter, Serializable { private static final long serialVersionUID = 5767770777065432721L; /** The list of file filters. */ private final List fileFilters; /** * Constructs a new instance of {@code OrFileFilter}. * * @since 1.1 */ public OrFileFilter() { this(0); } /** * Constructs a new instance with the given initial list. * * @param initialList the initial list. */ private OrFileFilter(final ArrayList initialList) { this.fileFilters = Objects.requireNonNull(initialList, "initialList"); } /** * Constructs a new instance with the given initial capacity. * * @param initialCapacity the initial capacity. */ private OrFileFilter(final int initialCapacity) { this(new ArrayList<>(initialCapacity)); } /** * Constructs a new instance for the give filters. * @param fileFilters filters to OR. * * @since 2.9.0 */ public OrFileFilter(final IOFileFilter... fileFilters) { this(Objects.requireNonNull(fileFilters, "fileFilters").length); addFileFilter(fileFilters); } /** * Constructs a new file filter that ORs the result of other filters. * * @param filter1 the first filter, must not be null * @param filter2 the second filter, must not be null * @throws IllegalArgumentException if either filter is null */ public OrFileFilter(final IOFileFilter filter1, final IOFileFilter filter2) { this(2); addFileFilter(filter1); addFileFilter(filter2); } /** * Constructs a new instance of {@code OrFileFilter} with the specified filters. * * @param fileFilters the file filters for this filter, copied. * @since 1.1 */ public OrFileFilter(final List fileFilters) { this(new ArrayList<>(Objects.requireNonNull(fileFilters, "fileFilters"))); } /** * {@inheritDoc} */ @Override public boolean accept(final File file) { for (final IOFileFilter fileFilter : fileFilters) { if (fileFilter.accept(file)) { return true; } } return false; } /** * {@inheritDoc} */ @Override public boolean accept(final File file, final String name) { for (final IOFileFilter fileFilter : fileFilters) { if (fileFilter.accept(file, name)) { return true; } } return false; } /** * {@inheritDoc} */ @Override public FileVisitResult accept(final Path file, final BasicFileAttributes attributes) { for (final IOFileFilter fileFilter : fileFilters) { if (fileFilter.accept(file, attributes) == FileVisitResult.CONTINUE) { return FileVisitResult.CONTINUE; } } return FileVisitResult.TERMINATE; } /** * {@inheritDoc} */ @Override public void addFileFilter(final IOFileFilter fileFilter) { this.fileFilters.add(Objects.requireNonNull(fileFilter, "fileFilter")); } /** * Adds the given file filters. * * @param fileFilters the filters to add. * @since 2.9.0 */ public void addFileFilter(final IOFileFilter... fileFilters) { for (final IOFileFilter fileFilter : Objects.requireNonNull(fileFilters, "fileFilters")) { addFileFilter(fileFilter); } } /** * {@inheritDoc} */ @Override public List getFileFilters() { return Collections.unmodifiableList(this.fileFilters); } /** * {@inheritDoc} */ @Override public boolean removeFileFilter(final IOFileFilter fileFilter) { return this.fileFilters.remove(fileFilter); } /** * {@inheritDoc} */ @Override public void setFileFilters(final List fileFilters) { this.fileFilters.clear(); this.fileFilters.addAll(Objects.requireNonNull(fileFilters, "fileFilters")); } /** * Provide a String representation of this file filter. * * @return a String representation */ @Override public String toString() { final StringBuilder buffer = new StringBuilder(); buffer.append(super.toString()); buffer.append("("); if (fileFilters != null) { for (int i = 0; i < fileFilters.size(); i++) { if (i > 0) { buffer.append(","); } buffer.append(fileFilters.get(i)); } } buffer.append(")"); return buffer.toString(); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/filefilter/PathEqualsFileFilter.java0100644 0000000 0000000 00000003552 13612062727 032545 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.filefilter; import java.io.File; import java.nio.file.FileVisitResult; import java.nio.file.Path; import java.nio.file.attribute.BasicFileAttributes; import java.util.Objects; /** * Accepts only an exact {@link Path} object match. You can use this filter to visit the start directory when walking a * file tree with * {@link java.nio.file.Files#walkFileTree(java.nio.file.Path, java.util.Set, int, java.nio.file.FileVisitor)}. * * @since 2.9.0 */ public class PathEqualsFileFilter extends AbstractFileFilter { private final Path path; /** * Constructs a new instance for the given {@link Path}. * * @param file The file to match. */ public PathEqualsFileFilter(final Path file) { this.path = file; } @Override public boolean accept(final File file) { return Objects.equals(this.path, file.toPath()); } @Override public FileVisitResult accept(final Path path, final BasicFileAttributes attributes) { return toFileVisitResult(Objects.equals(this.path, path), path); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/filefilter/PathVisitorFileFilter.java0100644 0000000 0000000 00000005555 13612062727 032757 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.filefilter; import java.io.File; import java.io.IOException; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.attribute.BasicFileAttributes; import org.apache.commons.io.file.NoopPathVisitor; import org.apache.commons.io.file.PathUtils; import org.apache.commons.io.file.PathVisitor; /** * A file filter backed by a path visitor. * * @since 2.9.0 */ public class PathVisitorFileFilter extends AbstractFileFilter { private final PathVisitor pathVisitor; /** * Constructs a new instance that will forward calls to the given visitor. * * @param pathVisitor visit me. */ public PathVisitorFileFilter(final PathVisitor pathVisitor) { this.pathVisitor = pathVisitor == null ? NoopPathVisitor.INSTANCE : pathVisitor; } @Override public boolean accept(final File file) { try { final Path path = file.toPath(); return visitFile(path, file.exists() ? PathUtils.readBasicFileAttributes(path) : null) == FileVisitResult.CONTINUE; } catch (final IOException e) { return handle(e) == FileVisitResult.CONTINUE; } } @Override public boolean accept(final File dir, final String name) { try { final Path path = dir.toPath().resolve(name); return accept(path, PathUtils.readBasicFileAttributes(path)) == FileVisitResult.CONTINUE; } catch (final IOException e) { return handle(e) == FileVisitResult.CONTINUE; } } @Override public FileVisitResult accept(final Path path, final BasicFileAttributes attributes) { try { return Files.isDirectory(path) ? pathVisitor.postVisitDirectory(path, null) : visitFile(path, attributes); } catch (final IOException e) { return handle(e); } } @Override public FileVisitResult visitFile(final Path path, final BasicFileAttributes attributes) throws IOException { return pathVisitor.visitFile(path, attributes); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/filefilter/PrefixFileFilter.java0100644 0000000 0000000 00000017557 13612062727 031745 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.filefilter; import java.io.File; import java.io.Serializable; import java.nio.file.FileVisitResult; import java.nio.file.Path; import java.nio.file.attribute.BasicFileAttributes; import java.util.List; import org.apache.commons.io.IOCase; /** * Filters file names for a certain prefix. *

* For example, to print all files and directories in the * current directory whose name starts with {@code Test}: *

*

Using Classic IO

*
 * File dir = new File(".");
 * String[] files = dir.list(new PrefixFileFilter("Test"));
 * for (String file : files) {
 *     System.out.println(file);
 * }
 * 
* *

Using NIO

*
 * final Path dir = Paths.get("");
 * final AccumulatorPathVisitor visitor = AccumulatorPathVisitor.withLongCounters(new PrefixFileFilter("Test"));
 * //
 * // Walk one dir
 * Files.walkFileTree(dir, Collections.emptySet(), 1, visitor);
 * System.out.println(visitor.getPathCounters());
 * System.out.println(visitor.getFileList());
 * //
 * visitor.getPathCounters().reset();
 * //
 * // Walk dir tree
 * Files.walkFileTree(dir, visitor);
 * System.out.println(visitor.getPathCounters());
 * System.out.println(visitor.getDirList());
 * System.out.println(visitor.getFileList());
 * 
* * @since 1.0 * @see FileFilterUtils#prefixFileFilter(String) * @see FileFilterUtils#prefixFileFilter(String, IOCase) */ public class PrefixFileFilter extends AbstractFileFilter implements Serializable { private static final long serialVersionUID = 8533897440809599867L; /** The file name prefixes to search for */ private final String[] prefixes; /** Whether the comparison is case sensitive. */ private final IOCase caseSensitivity; /** * Constructs a new Prefix file filter for a list of prefixes. * * @param prefixes the prefixes to allow, must not be null * @throws IllegalArgumentException if the prefix list is null * @throws ClassCastException if the list does not contain Strings */ public PrefixFileFilter(final List prefixes) { this(prefixes, IOCase.SENSITIVE); } /** * Constructs a new Prefix file filter for a list of prefixes * specifying case-sensitivity. * * @param prefixes the prefixes to allow, must not be null * @param caseSensitivity how to handle case sensitivity, null means case-sensitive * @throws IllegalArgumentException if the prefix list is null * @throws ClassCastException if the list does not contain Strings * @since 1.4 */ public PrefixFileFilter(final List prefixes, final IOCase caseSensitivity) { if (prefixes == null) { throw new IllegalArgumentException("The list of prefixes must not be null"); } this.prefixes = prefixes.toArray(EMPTY_STRING_ARRAY); this.caseSensitivity = caseSensitivity == null ? IOCase.SENSITIVE : caseSensitivity; } /** * Constructs a new Prefix file filter for a single prefix. * * @param prefix the prefix to allow, must not be null * @throws IllegalArgumentException if the prefix is null */ public PrefixFileFilter(final String prefix) { this(prefix, IOCase.SENSITIVE); } /** * Constructs a new Prefix file filter for any of an array of prefixes. *

* The array is not cloned, so could be changed after constructing the * instance. This would be inadvisable however. * * @param prefixes the prefixes to allow, must not be null * @throws IllegalArgumentException if the prefix array is null */ public PrefixFileFilter(final String... prefixes) { this(prefixes, IOCase.SENSITIVE); } /** * Constructs a new Prefix file filter for a single prefix * specifying case-sensitivity. * * @param prefix the prefix to allow, must not be null * @param caseSensitivity how to handle case sensitivity, null means case-sensitive * @throws IllegalArgumentException if the prefix is null * @since 1.4 */ public PrefixFileFilter(final String prefix, final IOCase caseSensitivity) { if (prefix == null) { throw new IllegalArgumentException("The prefix must not be null"); } this.prefixes = new String[] {prefix}; this.caseSensitivity = caseSensitivity == null ? IOCase.SENSITIVE : caseSensitivity; } /** * Constructs a new Prefix file filter for any of an array of prefixes * specifying case-sensitivity. * * @param prefixes the prefixes to allow, must not be null * @param caseSensitivity how to handle case sensitivity, null means case-sensitive * @throws IllegalArgumentException if the prefix is null * @since 1.4 */ public PrefixFileFilter(final String[] prefixes, final IOCase caseSensitivity) { if (prefixes == null) { throw new IllegalArgumentException("The array of prefixes must not be null"); } this.prefixes = new String[prefixes.length]; System.arraycopy(prefixes, 0, this.prefixes, 0, prefixes.length); this.caseSensitivity = caseSensitivity == null ? IOCase.SENSITIVE : caseSensitivity; } /** * Checks to see if the file name starts with the prefix. * * @param file the File to check * @return true if the file name starts with one of our prefixes */ @Override public boolean accept(final File file) { return accept(file == null ? null : file.getName()); } /** * Checks to see if the file name starts with the prefix. * * @param file the File directory * @param name the file name * @return true if the file name starts with one of our prefixes */ @Override public boolean accept(final File file, final String name) { return accept(name); } /** * Checks to see if the file name starts with the prefix. * @param file the File to check * * @return true if the file name starts with one of our prefixes * @since 2.9.0 */ @Override public FileVisitResult accept(final Path file, final BasicFileAttributes attributes) { final Path fileName = file.getFileName(); return toFileVisitResult(accept(fileName == null ? null : fileName.toFile()), file); } private boolean accept(final String name) { for (final String prefix : prefixes) { if (caseSensitivity.checkStartsWith(name, prefix)) { return true; } } return false; } /** * Provide a String representation of this file filter. * * @return a String representation */ @Override public String toString() { final StringBuilder buffer = new StringBuilder(); buffer.append(super.toString()); buffer.append("("); if (prefixes != null) { for (int i = 0; i < prefixes.length; i++) { if (i > 0) { buffer.append(","); } buffer.append(prefixes[i]); } } buffer.append(")"); return buffer.toString(); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/filefilter/RegexFileFilter.java0100644 0000000 0000000 00000014470 13612062727 031551 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.filefilter; import java.io.File; import java.io.Serializable; import java.nio.file.FileVisitResult; import java.nio.file.Path; import java.nio.file.attribute.BasicFileAttributes; import java.util.function.Function; import java.util.regex.Pattern; import org.apache.commons.io.IOCase; /** * Filters files using supplied regular expression(s). *

* See java.util.regex.Pattern for regex matching rules. *

*

Using Classic IO

*

* e.g. * *

 * File dir = new File(".");
 * FileFilter fileFilter = new RegexFileFilter("^.*[tT]est(-\\d+)?\\.java$");
 * File[] files = dir.listFiles(fileFilter);
 * for (String file : files) {
 *     System.out.println(file);
 * }
 * 
* *

Using NIO

* *
 * final Path dir = Paths.get("");
 * final AccumulatorPathVisitor visitor = AccumulatorPathVisitor.withLongCounters(new RegexFileFilter("^.*[tT]est(-\\d+)?\\.java$"));
 * //
 * // Walk one dir
 * Files.walkFileTree(dir, Collections.emptySet(), 1, visitor);
 * System.out.println(visitor.getPathCounters());
 * System.out.println(visitor.getFileList());
 * //
 * visitor.getPathCounters().reset();
 * //
 * // Walk dir tree
 * Files.walkFileTree(dir, visitor);
 * System.out.println(visitor.getPathCounters());
 * System.out.println(visitor.getDirList());
 * System.out.println(visitor.getFileList());
 * 
* * @since 1.4 */ public class RegexFileFilter extends AbstractFileFilter implements Serializable { private static final long serialVersionUID = 4269646126155225062L; /** * Compiles the given pattern source. * * @param pattern the source pattern. * @param flags the compilation flags. * @return a new Pattern. */ private static Pattern compile(final String pattern, final int flags) { if (pattern == null) { throw new IllegalArgumentException("Pattern is missing"); } return Pattern.compile(pattern, flags); } /** * Converts IOCase to Pattern compilation flags. * * @param caseSensitivity case-sensitivity. * @return Pattern compilation flags. */ private static int toFlags(final IOCase caseSensitivity) { return IOCase.isCaseSensitive(caseSensitivity) ? Pattern.CASE_INSENSITIVE : 0; } /** The regular expression pattern that will be used to match file names. */ private final Pattern pattern; /** How convert a path to a string. */ private final Function pathToString; /** * Constructs a new regular expression filter for a compiled regular expression * * @param pattern regular expression to match. * @throws IllegalArgumentException if the pattern is null. */ public RegexFileFilter(final Pattern pattern) { this(pattern, p -> p.getFileName().toString()); } /** * Constructs a new regular expression filter for a compiled regular expression * * @param pattern regular expression to match. * @param pathToString How convert a path to a string. * @throws IllegalArgumentException if the pattern is null. * @since 2.10.0 */ public RegexFileFilter(final Pattern pattern, final Function pathToString) { if (pattern == null) { throw new IllegalArgumentException("Pattern is missing"); } this.pattern = pattern; this.pathToString = pathToString; } /** * Constructs a new regular expression filter. * * @param pattern regular string expression to match * @throws IllegalArgumentException if the pattern is null */ public RegexFileFilter(final String pattern) { this(pattern, 0); } /** * Constructs a new regular expression filter with the specified flags. * * @param pattern regular string expression to match * @param flags pattern flags - e.g. {@link Pattern#CASE_INSENSITIVE} * @throws IllegalArgumentException if the pattern is null */ public RegexFileFilter(final String pattern, final int flags) { this(compile(pattern, flags)); } /** * Constructs a new regular expression filter with the specified flags case sensitivity. * * @param pattern regular string expression to match * @param caseSensitivity how to handle case sensitivity, null means case-sensitive * @throws IllegalArgumentException if the pattern is null */ public RegexFileFilter(final String pattern, final IOCase caseSensitivity) { this(compile(pattern, toFlags(caseSensitivity))); } /** * Checks to see if the file name matches one of the regular expressions. * * @param dir the file directory (ignored) * @param name the file name * @return true if the file name matches one of the regular expressions */ @Override public boolean accept(final File dir, final String name) { return pattern.matcher(name).matches(); } /** * Checks to see if the file name matches one of the regular expressions. * * @param path the path * @param attributes the path attributes * @return true if the file name matches one of the regular expressions */ @Override public FileVisitResult accept(final Path path, final BasicFileAttributes attributes) { return toFileVisitResult(pattern.matcher(pathToString.apply(path)).matches(), path); } /** * Returns a debug string. * * @since 2.10.0 */ @Override public String toString() { return "RegexFileFilter [pattern=" + pattern + "]"; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/filefilter/SizeFileFilter.java0100644 0000000 0000000 00000012341 13612062727 031404 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.filefilter; import java.io.File; import java.io.IOException; import java.io.Serializable; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.attribute.BasicFileAttributes; /** * Filters files based on size, can filter either smaller files or * files equal to or larger than a given threshold. *

* For example, to print all files and directories in the * current directory whose size is greater than 1 MB: *

*

Using Classic IO

*
 * File dir = new File(".");
 * String[] files = dir.list(new SizeFileFilter(1024 * 1024));
 * for (String file : files) {
 *     System.out.println(file);
 * }
 * 
* *

Using NIO

*
 * final Path dir = Paths.get("");
 * final AccumulatorPathVisitor visitor = AccumulatorPathVisitor.withLongCounters(new SizeFileFilter(1024 * 1024));
 * //
 * // Walk one dir
 * Files.walkFileTree(dir, Collections.emptySet(), 1, visitor);
 * System.out.println(visitor.getPathCounters());
 * System.out.println(visitor.getFileList());
 * //
 * visitor.getPathCounters().reset();
 * //
 * // Walk dir tree
 * Files.walkFileTree(dir, visitor);
 * System.out.println(visitor.getPathCounters());
 * System.out.println(visitor.getDirList());
 * System.out.println(visitor.getFileList());
 * 
* * @since 1.2 * @see FileFilterUtils#sizeFileFilter(long) * @see FileFilterUtils#sizeFileFilter(long, boolean) * @see FileFilterUtils#sizeRangeFileFilter(long, long) */ public class SizeFileFilter extends AbstractFileFilter implements Serializable { private static final long serialVersionUID = 7388077430788600069L; /** Whether the files accepted will be larger or smaller. */ private final boolean acceptLarger; /** The size threshold. */ private final long size; /** * Constructs a new size file filter for files equal to or * larger than a certain size. * * @param size the threshold size of the files * @throws IllegalArgumentException if the size is negative */ public SizeFileFilter(final long size) { this(size, true); } /** * Constructs a new size file filter for files based on a certain size * threshold. * * @param size the threshold size of the files * @param acceptLarger if true, files equal to or larger are accepted, * otherwise smaller ones (but not equal to) * @throws IllegalArgumentException if the size is negative */ public SizeFileFilter(final long size, final boolean acceptLarger) { if (size < 0) { throw new IllegalArgumentException("The size must be non-negative"); } this.size = size; this.acceptLarger = acceptLarger; } /** * Checks to see if the size of the file is favorable. *

* If size equals threshold and smaller files are required, * file IS NOT selected. * If size equals threshold and larger files are required, * file IS selected. *

* * @param file the File to check * @return true if the file name matches */ @Override public boolean accept(final File file) { return accept(file.length()); } private boolean accept(final long length) { return acceptLarger != length < size; } /** * Checks to see if the size of the file is favorable. *

* If size equals threshold and smaller files are required, * file IS NOT selected. * If size equals threshold and larger files are required, * file IS selected. *

* @param file the File to check * * @return true if the file name matches */ @Override public FileVisitResult accept(final Path file, final BasicFileAttributes attributes) { try { return toFileVisitResult(accept(Files.size(file)), file); } catch (final IOException e) { return handle(e); } } /** * Provide a String representation of this file filter. * * @return a String representation */ @Override public String toString() { final String condition = acceptLarger ? ">=" : "<"; return super.toString() + "(" + condition + size + ")"; } @Override public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) throws IOException { return toFileVisitResult(accept(Files.size(file)), file); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/filefilter/SuffixFileFilter.java0100644 0000000 0000000 00000017573 13612062727 031752 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.filefilter; import java.io.File; import java.io.Serializable; import java.nio.file.FileVisitResult; import java.nio.file.Path; import java.nio.file.attribute.BasicFileAttributes; import java.util.List; import java.util.Objects; import org.apache.commons.io.IOCase; /** * Filters files based on the suffix (what the file name ends with). * This is used in retrieving all the files of a particular type. *

* For example, to retrieve and print all {@code *.java} files * in the current directory: *

*

Using Classic IO

*
 * File dir = new File(".");
 * String[] files = dir.list(new SuffixFileFilter(".java"));
 * for (String file : files) {
 *     System.out.println(file);
 * }
 * 
* *

Using NIO

*
 * final Path dir = Paths.get("");
 * final AccumulatorPathVisitor visitor = AccumulatorPathVisitor.withLongCounters(new SuffixFileFilter(".java"));
 * //
 * // Walk one dir
 * Files.walkFileTree(dir, Collections.emptySet(), 1, visitor);
 * System.out.println(visitor.getPathCounters());
 * System.out.println(visitor.getFileList());
 * //
 * visitor.getPathCounters().reset();
 * //
 * // Walk dir tree
 * Files.walkFileTree(dir, visitor);
 * System.out.println(visitor.getPathCounters());
 * System.out.println(visitor.getDirList());
 * System.out.println(visitor.getFileList());
 * 
* * @since 1.0 * @see FileFilterUtils#suffixFileFilter(String) * @see FileFilterUtils#suffixFileFilter(String, IOCase) */ public class SuffixFileFilter extends AbstractFileFilter implements Serializable { private static final long serialVersionUID = -3389157631240246157L; /** The file name suffixes to search for */ private final String[] suffixes; /** Whether the comparison is case sensitive. */ private final IOCase caseSensitivity; /** * Constructs a new Suffix file filter for a list of suffixes. * * @param suffixes the suffixes to allow, must not be null * @throws IllegalArgumentException if the suffix list is null * @throws ClassCastException if the list does not contain Strings */ public SuffixFileFilter(final List suffixes) { this(suffixes, IOCase.SENSITIVE); } /** * Constructs a new Suffix file filter for a list of suffixes * specifying case-sensitivity. * * @param suffixes the suffixes to allow, must not be null * @param caseSensitivity how to handle case sensitivity, null means case-sensitive * @throws IllegalArgumentException if the suffix list is null * @throws ClassCastException if the list does not contain Strings * @since 1.4 */ public SuffixFileFilter(final List suffixes, final IOCase caseSensitivity) { if (suffixes == null) { throw new IllegalArgumentException("The list of suffixes must not be null"); } this.suffixes = suffixes.toArray(EMPTY_STRING_ARRAY); this.caseSensitivity = caseSensitivity == null ? IOCase.SENSITIVE : caseSensitivity; } /** * Constructs a new Suffix file filter for a single extension. * * @param suffix the suffix to allow, must not be null * @throws IllegalArgumentException if the suffix is null */ public SuffixFileFilter(final String suffix) { this(suffix, IOCase.SENSITIVE); } /** * Constructs a new Suffix file filter for an array of suffixes. *

* The array is not cloned, so could be changed after constructing the * instance. This would be inadvisable however. * * @param suffixes the suffixes to allow, must not be null * @throws IllegalArgumentException if the suffix array is null */ public SuffixFileFilter(final String... suffixes) { this(suffixes, IOCase.SENSITIVE); } /** * Constructs a new Suffix file filter for a single extension * specifying case-sensitivity. * * @param suffix the suffix to allow, must not be null * @param caseSensitivity how to handle case sensitivity, null means case-sensitive * @throws IllegalArgumentException if the suffix is null * @since 1.4 */ public SuffixFileFilter(final String suffix, final IOCase caseSensitivity) { if (suffix == null) { throw new IllegalArgumentException("The suffix must not be null"); } this.suffixes = new String[] {suffix}; this.caseSensitivity = caseSensitivity == null ? IOCase.SENSITIVE : caseSensitivity; } /** * Constructs a new Suffix file filter for an array of suffixes * specifying case-sensitivity. * * @param suffixes the suffixes to allow, must not be null * @param caseSensitivity how to handle case sensitivity, null means case-sensitive * @throws IllegalArgumentException if the suffix array is null * @since 1.4 */ public SuffixFileFilter(final String[] suffixes, final IOCase caseSensitivity) { if (suffixes == null) { throw new IllegalArgumentException("The array of suffixes must not be null"); } this.suffixes = new String[suffixes.length]; System.arraycopy(suffixes, 0, this.suffixes, 0, suffixes.length); this.caseSensitivity = caseSensitivity == null ? IOCase.SENSITIVE : caseSensitivity; } /** * Checks to see if the file name ends with the suffix. * * @param file the File to check * @return true if the file name ends with one of our suffixes */ @Override public boolean accept(final File file) { return accept(file.getName()); } /** * Checks to see if the file name ends with the suffix. * * @param file the File directory * @param name the file name * @return true if the file name ends with one of our suffixes */ @Override public boolean accept(final File file, final String name) { return accept(name); } /** * Checks to see if the file name ends with the suffix. * @param file the File to check * * @return true if the file name ends with one of our suffixes * @since 2.9.0 */ @Override public FileVisitResult accept(final Path file, final BasicFileAttributes attributes) { return toFileVisitResult(accept(Objects.toString(file.getFileName(), null)), file); } private boolean accept(final String name) { for (final String suffix : this.suffixes) { if (caseSensitivity.checkEndsWith(name, suffix)) { return true; } } return false; } /** * Provide a String representation of this file filter. * * @return a String representation */ @Override public String toString() { final StringBuilder buffer = new StringBuilder(); buffer.append(super.toString()); buffer.append("("); if (suffixes != null) { for (int i = 0; i < suffixes.length; i++) { if (i > 0) { buffer.append(","); } buffer.append(suffixes[i]); } } buffer.append(")"); return buffer.toString(); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/filefilter/SymbolicLinkFileFilter.java0100644 0000000 0000000 00000006025 13612062727 033073 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.filefilter; import java.io.File; import java.io.Serializable; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.attribute.BasicFileAttributes; /** * This filter accepts {@code File}s that are symbolic links. *

* For example, here is how to print out a list of the real files * within the current directory: *

*

Using Classic IO

*
 * File dir = new File(".");
 * String[] files = dir.list(SymbolicLinkFileFilter.INSTANCE);
 * for (String file : files) {
 *     System.out.println(file);
 * }
 * 
* *

Using NIO

*
 * final Path dir = Paths.get("");
 * final AccumulatorPathVisitor visitor = AccumulatorPathVisitor.withLongCounters(SymbolicLinkFileFilter.FILE);
 * //
 * // Walk one dir
 * Files.walkFileTree(dir, Collections.emptySet(), 1, visitor);
 * System.out.println(visitor.getPathCounters());
 * System.out.println(visitor.getFileList());
 * //
 * visitor.getPathCounters().reset();
 * //
 * // Walk dir tree
 * Files.walkFileTree(dir, visitor);
 * System.out.println(visitor.getPathCounters());
 * System.out.println(visitor.getDirList());
 * System.out.println(visitor.getFileList());
 * 
* * @since 2.11.0 * @see FileFilterUtils#fileFileFilter() */ public class SymbolicLinkFileFilter extends AbstractFileFilter implements Serializable { /** * Singleton instance of file filter. */ public static final SymbolicLinkFileFilter INSTANCE = new SymbolicLinkFileFilter(); private static final long serialVersionUID = 1L; /** * Restrictive constructor. */ protected SymbolicLinkFileFilter() { } /** * Checks to see if the file is a file. * * @param file the File to check * @return true if the file is a file */ @Override public boolean accept(final File file) { return file.isFile(); } /** * Checks to see if the file is a file. * @param file the File to check * * @return true if the file is a file */ @Override public FileVisitResult accept(final Path file, final BasicFileAttributes attributes) { return toFileVisitResult(Files.isSymbolicLink(file), file); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/filefilter/TrueFileFilter.java0100644 0000000 0000000 00000005777 13612062727 031430 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.filefilter; import java.io.File; import java.io.Serializable; import java.nio.file.FileVisitResult; import java.nio.file.Path; import java.nio.file.attribute.BasicFileAttributes; /** * A file filter that always returns true. * * @since 1.0 * @see FileFilterUtils#trueFileFilter() */ public class TrueFileFilter implements IOFileFilter, Serializable { private static final String TO_STRING = Boolean.TRUE.toString(); private static final long serialVersionUID = 8782512160909720199L; /** * Singleton instance of true filter. * * @since 1.3 */ public static final IOFileFilter TRUE = new TrueFileFilter(); /** * Singleton instance of true filter. Please use the identical TrueFileFilter.TRUE constant. The new name is more * JDK 1.5 friendly as it doesn't clash with other values when using static imports. */ public static final IOFileFilter INSTANCE = TRUE; /** * Restrictive constructor. */ protected TrueFileFilter() { } /** * Returns true. * * @param file the file to check (ignored) * @return true */ @Override public boolean accept(final File file) { return true; } /** * Returns true. * * @param dir the directory to check (ignored) * @param name the file name (ignored) * @return true */ @Override public boolean accept(final File dir, final String name) { return true; } /** * Returns true. * @param file the file to check (ignored) * * @return true * @since 2.9.0 */ @Override public FileVisitResult accept(final Path file, final BasicFileAttributes attributes) { return FileVisitResult.CONTINUE; } @Override public IOFileFilter negate() { return FalseFileFilter.INSTANCE; } @Override public IOFileFilter or(final IOFileFilter fileFilter) { // TRUE OR expression <=> true return INSTANCE; } @Override public IOFileFilter and(final IOFileFilter fileFilter) { // TRUE AND expression <=> expression return fileFilter; } @Override public String toString() { return TO_STRING; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/filefilter/WildcardFileFilter.java0100644 0000000 0000000 00000020054 13612062727 032223 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.filefilter; import java.io.File; import java.io.Serializable; import java.nio.file.FileVisitResult; import java.nio.file.Path; import java.nio.file.attribute.BasicFileAttributes; import java.util.List; import java.util.Objects; import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.IOCase; /** * Filters files using the supplied wildcards. *

* This filter selects files and directories based on one or more wildcards. * Testing is case-sensitive by default, but this can be configured. *

*

* The wildcard matcher uses the characters '?' and '*' to represent a * single or multiple wildcard characters. * This is the same as often found on Dos/Unix command lines. * The check is case-sensitive by default. * See {@link FilenameUtils#wildcardMatchOnSystem(String,String)} for more information. *

*

* For example: *

*

Using Classic IO

*
 * File dir = new File(".");
 * FileFilter fileFilter = new WildcardFileFilter("*test*.java~*~");
 * File[] files = dir.listFiles(fileFilter);
 * for (String file : files) {
 *     System.out.println(file);
 * }
 * 
* *

Using NIO

*
 * final Path dir = Paths.get("");
 * final AccumulatorPathVisitor visitor = AccumulatorPathVisitor.withLongCounters(new WildcardFileFilter("*test*.java~*~"));
 * //
 * // Walk one dir
 * Files.walkFileTree(dir, Collections.emptySet(), 1, visitor);
 * System.out.println(visitor.getPathCounters());
 * System.out.println(visitor.getFileList());
 * //
 * visitor.getPathCounters().reset();
 * //
 * // Walk dir tree
 * Files.walkFileTree(dir, visitor);
 * System.out.println(visitor.getPathCounters());
 * System.out.println(visitor.getDirList());
 * System.out.println(visitor.getFileList());
 * 
* * @since 1.3 */ public class WildcardFileFilter extends AbstractFileFilter implements Serializable { private static final long serialVersionUID = -7426486598995782105L; /** The wildcards that will be used to match file names. */ private final String[] wildcards; /** Whether the comparison is case sensitive. */ private final IOCase caseSensitivity; /** * Construct a new case-sensitive wildcard filter for a list of wildcards. * * @param wildcards the list of wildcards to match, not null * @throws IllegalArgumentException if the pattern list is null * @throws ClassCastException if the list does not contain Strings */ public WildcardFileFilter(final List wildcards) { this(wildcards, IOCase.SENSITIVE); } /** * Construct a new wildcard filter for a list of wildcards specifying case-sensitivity. * * @param wildcards the list of wildcards to match, not null * @param caseSensitivity how to handle case sensitivity, null means case-sensitive * @throws IllegalArgumentException if the pattern list is null * @throws ClassCastException if the list does not contain Strings */ public WildcardFileFilter(final List wildcards, final IOCase caseSensitivity) { if (wildcards == null) { throw new IllegalArgumentException("The wildcard list must not be null"); } this.wildcards = wildcards.toArray(EMPTY_STRING_ARRAY); this.caseSensitivity = caseSensitivity == null ? IOCase.SENSITIVE : caseSensitivity; } /** * Construct a new case-sensitive wildcard filter for a single wildcard. * * @param wildcard the wildcard to match * @throws IllegalArgumentException if the pattern is null */ public WildcardFileFilter(final String wildcard) { this(wildcard, IOCase.SENSITIVE); } /** * Construct a new case-sensitive wildcard filter for an array of wildcards. *

* * @param wildcards the array of wildcards to match * @throws IllegalArgumentException if the pattern array is null */ public WildcardFileFilter(final String... wildcards) { this(wildcards, IOCase.SENSITIVE); } /** * Construct a new wildcard filter for a single wildcard specifying case-sensitivity. * * @param wildcard the wildcard to match, not null * @param caseSensitivity how to handle case sensitivity, null means case-sensitive * @throws IllegalArgumentException if the pattern is null */ public WildcardFileFilter(final String wildcard, final IOCase caseSensitivity) { if (wildcard == null) { throw new IllegalArgumentException("The wildcard must not be null"); } this.wildcards = new String[] { wildcard }; this.caseSensitivity = caseSensitivity == null ? IOCase.SENSITIVE : caseSensitivity; } /** * Construct a new wildcard filter for an array of wildcards specifying case-sensitivity. *

* * @param wildcards the array of wildcards to match, not null * @param caseSensitivity how to handle case sensitivity, null means case-sensitive * @throws IllegalArgumentException if the pattern array is null */ public WildcardFileFilter(final String[] wildcards, final IOCase caseSensitivity) { if (wildcards == null) { throw new IllegalArgumentException("The wildcard array must not be null"); } this.wildcards = new String[wildcards.length]; System.arraycopy(wildcards, 0, this.wildcards, 0, wildcards.length); this.caseSensitivity = caseSensitivity == null ? IOCase.SENSITIVE : caseSensitivity; } /** * Checks to see if the file name matches one of the wildcards. * * @param file the file to check * @return true if the file name matches one of the wildcards */ @Override public boolean accept(final File file) { return accept(file.getName()); } /** * Checks to see if the file name matches one of the wildcards. * * @param dir the file directory (ignored) * @param name the file name * @return true if the file name matches one of the wildcards */ @Override public boolean accept(final File dir, final String name) { return accept(name); } /** * Checks to see if the file name matches one of the wildcards. * @param file the file to check * * @return true if the file name matches one of the wildcards. * @since 2.9.0 */ @Override public FileVisitResult accept(final Path file, final BasicFileAttributes attributes) { return toFileVisitResult(accept(Objects.toString(file.getFileName(), null)), file); } private boolean accept(final String name) { for (final String wildcard : wildcards) { if (FilenameUtils.wildcardMatch(name, wildcard, caseSensitivity)) { return true; } } return false; } /** * Provide a String representation of this file filter. * * @return a String representation */ @Override public String toString() { final StringBuilder buffer = new StringBuilder(); buffer.append(super.toString()); buffer.append("("); for (int i = 0; i < wildcards.length; i++) { if (i > 0) { buffer.append(","); } buffer.append(wildcards[i]); } buffer.append(")"); return buffer.toString(); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/filefilter/WildcardFilter.java0100644 0000000 0000000 00000014404 13612062727 031425 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.filefilter; import java.io.File; import java.io.Serializable; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.attribute.BasicFileAttributes; import java.util.List; import java.util.Objects; import org.apache.commons.io.FilenameUtils; /** * Filters files using the supplied wildcards. *

* This filter selects files, but not directories, based on one or more wildcards * and using case-sensitive comparison. *

*

* The wildcard matcher uses the characters '?' and '*' to represent a * single or multiple wildcard characters. * This is the same as often found on Dos/Unix command lines. * The extension check is case-sensitive. * See {@link FilenameUtils#wildcardMatch(String, String)} for more information. *

*

* For example: *

*

Using Classic IO

*
 * File dir = new File(".");
 * FileFilter fileFilter = new WildcardFilter("*test*.java~*~");
 * File[] files = dir.listFiles(fileFilter);
 * for (String file : files) {
 *     System.out.println(file);
 * }
 * 
* *

Using NIO

*
 * final Path dir = Paths.get("");
 * final AccumulatorPathVisitor visitor = AccumulatorPathVisitor.withLongCounters(new WildcardFilter("*test*.java~*~"));
 * //
 * // Walk one dir
 * Files.walkFileTree(dir, Collections.emptySet(), 1, visitor);
 * System.out.println(visitor.getPathCounters());
 * System.out.println(visitor.getFileList());
 * //
 * visitor.getPathCounters().reset();
 * //
 * // Walk dir tree
 * Files.walkFileTree(dir, visitor);
 * System.out.println(visitor.getPathCounters());
 * System.out.println(visitor.getDirList());
 * System.out.println(visitor.getFileList());
 * 
* * @since 1.1 * @deprecated Use WildcardFileFilter. Deprecated as this class performs directory * filtering which it shouldn't do, but that can't be removed due to compatibility. */ @Deprecated public class WildcardFilter extends AbstractFileFilter implements Serializable { private static final long serialVersionUID = -5037645902506953517L; /** The wildcards that will be used to match file names. */ private final String[] wildcards; /** * Construct a new case-sensitive wildcard filter for a list of wildcards. * * @param wildcards the list of wildcards to match * @throws IllegalArgumentException if the pattern list is null * @throws ClassCastException if the list does not contain Strings */ public WildcardFilter(final List wildcards) { if (wildcards == null) { throw new IllegalArgumentException("The wildcard list must not be null"); } this.wildcards = wildcards.toArray(EMPTY_STRING_ARRAY); } /** * Construct a new case-sensitive wildcard filter for a single wildcard. * * @param wildcard the wildcard to match * @throws IllegalArgumentException if the pattern is null */ public WildcardFilter(final String wildcard) { if (wildcard == null) { throw new IllegalArgumentException("The wildcard must not be null"); } this.wildcards = new String[] { wildcard }; } /** * Construct a new case-sensitive wildcard filter for an array of wildcards. * * @param wildcards the array of wildcards to match * @throws IllegalArgumentException if the pattern array is null */ public WildcardFilter(final String... wildcards) { if (wildcards == null) { throw new IllegalArgumentException("The wildcard array must not be null"); } this.wildcards = new String[wildcards.length]; System.arraycopy(wildcards, 0, this.wildcards, 0, wildcards.length); } /** * Checks to see if the file name matches one of the wildcards. * * @param file the file to check * @return true if the file name matches one of the wildcards */ @Override public boolean accept(final File file) { if (file.isDirectory()) { return false; } for (final String wildcard : wildcards) { if (FilenameUtils.wildcardMatch(file.getName(), wildcard)) { return true; } } return false; } /** * Checks to see if the file name matches one of the wildcards. * @param file the file to check * * @return true if the file name matches one of the wildcards * @since 2.9.0 */ @Override public FileVisitResult accept(final Path file, final BasicFileAttributes attributes) { if (Files.isDirectory(file)) { return FileVisitResult.TERMINATE; } for (final String wildcard : wildcards) { if (FilenameUtils.wildcardMatch(Objects.toString(file.getFileName(), null), wildcard)) { return FileVisitResult.CONTINUE; } } return FileVisitResult.TERMINATE; } /** * Checks to see if the file name matches one of the wildcards. * * @param dir the file directory * @param name the file name * @return true if the file name matches one of the wildcards */ @Override public boolean accept(final File dir, final String name) { if (dir != null && new File(dir, name).isDirectory()) { return false; } for (final String wildcard : wildcards) { if (FilenameUtils.wildcardMatch(name, wildcard)) { return true; } } return false; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/filefilter/package.html0100644 0000000 0000000 00000013532 13612062727 030145 0ustar00rootroot0000000 0000000

This package defines an interface (IOFileFilter) that combines both {@link java.io.FileFilter} and {@link java.io.FilenameFilter}. Besides that the package offers a series of ready-to-use implementations of the IOFileFilter interface including implementation that allow you to combine other such filters.

These filter can be used to list files or in {@link java.awt.FileDialog}, for example.

There are a number of 'primitive' filters:
DirectoryFilter Only accept directories
PrefixFileFilter Filter based on a prefix
SuffixFileFilter Filter based on a suffix
NameFileFilter Filter based on a filename
WildcardFileFilter Filter based on wildcards
AgeFileFilter Filter based on last modified time of file
SizeFileFilter Filter based on file size
And there are five 'boolean' filters:
TrueFileFilter Accept all files
FalseFileFilter Accept no files
NotFileFilter Applies a logical NOT to an existing filter
AndFileFilter Combines two filters using a logical AND
OrFileFilter Combines two filter using a logical OR

Using Classic IO

These boolean FilenameFilters can be nested, to allow arbitrary expressions. For example, here is how one could print all non-directory files in the current directory, starting with "A", and ending in ".java" or ".class":

  File dir = new File(".");
  String[] files = dir.list( 
    new AndFileFilter(
      new AndFileFilter(
        new PrefixFileFilter("A"),
        new OrFileFilter(
          new SuffixFileFilter(".class"),
          new SuffixFileFilter(".java")
        )
      ),
      new NotFileFilter(
        new DirectoryFileFilter()
      )
    )
  );
  for (int i=0; i<files.length; i++) {
    System.out.println(files[i]);
  }

You can alternatively build a filter tree using the "and", "or", and "not" methods on filters themselves:

  File dir = new File(".");
  String[] files = dir.list( 
    new AndFileFilter(
      new PrefixFileFilter("A").and(
        new SuffixFileFilter(".class").or(new SuffixFileFilter(".java"))),
      new DirectoryFileFilter().not()
    )
  );
  for (int i=0; i<files.length; i++) {
    System.out.println(files[i]);
  }

This package also contains a utility class: FileFilterUtils. It allows you to use all file filters without having to put them in the import section. Here's how the above example will look using FileFilterUtils:

  File dir = new File(".");
  String[] files = dir.list( 
    FileFilterUtils.andFileFilter(
      FileFilterUtils.andFileFilter(
        FileFilterUtils.prefixFileFilter("A"),
        FileFilterUtils.orFileFilter(
          FileFilterUtils.suffixFileFilter(".class"),
          FileFilterUtils.suffixFileFilter(".java")
        )
      ),
      FileFilterUtils.notFileFilter(
        FileFilterUtils.directoryFileFilter()
      )
    )
  );
  for (int i=0; i<files.length; i++) {
    System.out.println(files[i]);
  }

Using NIO

You can combine Java file tree walking by using java.nio.file.Files.walk() APIs with filters:

   final Path dir = Paths.get("");
   // We are interested in files older than one day
   final long cutoff = System.currentTimeMillis() - (24 * 60 * 60 * 1000);
   final AccumulatorPathVisitor visitor = AccumulatorPathVisitor.withLongCounters(new AgeFileFilter(cutoff));
   //
   // Walk one dir
   Files.walkFileTree(dir, Collections.emptySet(), 1, visitor);
   System.out.println(visitor.getPathCounters());
   System.out.println(visitor.getFileList());
   //
   visitor.getPathCounters().reset();
   //
   // Walk dir tree
   Files.walkFileTree(dir, visitor);
   System.out.println(visitor.getPathCounters());
   System.out.println(visitor.getDirList());
   System.out.println(visitor.getFileList());

There are a few other goodies in that class so please have a look at the documentation in detail.

commons-io-2.11.0-src/src/main/java/org/apache/commons/io/function/IOConsumer.java0100644 0000000 0000000 00000005063 13612062727 030252 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.function; import java.io.IOException; import java.util.Objects; import java.util.function.Consumer; /** * Like {@link Consumer} but throws {@link IOException}. * * @param the type of the input to the operations. * @since 2.7 */ @FunctionalInterface public interface IOConsumer { /** * Package private constant; consider private. */ IOConsumer NOOP_IO_CONSUMER = t -> {/* noop */}; /** * Returns a constant NOOP consumer. * * @param Type consumer type. * @return a constant NOOP consumer. * @since 2.9.0 */ @SuppressWarnings("unchecked") static IOConsumer noop() { return (IOConsumer) NOOP_IO_CONSUMER; } /** * Performs this operation on the given argument. * * @param t the input argument * @throws IOException if an I/O error occurs. */ void accept(T t) throws IOException; /** * Returns a composed {@code IoConsumer} that performs, in sequence, this operation followed by the {@code after} * operation. If performing either operation throws an exception, it is relayed to the caller of the composed * operation. If performing this operation throws an exception, the {@code after} operation will not be performed. * * @param after the operation to perform after this operation * @return a composed {@code Consumer} that performs in sequence this operation followed by the {@code after} * operation * @throws NullPointerException if {@code after} is null */ default IOConsumer andThen(final IOConsumer after) { Objects.requireNonNull(after, "after"); return (final T t) -> { accept(t); after.accept(t); }; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/function/IOFunction.java0100644 0000000 0000000 00000020511 13612062727 030237 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.function; import java.io.IOException; import java.util.Objects; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Supplier; /** * Like {@link Function} but throws {@link IOException}. * * @param the type of the input to the operations. * @param the return type of the operations. * @since 2.7 */ @FunctionalInterface public interface IOFunction { /** * Applies this function to the given argument. * * @param t the function argument * @return the function result * * @throws IOException if the function throws an IOException */ R apply(final T t) throws IOException; /** * Returns a composed {@link IOFunction} that first applies the {@code before} * function to its input, and then applies this function to the result. * If evaluation of either function throws an exception, it is relayed to * the caller of the composed function. * * @param the type of input to the {@code before} function, and to the * composed function * @param before the function to apply before this function is applied * @return a composed function that first applies the {@code before} * function and then applies this function * @throws NullPointerException if before is null * * @see #andThen(IOFunction) */ default IOFunction compose(final IOFunction before) { Objects.requireNonNull(before, "before"); return (final V v) -> apply(before.apply(v)); } /** * Returns a composed {@link IOFunction} that first applies the {@code before} * function to its input, and then applies this function to the result. * If evaluation of either function throws an exception, it is relayed to * the caller of the composed function. * * @param the type of input to the {@code before} function, and to the * composed function * @param before the function to apply before this function is applied * @return a composed function that first applies the {@code before} * function and then applies this function * @throws NullPointerException if before is null * * @see #andThen(IOFunction) */ default IOFunction compose(final Function before) { Objects.requireNonNull(before, "before"); return (final V v) -> apply(before.apply(v)); } /** * Returns a composed {@link IOFunction} that first applies the {@code before} * function to its input, and then applies this function to the result. * If evaluation of either function throws an exception, it is relayed to * the caller of the composed function. * * @param before the supplier which feeds the application of this function * @return a composed function that first applies the {@code before} * function and then applies this function * @throws NullPointerException if before is null * * @see #andThen(IOFunction) */ default IOSupplier compose(final IOSupplier before) { Objects.requireNonNull(before, "before"); return () -> apply(before.get()); } /** * Returns a composed {@link IOFunction} that first applies the {@code before} * function to its input, and then applies this function to the result. * If evaluation of either function throws an exception, it is relayed to * the caller of the composed function. * * @param before the supplier which feeds the application of this function * @return a composed function that first applies the {@code before} * function and then applies this function * @throws NullPointerException if before is null * * @see #andThen(IOFunction) */ default IOSupplier compose(final Supplier before) { Objects.requireNonNull(before, "before"); return () -> apply(before.get()); } /** * Returns a composed {@link IOFunction} that first applies this function to * its input, and then applies the {@code after} function to the result. * If evaluation of either function throws an exception, it is relayed to * the caller of the composed function. * * @param the type of output of the {@code after} function, and of the * composed function * @param after the function to apply after this function is applied * @return a composed function that first applies this function and then * applies the {@code after} function * @throws NullPointerException if after is null * * @see #compose(IOFunction) */ default IOFunction andThen(final IOFunction after) { Objects.requireNonNull(after, "after"); return (final T t) -> after.apply(apply(t)); } /** * Returns a composed {@link IOFunction} that first applies this function to * its input, and then applies the {@code after} function to the result. * If evaluation of either function throws an exception, it is relayed to * the caller of the composed function. * * @param the type of output of the {@code after} function, and of the * composed function * @param after the function to apply after this function is applied * @return a composed function that first applies this function and then * applies the {@code after} function * @throws NullPointerException if after is null * * @see #compose(IOFunction) */ default IOFunction andThen(final Function after) { Objects.requireNonNull(after, "after"); return (final T t) -> after.apply(apply(t)); } /** * Returns a composed {@link IOFunction} that first applies this function to * its input, and then applies the {@code after} consumer to the result. * If evaluation of either function throws an exception, it is relayed to * the caller of the composed function. * * @param after the consumer to apply after this function is applied * @return a composed function that first applies this function and then * applies the {@code after} consumer * @throws NullPointerException if after is null * * @see #compose(IOFunction) */ default IOConsumer andThen(final IOConsumer after) { Objects.requireNonNull(after, "after"); return (final T t) -> after.accept(apply(t)); } /** * Returns a composed {@link IOFunction} that first applies this function to * its input, and then applies the {@code after} consumer to the result. * If evaluation of either function throws an exception, it is relayed to * the caller of the composed function. * * @param after the consumer to apply after this function is applied * @return a composed function that first applies this function and then * applies the {@code after} consumer * @throws NullPointerException if after is null * * @see #compose(IOFunction) */ default IOConsumer andThen(final Consumer after) { Objects.requireNonNull(after, "after"); return (final T t) -> after.accept(apply(t)); } /** * Returns a {@link IOFunction} that always returns its input argument. * * @param the type of the input and output objects to the function * @return a function that always returns its input argument */ static IOFunction identity() { return t -> t; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/function/IOSupplier.java0100644 0000000 0000000 00000002403 13612062727 030255 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.function; import java.io.IOException; import java.util.function.Supplier; /** * Like {@link Supplier} but throws {@link IOException}. * * @param the return type of the operations. * @since 2.7 */ @FunctionalInterface public interface IOSupplier { /** * Gets a result. * * @return a result * * @throws IOException if an IO error occurs whilst supplying the value. */ T get() throws IOException; } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/function/package.html0100644 0000000 0000000 00000001715 13612062727 027645 0ustar00rootroot0000000 0000000

This package defines IO-only related functional interfaces for lambda expressions and method references.

commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/AbstractCharacterFilterReader.java0100644 0000000 0000000 00000005625 13612062727 033416 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.apache.commons.io.IOUtils.EOF; import java.io.FilterReader; import java.io.IOException; import java.io.Reader; import java.util.function.IntPredicate; /** * A filter reader that filters out characters where subclasses decide which characters to filter out. */ public abstract class AbstractCharacterFilterReader extends FilterReader { /** * Skips nothing. * * @since 2.9.0 */ protected static final IntPredicate SKIP_NONE = ch -> false; private final IntPredicate skip; /** * Constructs a new reader. * * @param reader the reader to filter */ protected AbstractCharacterFilterReader(final Reader reader) { this(reader, SKIP_NONE); } /** * Constructs a new reader. * * @param reader the reader to filter. * @param skip Skip test. * @since 2.9.0 */ protected AbstractCharacterFilterReader(final Reader reader, final IntPredicate skip) { super(reader); this.skip = skip == null ? SKIP_NONE : skip; } /** * Returns true if the given character should be filtered out, false to keep the character. * * @param ch the character to test. * @return true if the given character should be filtered out, false to keep the character. */ protected boolean filter(final int ch) { return skip.test(ch); } @Override public int read() throws IOException { int ch; do { ch = in.read(); } while (ch != EOF && filter(ch)); return ch; } @Override public int read(final char[] cbuf, final int off, final int len) throws IOException { final int read = super.read(cbuf, off, len); if (read == EOF) { return EOF; } int pos = off - 1; for (int readPos = off; readPos < off + read; readPos++) { if (filter(cbuf[readPos])) { continue; } pos++; if (pos < readPos) { cbuf[pos] = cbuf[readPos]; } } return pos - off + 1; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/AutoCloseInputStream.java0100644 0000000 0000000 00000006446 13612062727 031641 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.apache.commons.io.IOUtils.EOF; import java.io.IOException; import java.io.InputStream; /** * Proxy stream that closes and discards the underlying stream as soon as the * end of input has been reached or when the stream is explicitly closed. * Not even a reference to the underlying stream is kept after it has been * closed, so any allocated in-memory buffers can be freed even if the * client application still keeps a reference to the proxy stream. *

* This class is typically used to release any resources related to an open * stream as soon as possible even if the client application (by not explicitly * closing the stream when no longer needed) or the underlying stream (by not * releasing resources once the last byte has been read) do not do that. *

* * @since 1.4 */ public class AutoCloseInputStream extends ProxyInputStream { /** * Creates an automatically closing proxy for the given input stream. * * @param in underlying input stream */ public AutoCloseInputStream(final InputStream in) { super(in); } /** * Closes the underlying input stream and replaces the reference to it * with a {@link ClosedInputStream} instance. *

* This method is automatically called by the read methods when the end * of input has been reached. *

* Note that it is safe to call this method any number of times. The original * underlying input stream is closed and discarded only once when this * method is first called. * * @throws IOException if the underlying input stream can not be closed */ @Override public void close() throws IOException { in.close(); in = ClosedInputStream.CLOSED_INPUT_STREAM; } /** * Automatically closes the stream if the end of stream was reached. * * @param n number of bytes read, or -1 if no more bytes are available * @throws IOException if the stream could not be closed * @since 2.0 */ @Override protected void afterRead(final int n) throws IOException { if (n == EOF) { close(); } } /** * Ensures that the stream is closed before it gets garbage-collected. * As mentioned in {@link #close()}, this is a no-op if the stream has * already been closed. * @throws Throwable if an error occurs */ @Override protected void finalize() throws Throwable { close(); super.finalize(); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/BOMInputStream.java0100644 0000000 0000000 00000031443 13612062727 030353 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.apache.commons.io.IOUtils.EOF; import java.io.IOException; import java.io.InputStream; import java.util.Arrays; import java.util.Comparator; import java.util.List; import org.apache.commons.io.ByteOrderMark; import org.apache.commons.io.IOUtils; /** * This class is used to wrap a stream that includes an encoded {@link ByteOrderMark} as its first bytes. *

* This class detects these bytes and, if required, can automatically skip them and return the subsequent byte as the * first byte in the stream. *

*

* The {@link ByteOrderMark} implementation has the following pre-defined BOMs: *

*
    *
  • UTF-8 - {@link ByteOrderMark#UTF_8}
  • *
  • UTF-16BE - {@link ByteOrderMark#UTF_16LE}
  • *
  • UTF-16LE - {@link ByteOrderMark#UTF_16BE}
  • *
  • UTF-32BE - {@link ByteOrderMark#UTF_32LE}
  • *
  • UTF-32LE - {@link ByteOrderMark#UTF_32BE}
  • *
* *

Example 1 - Detect and exclude a UTF-8 BOM

* *
 * BOMInputStream bomIn = new BOMInputStream(in);
 * if (bomIn.hasBOM()) {
 *     // has a UTF-8 BOM
 * }
 * 
* *

Example 2 - Detect a UTF-8 BOM (but don't exclude it)

* *
 * boolean include = true;
 * BOMInputStream bomIn = new BOMInputStream(in, include);
 * if (bomIn.hasBOM()) {
 *     // has a UTF-8 BOM
 * }
 * 
* *

Example 3 - Detect Multiple BOMs

* *
 * BOMInputStream bomIn = new BOMInputStream(in,
 *   ByteOrderMark.UTF_16LE, ByteOrderMark.UTF_16BE,
 *   ByteOrderMark.UTF_32LE, ByteOrderMark.UTF_32BE
 *   );
 * if (bomIn.hasBOM() == false) {
 *     // No BOM found
 * } else if (bomIn.hasBOM(ByteOrderMark.UTF_16LE)) {
 *     // has a UTF-16LE BOM
 * } else if (bomIn.hasBOM(ByteOrderMark.UTF_16BE)) {
 *     // has a UTF-16BE BOM
 * } else if (bomIn.hasBOM(ByteOrderMark.UTF_32LE)) {
 *     // has a UTF-32LE BOM
 * } else if (bomIn.hasBOM(ByteOrderMark.UTF_32BE)) {
 *     // has a UTF-32BE BOM
 * }
 * 
* * @see org.apache.commons.io.ByteOrderMark * @see Wikipedia - Byte Order Mark * @since 2.0 */ public class BOMInputStream extends ProxyInputStream { private final boolean include; /** * BOMs are sorted from longest to shortest. */ private final List boms; private ByteOrderMark byteOrderMark; private int[] firstBytes; private int fbLength; private int fbIndex; private int markFbIndex; private boolean markedAtStart; /** * Constructs a new BOM InputStream that excludes a {@link ByteOrderMark#UTF_8} BOM. * * @param delegate * the InputStream to delegate to */ public BOMInputStream(final InputStream delegate) { this(delegate, false, ByteOrderMark.UTF_8); } /** * Constructs a new BOM InputStream that detects a a {@link ByteOrderMark#UTF_8} and optionally includes it. * * @param delegate * the InputStream to delegate to * @param include * true to include the UTF-8 BOM or false to exclude it */ public BOMInputStream(final InputStream delegate, final boolean include) { this(delegate, include, ByteOrderMark.UTF_8); } /** * Constructs a new BOM InputStream that excludes the specified BOMs. * * @param delegate * the InputStream to delegate to * @param boms * The BOMs to detect and exclude */ public BOMInputStream(final InputStream delegate, final ByteOrderMark... boms) { this(delegate, false, boms); } /** * Compares ByteOrderMark objects in descending length order. */ private static final Comparator ByteOrderMarkLengthComparator = (bom1, bom2) -> { final int len1 = bom1.length(); final int len2 = bom2.length(); return Integer.compare(len2, len1); }; /** * Constructs a new BOM InputStream that detects the specified BOMs and optionally includes them. * * @param delegate * the InputStream to delegate to * @param include * true to include the specified BOMs or false to exclude them * @param boms * The BOMs to detect and optionally exclude */ public BOMInputStream(final InputStream delegate, final boolean include, final ByteOrderMark... boms) { super(delegate); if (IOUtils.length(boms) == 0) { throw new IllegalArgumentException("No BOMs specified"); } this.include = include; final List list = Arrays.asList(boms); // Sort the BOMs to match the longest BOM first because some BOMs have the same starting two bytes. list.sort(ByteOrderMarkLengthComparator); this.boms = list; } /** * Indicates whether the stream contains one of the specified BOMs. * * @return true if the stream has one of the specified BOMs, otherwise false if it does not * @throws IOException * if an error reading the first bytes of the stream occurs */ public boolean hasBOM() throws IOException { return getBOM() != null; } /** * Indicates whether the stream contains the specified BOM. * * @param bom * The BOM to check for * @return true if the stream has the specified BOM, otherwise false if it does not * @throws IllegalArgumentException * if the BOM is not one the stream is configured to detect * @throws IOException * if an error reading the first bytes of the stream occurs */ public boolean hasBOM(final ByteOrderMark bom) throws IOException { if (!boms.contains(bom)) { throw new IllegalArgumentException("Stream not configure to detect " + bom); } getBOM(); return byteOrderMark != null && byteOrderMark.equals(bom); } /** * Return the BOM (Byte Order Mark). * * @return The BOM or null if none * @throws IOException * if an error reading the first bytes of the stream occurs */ public ByteOrderMark getBOM() throws IOException { if (firstBytes == null) { fbLength = 0; // BOMs are sorted from longest to shortest final int maxBomSize = boms.get(0).length(); firstBytes = new int[maxBomSize]; // Read first maxBomSize bytes for (int i = 0; i < firstBytes.length; i++) { firstBytes[i] = in.read(); fbLength++; if (firstBytes[i] < 0) { break; } } // match BOM in firstBytes byteOrderMark = find(); if ((byteOrderMark != null) && !include) { if (byteOrderMark.length() < firstBytes.length) { fbIndex = byteOrderMark.length(); } else { fbLength = 0; } } } return byteOrderMark; } /** * Return the BOM charset Name - {@link ByteOrderMark#getCharsetName()}. * * @return The BOM charset Name or null if no BOM found * @throws IOException * if an error reading the first bytes of the stream occurs * */ public String getBOMCharsetName() throws IOException { getBOM(); return byteOrderMark == null ? null : byteOrderMark.getCharsetName(); } /** * This method reads and either preserves or skips the first bytes in the stream. It behaves like the single-byte * {@code read()} method, either returning a valid byte or -1 to indicate that the initial bytes have been * processed already. * * @return the byte read (excluding BOM) or -1 if the end of stream * @throws IOException * if an I/O error occurs */ private int readFirstBytes() throws IOException { getBOM(); return fbIndex < fbLength ? firstBytes[fbIndex++] : EOF; } /** * Find a BOM with the specified bytes. * * @return The matched BOM or null if none matched */ private ByteOrderMark find() { for (final ByteOrderMark bom : boms) { if (matches(bom)) { return bom; } } return null; } /** * Check if the bytes match a BOM. * * @param bom * The BOM * @return true if the bytes match the bom, otherwise false */ private boolean matches(final ByteOrderMark bom) { // if (bom.length() != fbLength) { // return false; // } // firstBytes may be bigger than the BOM bytes for (int i = 0; i < bom.length(); i++) { if (bom.get(i) != firstBytes[i]) { return false; } } return true; } // ---------------------------------------------------------------------------- // Implementation of InputStream // ---------------------------------------------------------------------------- /** * Invokes the delegate's {@code read()} method, detecting and optionally skipping BOM. * * @return the byte read (excluding BOM) or -1 if the end of stream * @throws IOException * if an I/O error occurs */ @Override public int read() throws IOException { final int b = readFirstBytes(); return b >= 0 ? b : in.read(); } /** * Invokes the delegate's {@code read(byte[], int, int)} method, detecting and optionally skipping BOM. * * @param buf * the buffer to read the bytes into * @param off * The start offset * @param len * The number of bytes to read (excluding BOM) * @return the number of bytes read or -1 if the end of stream * @throws IOException * if an I/O error occurs */ @Override public int read(final byte[] buf, int off, int len) throws IOException { int firstCount = 0; int b = 0; while (len > 0 && b >= 0) { b = readFirstBytes(); if (b >= 0) { buf[off++] = (byte) (b & 0xFF); len--; firstCount++; } } final int secondCount = in.read(buf, off, len); return secondCount < 0 ? firstCount > 0 ? firstCount : EOF : firstCount + secondCount; } /** * Invokes the delegate's {@code read(byte[])} method, detecting and optionally skipping BOM. * * @param buf * the buffer to read the bytes into * @return the number of bytes read (excluding BOM) or -1 if the end of stream * @throws IOException * if an I/O error occurs */ @Override public int read(final byte[] buf) throws IOException { return read(buf, 0, buf.length); } /** * Invokes the delegate's {@code mark(int)} method. * * @param readlimit * read ahead limit */ @Override public synchronized void mark(final int readlimit) { markFbIndex = fbIndex; markedAtStart = firstBytes == null; in.mark(readlimit); } /** * Invokes the delegate's {@code reset()} method. * * @throws IOException * if an I/O error occurs */ @Override public synchronized void reset() throws IOException { fbIndex = markFbIndex; if (markedAtStart) { firstBytes = null; } in.reset(); } /** * Invokes the delegate's {@code skip(long)} method, detecting and optionally skipping BOM. * * @param n * the number of bytes to skip * @return the number of bytes to skipped or -1 if the end of stream * @throws IOException * if an I/O error occurs */ @Override public long skip(final long n) throws IOException { int skipped = 0; while ((n > skipped) && (readFirstBytes() >= 0)) { skipped++; } return in.skip(n - skipped) + skipped; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/BoundedInputStream.java0100644 0000000 0000000 00000015655 13612062727 031325 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.apache.commons.io.IOUtils.EOF; import java.io.IOException; import java.io.InputStream; /** * This is a stream that will only supply bytes up to a certain length - if its * position goes above that, it will stop. *

* This is useful to wrap ServletInputStreams. The ServletInputStream will block * if you try to read content from it that isn't there, because it doesn't know * whether the content hasn't arrived yet or whether the content has finished. * So, one of these, initialized with the Content-length sent in the * ServletInputStream's header, will stop it blocking, providing it's been sent * with a correct content length. *

* * @since 2.0 */ public class BoundedInputStream extends InputStream { /** the wrapped input stream */ private final InputStream in; /** the max length to provide */ private final long max; /** the number of bytes already returned */ private long pos; /** the marked position */ private long mark = EOF; /** flag if close should be propagated */ private boolean propagateClose = true; /** * Creates a new {@code BoundedInputStream} that wraps the given input * stream and limits it to a certain size. * * @param in The wrapped input stream * @param size The maximum number of bytes to return */ public BoundedInputStream(final InputStream in, final long size) { // Some badly designed methods - eg the servlet API - overload length // such that "-1" means stream finished this.max = size; this.in = in; } /** * Creates a new {@code BoundedInputStream} that wraps the given input * stream and is unlimited. * * @param in The wrapped input stream */ public BoundedInputStream(final InputStream in) { this(in, EOF); } /** * Invokes the delegate's {@code read()} method if * the current position is less than the limit. * @return the byte read or -1 if the end of stream or * the limit has been reached. * @throws IOException if an I/O error occurs. */ @Override public int read() throws IOException { if (max >= 0 && pos >= max) { return EOF; } final int result = in.read(); pos++; return result; } /** * Invokes the delegate's {@code read(byte[])} method. * @param b the buffer to read the bytes into * @return the number of bytes read or -1 if the end of stream or * the limit has been reached. * @throws IOException if an I/O error occurs. */ @Override public int read(final byte[] b) throws IOException { return this.read(b, 0, b.length); } /** * Invokes the delegate's {@code read(byte[], int, int)} method. * @param b the buffer to read the bytes into * @param off The start offset * @param len The number of bytes to read * @return the number of bytes read or -1 if the end of stream or * the limit has been reached. * @throws IOException if an I/O error occurs. */ @Override public int read(final byte[] b, final int off, final int len) throws IOException { if (max>=0 && pos>=max) { return EOF; } final long maxRead = max>=0 ? Math.min(len, max-pos) : len; final int bytesRead = in.read(b, off, (int)maxRead); if (bytesRead==EOF) { return EOF; } pos+=bytesRead; return bytesRead; } /** * Invokes the delegate's {@code skip(long)} method. * @param n the number of bytes to skip * @return the actual number of bytes skipped * @throws IOException if an I/O error occurs. */ @Override public long skip(final long n) throws IOException { final long toSkip = max>=0 ? Math.min(n, max-pos) : n; final long skippedBytes = in.skip(toSkip); pos+=skippedBytes; return skippedBytes; } /** * {@inheritDoc} */ @Override public int available() throws IOException { if (max>=0 && pos>=max) { return 0; } return in.available(); } /** * Invokes the delegate's {@code toString()} method. * @return the delegate's {@code toString()} */ @Override public String toString() { return in.toString(); } /** * Invokes the delegate's {@code close()} method * if {@link #isPropagateClose()} is {@code true}. * @throws IOException if an I/O error occurs. */ @Override public void close() throws IOException { if (propagateClose) { in.close(); } } /** * Invokes the delegate's {@code reset()} method. * @throws IOException if an I/O error occurs. */ @Override public synchronized void reset() throws IOException { in.reset(); pos = mark; } /** * Invokes the delegate's {@code mark(int)} method. * @param readlimit read ahead limit */ @Override public synchronized void mark(final int readlimit) { in.mark(readlimit); mark = pos; } /** * Invokes the delegate's {@code markSupported()} method. * @return true if mark is supported, otherwise false */ @Override public boolean markSupported() { return in.markSupported(); } /** * Indicates whether the {@link #close()} method * should propagate to the underling {@link InputStream}. * * @return {@code true} if calling {@link #close()} * propagates to the {@code close()} method of the * underlying stream or {@code false} if it does not. */ public boolean isPropagateClose() { return propagateClose; } /** * Set whether the {@link #close()} method * should propagate to the underling {@link InputStream}. * * @param propagateClose {@code true} if calling * {@link #close()} propagates to the {@code close()} * method of the underlying stream or * {@code false} if it does not. */ public void setPropagateClose(final boolean propagateClose) { this.propagateClose = propagateClose; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/BoundedReader.java0100644 0000000 0000000 00000011126 13612062727 030241 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.commons.io.input; import static org.apache.commons.io.IOUtils.EOF; import java.io.IOException; import java.io.Reader; /** * A reader that imposes a limit to the number of characters that can be read from an underlying reader, returning EOF * when this limit is reached, regardless of state of underlying reader. * *

* One use case is to avoid overrunning the readAheadLimit supplied to {@link java.io.Reader#mark(int)}, since reading * too many characters removes the ability to do a successful reset. *

* * @since 2.5 */ public class BoundedReader extends Reader { private static final int INVALID = -1; private final Reader target; private int charsRead; private int markedAt = INVALID; private int readAheadLimit; // Internally, this value will never exceed the allowed size private final int maxCharsFromTargetReader; /** * Constructs a bounded reader * * @param target The target stream that will be used * @param maxCharsFromTargetReader The maximum number of characters that can be read from target */ public BoundedReader(final Reader target, final int maxCharsFromTargetReader) { this.target = target; this.maxCharsFromTargetReader = maxCharsFromTargetReader; } /** * Closes the target * * @throws IOException If an I/O error occurs while calling the underlying reader's close method */ @Override public void close() throws IOException { target.close(); } /** * Resets the target to the latest mark, * * @throws IOException If an I/O error occurs while calling the underlying reader's reset method * @see java.io.Reader#reset() */ @Override public void reset() throws IOException { charsRead = markedAt; target.reset(); } /** * marks the target stream * * @param readAheadLimit The number of characters that can be read while still retaining the ability to do #reset(). * Note that this parameter is not validated with respect to maxCharsFromTargetReader. There * is no way to pass past maxCharsFromTargetReader, even if this value is greater. * * @throws IOException If an I/O error occurs while calling the underlying reader's mark method * @see java.io.Reader#mark(int) */ @Override public void mark(final int readAheadLimit) throws IOException { this.readAheadLimit = readAheadLimit - charsRead; markedAt = charsRead; target.mark(readAheadLimit); } /** * Reads a single character * * @return -1 on EOF or the character read * @throws IOException If an I/O error occurs while calling the underlying reader's read method * @see java.io.Reader#read() */ @Override public int read() throws IOException { if (charsRead >= maxCharsFromTargetReader) { return EOF; } if (markedAt >= 0 && (charsRead - markedAt) >= readAheadLimit) { return EOF; } charsRead++; return target.read(); } /** * Reads into an array * * @param cbuf The buffer to fill * @param off The offset * @param len The number of chars to read * @return the number of chars read * @throws IOException If an I/O error occurs while calling the underlying reader's read method * @see java.io.Reader#read(char[], int, int) */ @Override public int read(final char[] cbuf, final int off, final int len) throws IOException { int c; for (int i = 0; i < len; i++) { c = read(); if (c == EOF) { return i == 0 ? EOF : i; } cbuf[off + i] = (char) c; } return len; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/BrokenInputStream.java0100644 0000000 0000000 00000005502 13612062727 031153 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import java.io.IOException; import java.io.InputStream; /** * Broken input stream. This stream always throws an {@link IOException} from * all the {@link InputStream} methods where the exception is declared. *

* This class is mostly useful for testing error handling in code that uses an * input stream. *

* * @since 2.0 */ public class BrokenInputStream extends InputStream { /** * The exception that is thrown by all methods of this class. */ private final IOException exception; /** * Creates a new stream that always throws the given exception. * * @param exception the exception to be thrown */ public BrokenInputStream(final IOException exception) { this.exception = exception; } /** * Creates a new stream that always throws an {@link IOException} */ public BrokenInputStream() { this(new IOException("Broken input stream")); } /** * Throws the configured exception. * * @return nothing * @throws IOException always thrown */ @Override public int read() throws IOException { throw exception; } /** * Throws the configured exception. * * @return nothing * @throws IOException always thrown */ @Override public int available() throws IOException { throw exception; } /** * Throws the configured exception. * * @param n ignored * @return nothing * @throws IOException always thrown */ @Override public long skip(final long n) throws IOException { throw exception; } /** * Throws the configured exception. * * @throws IOException always thrown */ @Override public synchronized void reset() throws IOException { throw exception; } /** * Throws the configured exception. * * @throws IOException always thrown */ @Override public void close() throws IOException { throw exception; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/BrokenReader.java0100644 0000000 0000000 00000006216 13612062727 030105 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import java.io.IOException; import java.io.Reader; /** * Broken reader. This reader always throws an {@link IOException} from * all the {@link Reader} methods where the exception is declared. *

* This class is mostly useful for testing error handling in code that uses a * reader. *

* * @since 2.7 */ public class BrokenReader extends Reader { /** * The exception that is thrown by all methods of this class. */ private final IOException exception; /** * Creates a new reader that always throws the given exception. * * @param exception the exception to be thrown */ public BrokenReader(final IOException exception) { this.exception = exception; } /** * Creates a new reader that always throws an {@link IOException} */ public BrokenReader() { this(new IOException("Broken reader")); } /** * Throws the configured exception. * * @param cbuf ignored * @param off ignored * @param len ignored * @return nothing * @throws IOException always thrown */ @Override public int read(final char[] cbuf, final int off, final int len) throws IOException { throw exception; } /** * Throws the configured exception. * * @param n ignored * @return nothing * @throws IOException always thrown */ @Override public long skip(final long n) throws IOException { throw exception; } /** * Throws the configured exception. * * @return nothing * @throws IOException always thrown */ @Override public boolean ready() throws IOException { throw exception; } /** * Throws the configured exception. * * @param readAheadLimit ignored * @throws IOException always thrown */ @Override public void mark(final int readAheadLimit) throws IOException { throw exception; } /** * Throws the configured exception. * * @throws IOException always thrown */ @Override public synchronized void reset() throws IOException { throw exception; } /** * Throws the configured exception. * * @throws IOException always thrown */ @Override public void close() throws IOException { throw exception; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/BufferedFileChannelInputStream.java0100644 0000000 0000000 00000023354 13612062727 033553 0ustar00rootroot0000000 0000000 /* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.apache.commons.io.IOUtils.EOF; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.nio.file.Path; import java.nio.file.StandardOpenOption; import java.util.Objects; import org.apache.commons.io.IOUtils; /** * {@link InputStream} implementation which uses direct buffer to read a file to avoid extra copy of data between Java * and native memory which happens when using {@link java.io.BufferedInputStream}. Unfortunately, this is not something * already available in JDK, {@code sun.nio.ch.ChannelInputStream} supports reading a file using NIO, but does not * support buffering. *

* This class was ported and adapted from Apache Spark commit 933dc6cb7b3de1d8ccaf73d124d6eb95b947ed19 where it was * called {@code NioBufferedFileInputStream}. *

* * @since 2.9.0 */ @SuppressWarnings("restriction") public final class BufferedFileChannelInputStream extends InputStream { private final ByteBuffer byteBuffer; private final FileChannel fileChannel; private static final Class DIRECT_BUFFER_CLASS = getDirectBufferClass(); private static Class getDirectBufferClass() { Class res = null; try { res = Class.forName("sun.nio.ch.DirectBuffer"); } catch (final IllegalAccessError | ClassNotFoundException ignored) { // ignored } return res; } private static boolean isDirectBuffer(final Object object) { return DIRECT_BUFFER_CLASS != null && DIRECT_BUFFER_CLASS.isInstance(object); } /** * Constructs a new instance for the given File. * * @param file The file to stream. * @throws IOException If an I/O error occurs */ public BufferedFileChannelInputStream(final File file) throws IOException { this(file, IOUtils.DEFAULT_BUFFER_SIZE); } /** * Constructs a new instance for the given File and buffer size. * * @param file The file to stream. * @param bufferSizeInBytes buffer size. * @throws IOException If an I/O error occurs */ public BufferedFileChannelInputStream(final File file, final int bufferSizeInBytes) throws IOException { this(file.toPath(), bufferSizeInBytes); } /** * Constructs a new instance for the given Path. * * @param path The path to stream. * @throws IOException If an I/O error occurs */ public BufferedFileChannelInputStream(final Path path) throws IOException { this(path, IOUtils.DEFAULT_BUFFER_SIZE); } /** * Constructs a new instance for the given Path and buffer size. * * @param path The path to stream. * @param bufferSizeInBytes buffer size. * @throws IOException If an I/O error occurs */ public BufferedFileChannelInputStream(final Path path, final int bufferSizeInBytes) throws IOException { Objects.requireNonNull(path, "path"); fileChannel = FileChannel.open(path, StandardOpenOption.READ); byteBuffer = ByteBuffer.allocateDirect(bufferSizeInBytes); byteBuffer.flip(); } @Override public synchronized int available() throws IOException { return byteBuffer.remaining(); } /** * Attempts to clean up a ByteBuffer if it is direct or memory-mapped. This uses an *unsafe* Sun API that will cause * errors if one attempts to read from the disposed buffer. However, neither the bytes allocated to direct buffers * nor file descriptors opened for memory-mapped buffers put pressure on the garbage collector. Waiting for garbage * collection may lead to the depletion of off-heap memory or huge numbers of open files. There's unfortunately no * standard API to manually dispose of these kinds of buffers. * * @param buffer the buffer to clean. */ private void clean(final ByteBuffer buffer) { if (isDirectBuffer(buffer)) { cleanDirectBuffer(buffer); } } /** * In Java 8, the type of DirectBuffer.cleaner() was sun.misc.Cleaner, and it was possible to access the method * sun.misc.Cleaner.clean() to invoke it. The type changed to jdk.internal.ref.Cleaner in later JDKs, and the * .clean() method is not accessible even with reflection. However sun.misc.Unsafe added a invokeCleaner() method in * JDK 9+ and this is still accessible with reflection. * * @param buffer the buffer to clean. must be a DirectBuffer. */ private void cleanDirectBuffer(final ByteBuffer buffer) { // // Ported from StorageUtils.scala. // // private val bufferCleaner: DirectBuffer => Unit = // if (SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_9)) { // val cleanerMethod = // Utils.classForName("sun.misc.Unsafe").getMethod("invokeCleaner", classOf[ByteBuffer]) // val unsafeField = classOf[Unsafe].getDeclaredField("theUnsafe") // unsafeField.setAccessible(true) // val unsafe = unsafeField.get(null).asInstanceOf[Unsafe] // buffer: DirectBuffer => cleanerMethod.invoke(unsafe, buffer) // } else { // val cleanerMethod = Utils.classForName("sun.misc.Cleaner").getMethod("clean") // buffer: DirectBuffer => { // // Careful to avoid the return type of .cleaner(), which changes with JDK // val cleaner: AnyRef = buffer.cleaner() // if (cleaner != null) { // cleanerMethod.invoke(cleaner) // } // } // } // final String specVer = System.getProperty("java.specification.version"); if ("1.8".equals(specVer)) { // On Java 8, but also compiles on Java 11. try { final Class clsCleaner = Class.forName("sun.misc.Cleaner"); final Method cleanerMethod = DIRECT_BUFFER_CLASS.getMethod("cleaner"); final Object cleaner = cleanerMethod.invoke(buffer); if (cleaner != null) { final Method cleanMethod = clsCleaner.getMethod("clean"); cleanMethod.invoke(cleaner); } } catch (final ReflectiveOperationException e) { throw new IllegalStateException(e); } } else { // On Java 9 and up, but compiles on Java 8. try { final Class clsUnsafe = Class.forName("sun.misc.Unsafe"); final Method cleanerMethod = clsUnsafe.getMethod("invokeCleaner", ByteBuffer.class); final Field unsafeField = clsUnsafe.getDeclaredField("theUnsafe"); unsafeField.setAccessible(true); cleanerMethod.invoke(unsafeField.get(null), buffer); } catch (final ReflectiveOperationException e) { throw new IllegalStateException(e); } } } @Override public synchronized void close() throws IOException { try { fileChannel.close(); } finally { clean(byteBuffer); } } @Override public synchronized int read() throws IOException { if (!refill()) { return EOF; } return byteBuffer.get() & 0xFF; } @Override public synchronized int read(final byte[] b, final int offset, int len) throws IOException { if (offset < 0 || len < 0 || offset + len < 0 || offset + len > b.length) { throw new IndexOutOfBoundsException(); } if (!refill()) { return EOF; } len = Math.min(len, byteBuffer.remaining()); byteBuffer.get(b, offset, len); return len; } /** * Checks whether data is left to be read from the input stream. * * @return true if data is left, false otherwise */ private boolean refill() throws IOException { if (!byteBuffer.hasRemaining()) { byteBuffer.clear(); int nRead = 0; while (nRead == 0) { nRead = fileChannel.read(byteBuffer); } byteBuffer.flip(); return nRead >= 0; } return true; } @Override public synchronized long skip(final long n) throws IOException { if (n <= 0L) { return 0L; } if (byteBuffer.remaining() >= n) { // The buffered content is enough to skip byteBuffer.position(byteBuffer.position() + (int) n); return n; } final long skippedFromBuffer = byteBuffer.remaining(); final long toSkipFromFileChannel = n - skippedFromBuffer; // Discard everything we have read in the buffer. byteBuffer.position(0); byteBuffer.flip(); return skippedFromBuffer + skipFromFileChannel(toSkipFromFileChannel); } private long skipFromFileChannel(final long n) throws IOException { final long currentFilePosition = fileChannel.position(); final long size = fileChannel.size(); if (n > size - currentFilePosition) { fileChannel.position(size); return size - currentFilePosition; } fileChannel.position(currentFilePosition + n); return n; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/CharSequenceInputStream.java0100644 0000000 0000000 00000023261 13612062727 032303 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.apache.commons.io.IOUtils.EOF; import java.io.IOException; import java.io.InputStream; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.CharacterCodingException; import java.nio.charset.Charset; import java.nio.charset.CharsetEncoder; import java.nio.charset.CoderResult; import java.nio.charset.CodingErrorAction; import java.util.Objects; /** * {@link InputStream} implementation that can read from String, StringBuffer, * StringBuilder or CharBuffer. *

* Note: Supports {@link #mark(int)} and {@link #reset()}. *

* * @since 2.2 */ public class CharSequenceInputStream extends InputStream { private static final int BUFFER_SIZE = 2048; private static final int NO_MARK = -1; private final CharsetEncoder encoder; private final CharBuffer cbuf; private final ByteBuffer bbuf; private int mark_cbuf; // position in cbuf private int mark_bbuf; // position in bbuf /** * Constructor. * * @param cs the input character sequence * @param charset the character set name to use * @param bufferSize the buffer size to use. * @throws IllegalArgumentException if the buffer is not large enough to hold a complete character */ public CharSequenceInputStream(final CharSequence cs, final Charset charset, final int bufferSize) { this.encoder = charset.newEncoder() .onMalformedInput(CodingErrorAction.REPLACE) .onUnmappableCharacter(CodingErrorAction.REPLACE); // Ensure that buffer is long enough to hold a complete character final float maxBytesPerChar = encoder.maxBytesPerChar(); if (bufferSize < maxBytesPerChar) { throw new IllegalArgumentException("Buffer size " + bufferSize + " is less than maxBytesPerChar " + maxBytesPerChar); } this.bbuf = ByteBuffer.allocate(bufferSize); this.bbuf.flip(); this.cbuf = CharBuffer.wrap(cs); this.mark_cbuf = NO_MARK; this.mark_bbuf = NO_MARK; } /** * Constructor, calls {@link #CharSequenceInputStream(CharSequence, Charset, int)}. * * @param cs the input character sequence * @param charset the character set name to use * @param bufferSize the buffer size to use. * @throws IllegalArgumentException if the buffer is not large enough to hold a complete character */ public CharSequenceInputStream(final CharSequence cs, final String charset, final int bufferSize) { this(cs, Charset.forName(charset), bufferSize); } /** * Constructor, calls {@link #CharSequenceInputStream(CharSequence, Charset, int)} * with a buffer size of 2048. * * @param cs the input character sequence * @param charset the character set name to use * @throws IllegalArgumentException if the buffer is not large enough to hold a complete character */ public CharSequenceInputStream(final CharSequence cs, final Charset charset) { this(cs, charset, BUFFER_SIZE); } /** * Constructor, calls {@link #CharSequenceInputStream(CharSequence, String, int)} * with a buffer size of 2048. * * @param cs the input character sequence * @param charset the character set name to use * @throws IllegalArgumentException if the buffer is not large enough to hold a complete character */ public CharSequenceInputStream(final CharSequence cs, final String charset) { this(cs, charset, BUFFER_SIZE); } /** * Fills the byte output buffer from the input char buffer. * * @throws CharacterCodingException * an error encoding data */ private void fillBuffer() throws CharacterCodingException { this.bbuf.compact(); final CoderResult result = this.encoder.encode(this.cbuf, this.bbuf, true); if (result.isError()) { result.throwException(); } this.bbuf.flip(); } @Override public int read(final byte[] array, int off, int len) throws IOException { Objects.requireNonNull(array, "array"); if (len < 0 || (off + len) > array.length) { throw new IndexOutOfBoundsException("Array Size=" + array.length + ", offset=" + off + ", length=" + len); } if (len == 0) { return 0; // must return 0 for zero length read } if (!this.bbuf.hasRemaining() && !this.cbuf.hasRemaining()) { return EOF; } int bytesRead = 0; while (len > 0) { if (this.bbuf.hasRemaining()) { final int chunk = Math.min(this.bbuf.remaining(), len); this.bbuf.get(array, off, chunk); off += chunk; len -= chunk; bytesRead += chunk; } else { fillBuffer(); if (!this.bbuf.hasRemaining() && !this.cbuf.hasRemaining()) { break; } } } return bytesRead == 0 && !this.cbuf.hasRemaining() ? EOF : bytesRead; } @Override public int read() throws IOException { for (;;) { if (this.bbuf.hasRemaining()) { return this.bbuf.get() & 0xFF; } fillBuffer(); if (!this.bbuf.hasRemaining() && !this.cbuf.hasRemaining()) { return EOF; } } } @Override public int read(final byte[] b) throws IOException { return read(b, 0, b.length); } @Override public long skip(long n) throws IOException { /* * This could be made more efficient by using position to skip within the current buffer. */ long skipped = 0; while (n > 0 && available() > 0) { this.read(); n--; skipped++; } return skipped; } /** * Return an estimate of the number of bytes remaining in the byte stream. * @return the count of bytes that can be read without blocking (or returning EOF). * * @throws IOException if an error occurs (probably not possible) */ @Override public int available() throws IOException { // The cached entries are in bbuf; since encoding always creates at least one byte // per character, we can add the two to get a better estimate (e.g. if bbuf is empty) // Note that the previous implementation (2.4) could return zero even though there were // encoded bytes still available. return this.bbuf.remaining() + this.cbuf.remaining(); } @Override public void close() throws IOException { // noop } /** * {@inheritDoc} * @param readlimit max read limit (ignored) */ @Override public synchronized void mark(final int readlimit) { this.mark_cbuf = this.cbuf.position(); this.mark_bbuf = this.bbuf.position(); this.cbuf.mark(); this.bbuf.mark(); // It would be nice to be able to use mark & reset on the cbuf and bbuf; // however the bbuf is re-used so that won't work } @Override public synchronized void reset() throws IOException { /* * This is not the most efficient implementation, as it re-encodes from the beginning. * * Since the bbuf is re-used, in general it's necessary to re-encode the data. * * It should be possible to apply some optimisations however: * + use mark/reset on the cbuf and bbuf. This would only work if the buffer had not been (re)filled since * the mark. The code would have to catch InvalidMarkException - does not seem possible to check if mark is * valid otherwise. + Try saving the state of the cbuf before each fillBuffer; it might be possible to * restart from there. */ if (this.mark_cbuf != NO_MARK) { // if cbuf is at 0, we have not started reading anything, so skip re-encoding if (this.cbuf.position() != 0) { this.encoder.reset(); this.cbuf.rewind(); this.bbuf.rewind(); this.bbuf.limit(0); // rewind does not clear the buffer while(this.cbuf.position() < this.mark_cbuf) { this.bbuf.rewind(); // empty the buffer (we only refill when empty during normal processing) this.bbuf.limit(0); fillBuffer(); } } if (this.cbuf.position() != this.mark_cbuf) { throw new IllegalStateException("Unexpected CharBuffer position: actual=" + cbuf.position() + " " + "expected=" + this.mark_cbuf); } this.bbuf.position(this.mark_bbuf); this.mark_cbuf = NO_MARK; this.mark_bbuf = NO_MARK; } } @Override public boolean markSupported() { return true; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/CharSequenceReader.java0100644 0000000 0000000 00000023754 13612062727 031241 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.apache.commons.io.IOUtils.EOF; import java.io.Reader; import java.io.Serializable; import java.util.Objects; /** * {@link Reader} implementation that can read from String, StringBuffer, * StringBuilder or CharBuffer. *

* Note: Supports {@link #mark(int)} and {@link #reset()}. *

* * @since 1.4 */ public class CharSequenceReader extends Reader implements Serializable { private static final long serialVersionUID = 3724187752191401220L; private final CharSequence charSequence; private int idx; private int mark; /** * The start index in the character sequence, inclusive. *

* When de-serializing a CharSequenceReader that was serialized before * this fields was added, this field will be initialized to 0, which * gives the same behavior as before: start reading from the start. *

* * @see #start() * @since 2.7 */ private final int start; /** * The end index in the character sequence, exclusive. *

* When de-serializing a CharSequenceReader that was serialized before * this fields was added, this field will be initialized to {@code null}, * which gives the same behavior as before: stop reading at the * CharSequence's length. * If this field was an int instead, it would be initialized to 0 when the * CharSequenceReader is de-serialized, causing it to not return any * characters at all. *

* * @see #end() * @since 2.7 */ private final Integer end; /** * Constructs a new instance with the specified character sequence. * * @param charSequence The character sequence, may be {@code null} */ public CharSequenceReader(final CharSequence charSequence) { this(charSequence, 0); } /** * Constructs a new instance with a portion of the specified character sequence. *

* The start index is not strictly enforced to be within the bounds of the * character sequence. This allows the character sequence to grow or shrink * in size without risking any {@link IndexOutOfBoundsException} to be thrown. * Instead, if the character sequence grows smaller than the start index, this * instance will act as if all characters have been read. *

* * @param charSequence The character sequence, may be {@code null} * @param start The start index in the character sequence, inclusive * @throws IllegalArgumentException if the start index is negative * @since 2.7 */ public CharSequenceReader(final CharSequence charSequence, final int start) { this(charSequence, start, Integer.MAX_VALUE); } /** * Constructs a new instance with a portion of the specified character sequence. *

* The start and end indexes are not strictly enforced to be within the bounds * of the character sequence. This allows the character sequence to grow or shrink * in size without risking any {@link IndexOutOfBoundsException} to be thrown. * Instead, if the character sequence grows smaller than the start index, this * instance will act as if all characters have been read; if the character sequence * grows smaller than the end, this instance will use the actual character sequence * length. *

* * @param charSequence The character sequence, may be {@code null} * @param start The start index in the character sequence, inclusive * @param end The end index in the character sequence, exclusive * @throws IllegalArgumentException if the start index is negative, or if the end index is smaller than the start index * @since 2.7 */ public CharSequenceReader(final CharSequence charSequence, final int start, final int end) { if (start < 0) { throw new IllegalArgumentException( "Start index is less than zero: " + start); } if (end < start) { throw new IllegalArgumentException( "End index is less than start " + start + ": " + end); } // Don't check the start and end indexes against the CharSequence, // to let it grow and shrink without breaking existing behavior. this.charSequence = charSequence != null ? charSequence : ""; this.start = start; this.end = end; this.idx = start; this.mark = start; } /** * Returns the index in the character sequence to start reading from, taking into account its length. * * @return The start index in the character sequence (inclusive). */ private int start() { return Math.min(charSequence.length(), start); } /** * Returns the index in the character sequence to end reading at, taking into account its length. * * @return The end index in the character sequence (exclusive). */ private int end() { /* * end == null for de-serialized instances that were serialized before start and end were added. * Use Integer.MAX_VALUE to get the same behavior as before - use the entire CharSequence. */ return Math.min(charSequence.length(), end == null ? Integer.MAX_VALUE : end); } /** * Close resets the file back to the start and removes any marked position. */ @Override public void close() { idx = start; mark = start; } /** * Tells whether this stream is ready to be read. * * @return {@code true} if more characters from the character sequence are available, or {@code false} otherwise. */ @Override public boolean ready() { return idx < end(); } /** * Mark the current position. * * @param readAheadLimit ignored */ @Override public void mark(final int readAheadLimit) { mark = idx; } /** * Mark is supported (returns true). * * @return {@code true} */ @Override public boolean markSupported() { return true; } /** * Read a single character. * * @return the next character from the character sequence * or -1 if the end has been reached. */ @Override public int read() { if (idx >= end()) { return EOF; } return charSequence.charAt(idx++); } /** * Read the specified number of characters into the array. * * @param array The array to store the characters in * @param offset The starting position in the array to store * @param length The maximum number of characters to read * @return The number of characters read or -1 if there are * no more */ @Override public int read(final char[] array, final int offset, final int length) { if (idx >= end()) { return EOF; } Objects.requireNonNull(array, "array"); if (length < 0 || offset < 0 || offset + length > array.length) { throw new IndexOutOfBoundsException("Array Size=" + array.length + ", offset=" + offset + ", length=" + length); } if (charSequence instanceof String) { final int count = Math.min(length, end() - idx); ((String) charSequence).getChars(idx, idx + count, array, offset); idx += count; return count; } if (charSequence instanceof StringBuilder) { final int count = Math.min(length, end() - idx); ((StringBuilder) charSequence).getChars(idx, idx + count, array, offset); idx += count; return count; } if (charSequence instanceof StringBuffer) { final int count = Math.min(length, end() - idx); ((StringBuffer) charSequence).getChars(idx, idx + count, array, offset); idx += count; return count; } int count = 0; for (int i = 0; i < length; i++) { final int c = read(); if (c == EOF) { return count; } array[offset + i] = (char)c; count++; } return count; } /** * Reset the reader to the last marked position (or the beginning if * mark has not been called). */ @Override public void reset() { idx = mark; } /** * Skip the specified number of characters. * * @param n The number of characters to skip * @return The actual number of characters skipped */ @Override public long skip(final long n) { if (n < 0) { throw new IllegalArgumentException( "Number of characters to skip is less than zero: " + n); } if (idx >= end()) { return 0; } final int dest = (int)Math.min(end(), idx + n); final int count = dest - idx; idx = dest; return count; } /** * Return a String representation of the underlying * character sequence. * * @return The contents of the character sequence */ @Override public String toString() { final CharSequence subSequence = charSequence.subSequence(start(), end()); return subSequence.toString(); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/CharacterFilterReader.java0100644 0000000 0000000 00000003555 13612062727 031732 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import java.io.Reader; import java.util.function.IntPredicate; /** * A filter reader that filters out a given character represented as an {@code int} code point, handy to remove * known junk characters from CSV files for example. This class is the most efficient way to filter out a single * character, as opposed to using a {@link CharacterSetFilterReader}. You can also nest {@link CharacterFilterReader}s. */ public class CharacterFilterReader extends AbstractCharacterFilterReader { /** * Constructs a new reader. * * @param reader * the reader to filter. * @param skip * the character to filter out. */ public CharacterFilterReader(final Reader reader, final int skip) { super(reader, c -> c == skip); } /** * Constructs a new reader. * * @param reader the reader to filter. * @param skip Skip test. * @since 2.9.0 */ public CharacterFilterReader(final Reader reader, final IntPredicate skip) { super(reader, skip); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/CharacterSetFilterReader.java0100644 0000000 0000000 00000004444 13612062727 032404 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import java.io.Reader; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Set; import java.util.function.IntPredicate; /** * A filter reader that removes a given set of characters represented as {@code int} code points, handy to remove known * junk characters from CSV files for example. *

* This class must convert each {@code int} read to an {@code Integer}. You can increase the Integer cache with a system * property, see {@link Integer}. *

*/ public class CharacterSetFilterReader extends AbstractCharacterFilterReader { private static IntPredicate toIntPredicate(final Set skip) { if (skip == null) { return SKIP_NONE; } final Set unmodifiableSet = Collections.unmodifiableSet(skip); return c -> unmodifiableSet.contains(Integer.valueOf(c)); } /** * Constructs a new reader. * * @param reader the reader to filter. * @param skip the set of characters to filter out. * @since 2.9.0 */ public CharacterSetFilterReader(final Reader reader, final Integer... skip) { this(reader, new HashSet<>(Arrays.asList(skip))); } /** * Constructs a new reader. * * @param reader the reader to filter. * @param skip the set of characters to filter out. */ public CharacterSetFilterReader(final Reader reader, final Set skip) { super(reader, toIntPredicate(skip)); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/CircularInputStream.java0100644 0000000 0000000 00000005635 13612062727 031506 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import java.io.IOException; import java.io.InputStream; import java.util.Objects; import org.apache.commons.io.IOUtils; /** * * An {@link InputStream} that repeats provided bytes for given target byte count. *

* Closing this input stream has no effect. The methods in this class can be called after the stream has been closed * without generating an {@link IOException}. *

* * @see InfiniteCircularInputStream * @since 2.8.0 */ public class CircularInputStream extends InputStream { /** * Throws an {@link IllegalArgumentException} if the input contains -1. * * @param repeatContent input to validate. * @return the input. */ private static byte[] validate(final byte[] repeatContent) { Objects.requireNonNull(repeatContent, "repeatContent"); for (final byte b : repeatContent) { if (b == IOUtils.EOF) { throw new IllegalArgumentException("repeatContent contains the end-of-stream marker " + IOUtils.EOF); } } return repeatContent; } private long byteCount; private int position = -1; private final byte[] repeatedContent; private final long targetByteCount; /** * Creates an instance from the specified array of bytes. * * @param repeatContent Input buffer to be repeated this buffer is not copied. * @param targetByteCount How many bytes the read. A negative number means an infinite target count. */ public CircularInputStream(final byte[] repeatContent, final long targetByteCount) { this.repeatedContent = validate(repeatContent); if (repeatContent.length == 0) { throw new IllegalArgumentException("repeatContent is empty."); } this.targetByteCount = targetByteCount; } @Override public int read() { if (targetByteCount >= 0) { if (byteCount == targetByteCount) { return IOUtils.EOF; } byteCount++; } position = (position + 1) % repeatedContent.length; return repeatedContent[position] & 0xff; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/ClassLoaderObjectInputStream.java0100644 0000000 0000000 00000007440 13612062727 033261 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectStreamClass; import java.io.StreamCorruptedException; import java.lang.reflect.Proxy; /** * A special ObjectInputStream that loads a class based on a specified * {@code ClassLoader} rather than the system default. *

* This is useful in dynamic container environments. *

* * @since 1.1 */ public class ClassLoaderObjectInputStream extends ObjectInputStream { /** The class loader to use. */ private final ClassLoader classLoader; /** * Constructs a new ClassLoaderObjectInputStream. * * @param classLoader the ClassLoader from which classes should be loaded * @param inputStream the InputStream to work on * @throws IOException in case of an I/O error * @throws StreamCorruptedException if the stream is corrupted */ public ClassLoaderObjectInputStream( final ClassLoader classLoader, final InputStream inputStream) throws IOException, StreamCorruptedException { super(inputStream); this.classLoader = classLoader; } /** * Resolve a class specified by the descriptor using the * specified ClassLoader or the super ClassLoader. * * @param objectStreamClass descriptor of the class * @return the Class object described by the ObjectStreamClass * @throws IOException in case of an I/O error * @throws ClassNotFoundException if the Class cannot be found */ @Override protected Class resolveClass(final ObjectStreamClass objectStreamClass) throws IOException, ClassNotFoundException { try { return Class.forName(objectStreamClass.getName(), false, classLoader); } catch (final ClassNotFoundException cnfe) { // delegate to super class loader which can resolve primitives return super.resolveClass(objectStreamClass); } } /** * Create a proxy class that implements the specified interfaces using * the specified ClassLoader or the super ClassLoader. * * @param interfaces the interfaces to implement * @return a proxy class implementing the interfaces * @throws IOException in case of an I/O error * @throws ClassNotFoundException if the Class cannot be found * @see java.io.ObjectInputStream#resolveProxyClass(java.lang.String[]) * @since 2.1 */ @Override protected Class resolveProxyClass(final String[] interfaces) throws IOException, ClassNotFoundException { final Class[] interfaceClasses = new Class[interfaces.length]; for (int i = 0; i < interfaces.length; i++) { interfaceClasses[i] = Class.forName(interfaces[i], false, classLoader); } try { return Proxy.getProxyClass(classLoader, interfaceClasses); } catch (final IllegalArgumentException e) { return super.resolveProxyClass(interfaces); } } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/CloseShieldInputStream.java0100644 0000000 0000000 00000004501 13612062727 032127 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import java.io.InputStream; /** * Proxy stream that prevents the underlying input stream from being closed. *

* This class is typically used in cases where an input stream needs to be * passed to a component that wants to explicitly close the stream even if more * input would still be available to other components. *

* * @since 1.4 */ public class CloseShieldInputStream extends ProxyInputStream { /** * Creates a proxy that shields the given input stream from being closed. * * @param inputStream the input stream to wrap * @return the created proxy * @since 2.9.0 */ public static CloseShieldInputStream wrap(final InputStream inputStream) { return new CloseShieldInputStream(inputStream); } /** * Creates a proxy that shields the given input stream from being closed. * * @param inputStream underlying input stream * @deprecated Using this constructor prevents IDEs from warning if the * underlying input stream is never closed. Use * {@link #wrap(InputStream)} instead. */ @Deprecated public CloseShieldInputStream(final InputStream inputStream) { super(inputStream); } /** * Replaces the underlying input stream with a {@link ClosedInputStream} * sentinel. The original input stream will remain open, but this proxy will * appear closed. */ @Override public void close() { in = ClosedInputStream.CLOSED_INPUT_STREAM; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/CloseShieldReader.java0100644 0000000 0000000 00000004250 13612062727 031057 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import java.io.Reader; /** * Proxy reader that prevents the underlying reader from being closed. *

* This class is typically used in cases where a reader needs to be passed to a * component that wants to explicitly close the reader even if more input would * still be available to other components. *

* * @since 2.7 */ public class CloseShieldReader extends ProxyReader { /** * Creates a proxy that shields the given reader from being closed. * * @param reader the reader to wrap * @return the created proxy * @since 2.9.0 */ public static CloseShieldReader wrap(final Reader reader) { return new CloseShieldReader(reader); } /** * Creates a proxy that shields the given reader from being closed. * * @param reader underlying reader * @deprecated Using this constructor prevents IDEs from warning if the * underlying reader is never closed. Use {@link #wrap(Reader)} * instead. */ @Deprecated public CloseShieldReader(final Reader reader) { super(reader); } /** * Replaces the underlying reader with a {@link ClosedReader} sentinel. The * original reader will remain open, but this proxy will appear closed. */ @Override public void close() { in = ClosedReader.CLOSED_READER; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/ClosedInputStream.java0100644 0000000 0000000 00000003071 13612062727 031143 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.apache.commons.io.IOUtils.EOF; import java.io.InputStream; /** * Closed input stream. This stream returns EOF to all attempts to read * something from the stream. *

* Typically uses of this class include testing for corner cases in methods * that accept input streams and acting as a sentinel value instead of a * {@code null} input stream. *

* * @since 1.4 */ public class ClosedInputStream extends InputStream { /** * A singleton. */ public static final ClosedInputStream CLOSED_INPUT_STREAM = new ClosedInputStream(); /** * Returns -1 to indicate that the stream is closed. * * @return always -1 */ @Override public int read() { return EOF; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/ClosedReader.java0100644 0000000 0000000 00000003350 13612062727 030072 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.apache.commons.io.IOUtils.EOF; import java.io.IOException; import java.io.Reader; /** * Closed reader. This reader returns EOF to all attempts to read something from it. *

* Typically uses of this class include testing for corner cases in methods that accept readers and acting as a sentinel * value instead of a {@code null} reader. *

* * @since 2.7 */ public class ClosedReader extends Reader { /** * A singleton. */ public static final ClosedReader CLOSED_READER = new ClosedReader(); /** * Returns -1 to indicate that the stream is closed. * * @param cbuf ignored * @param off ignored * @param len ignored * @return always -1 */ @Override public int read(final char[] cbuf, final int off, final int len) { return EOF; } @Override public void close() throws IOException { // noop } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/CountingInputStream.java0100644 0000000 0000000 00000010767 13612062727 031532 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.apache.commons.io.IOUtils.EOF; import java.io.IOException; import java.io.InputStream; /** * A decorating input stream that counts the number of bytes that have passed * through the stream so far. *

* A typical use case would be during debugging, to ensure that data is being * read as expected. *

*/ public class CountingInputStream extends ProxyInputStream { /** The count of bytes that have passed. */ private long count; /** * Constructs a new CountingInputStream. * * @param in the InputStream to delegate to */ public CountingInputStream(final InputStream in) { super(in); } /** * Skips the stream over the specified number of bytes, adding the skipped * amount to the count. * * @param length the number of bytes to skip * @return the actual number of bytes skipped * @throws IOException if an I/O error occurs. * @see java.io.InputStream#skip(long) */ @Override public synchronized long skip(final long length) throws IOException { final long skip = super.skip(length); this.count += skip; return skip; } /** * Adds the number of read bytes to the count. * * @param n number of bytes read, or -1 if no more bytes are available * @since 2.0 */ @Override protected synchronized void afterRead(final int n) { if (n != EOF) { this.count += n; } } /** * The number of bytes that have passed through this stream. *

* NOTE: From v1.3 this method throws an ArithmeticException if the * count is greater than can be expressed by an {@code int}. * See {@link #getByteCount()} for a method using a {@code long}. * * @return the number of bytes accumulated * @throws ArithmeticException if the byte count is too large */ public int getCount() { final long result = getByteCount(); if (result > Integer.MAX_VALUE) { throw new ArithmeticException("The byte count " + result + " is too large to be converted to an int"); } return (int) result; } /** * Set the byte count back to 0. *

* NOTE: From v1.3 this method throws an ArithmeticException if the * count is greater than can be expressed by an {@code int}. * See {@link #resetByteCount()} for a method using a {@code long}. * * @return the count previous to resetting * @throws ArithmeticException if the byte count is too large */ public int resetCount() { final long result = resetByteCount(); if (result > Integer.MAX_VALUE) { throw new ArithmeticException("The byte count " + result + " is too large to be converted to an int"); } return (int) result; } /** * The number of bytes that have passed through this stream. *

* NOTE: This method is an alternative for {@code getCount()} * and was added because that method returns an integer which will * result in incorrect count for files over 2GB. * * @return the number of bytes accumulated * @since 1.3 */ public synchronized long getByteCount() { return this.count; } /** * Set the byte count back to 0. *

* NOTE: This method is an alternative for {@code resetCount()} * and was added because that method returns an integer which will * result in incorrect count for files over 2GB. * * @return the count previous to resetting * @since 1.3 */ public synchronized long resetByteCount() { final long tmp = this.count; this.count = 0; return tmp; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/DemuxInputStream.java0100644 0000000 0000000 00000004475 13612062727 031025 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.apache.commons.io.IOUtils.EOF; import java.io.IOException; import java.io.InputStream; import org.apache.commons.io.IOUtils; /** * Data written to this stream is forwarded to a stream that has been associated with this thread. */ public class DemuxInputStream extends InputStream { private final InheritableThreadLocal inputStreamLocal = new InheritableThreadLocal<>(); /** * Binds the specified stream to the current thread. * * @param input the stream to bind * @return the InputStream that was previously active */ public InputStream bindStream(final InputStream input) { final InputStream oldValue = inputStreamLocal.get(); inputStreamLocal.set(input); return oldValue; } /** * Closes stream associated with current thread. * * @throws IOException if an error occurs */ @SuppressWarnings("resource") // we actually close the stream here @Override public void close() throws IOException { IOUtils.close(inputStreamLocal.get()); } /** * Reads byte from stream associated with current thread. * * @return the byte read from stream * @throws IOException if an error occurs */ @SuppressWarnings("resource") @Override public int read() throws IOException { final InputStream inputStream = inputStreamLocal.get(); if (null != inputStream) { return inputStream.read(); } return EOF; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/InfiniteCircularInputStream.java0100644 0000000 0000000 00000003063 13612062727 033165 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import java.io.IOException; import java.io.InputStream; /** * * An {@link InputStream} that infinitely repeats the provided bytes. *

* Closing this input stream has no effect. The methods in this class can be called after the stream has been closed * without generating an {@link IOException}. *

* * @since 2.6 */ public class InfiniteCircularInputStream extends CircularInputStream { /** * Creates an instance from the specified array of bytes. * * @param repeatContent Input buffer to be repeated this buffer is not copied. */ public InfiniteCircularInputStream(final byte[] repeatContent) { // A negative number means an infinite target count. super(repeatContent, -1); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/MarkShieldInputStream.java0100644 0000000 0000000 00000004061 13612062727 031755 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import java.io.IOException; import java.io.InputStream; /** * This is an alternative to {@link java.io.ByteArrayInputStream} * which removes the synchronization overhead for non-concurrent * access; as such this class is not thread-safe. * * Proxy stream that prevents the underlying input stream from being marked/reset. *

* This class is typically used in cases where an input stream that supports * marking needs to be passed to a component that wants to explicitly mark * the stream, but it it is not desirable to allow marking of the stream. *

* * @since 2.8.0 */ public class MarkShieldInputStream extends ProxyInputStream { /** * Creates a proxy that shields the given input stream from being * marked or rest. * * @param in underlying input stream */ public MarkShieldInputStream(final InputStream in) { super(in); } @SuppressWarnings("sync-override") @Override public void mark(final int readlimit) { // no-op } @Override public boolean markSupported() { return false; } @SuppressWarnings("sync-override") @Override public void reset() throws IOException { throw UnsupportedOperationExceptions.reset(); } } ././@LongLink0100644 0000000 0000000 00000000151 13612062727 011636 Lustar 0000000 0000000 commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/MessageDigestCalculatingInputStream.javacommons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/MessageDigestCalculatingInputStream.0100644 0000000 0000000 00000010747 13612062727 033773 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import java.io.IOException; import java.io.InputStream; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; /** * This class is an example for using an {@link ObservableInputStream}. It * creates its own {@link org.apache.commons.io.input.ObservableInputStream.Observer}, * which calculates a checksum using a MessageDigest, for example an MD5 sum. * Note: Neither {@link ObservableInputStream}, nor {@link MessageDigest}, * are thread safe. So is {@link MessageDigestCalculatingInputStream}. */ public class MessageDigestCalculatingInputStream extends ObservableInputStream { /** * Maintains the message digest. */ public static class MessageDigestMaintainingObserver extends Observer { private final MessageDigest messageDigest; /** * Creates an MessageDigestMaintainingObserver for the given MessageDigest. * @param messageDigest the message digest to use */ public MessageDigestMaintainingObserver(final MessageDigest messageDigest) { this.messageDigest = messageDigest; } @Override public void data(final int input) throws IOException { messageDigest.update((byte) input); } @Override public void data(final byte[] input, final int offset, final int length) throws IOException { messageDigest.update(input, offset, length); } } private final MessageDigest messageDigest; /** Creates a new instance, which calculates a signature on the given stream, * using the given {@link MessageDigest}. * @param inputStream the stream to calculate the message digest for * @param messageDigest the message digest to use */ public MessageDigestCalculatingInputStream(final InputStream inputStream, final MessageDigest messageDigest) { super(inputStream, new MessageDigestMaintainingObserver(messageDigest)); this.messageDigest = messageDigest; } /** * Creates a new instance, which calculates a signature on the given stream, using a {@link MessageDigest} with the * given algorithm. * * @param inputStream the stream to calculate the message digest for * @param algorithm the name of the algorithm to use * @throws NoSuchAlgorithmException if no Provider supports a MessageDigestSpi implementation for the specified * algorithm. */ public MessageDigestCalculatingInputStream(final InputStream inputStream, final String algorithm) throws NoSuchAlgorithmException { this(inputStream, MessageDigest.getInstance(algorithm)); } /** * Creates a new instance, which calculates a signature on the given stream, using a {@link MessageDigest} with the * "MD5" algorithm. * * @param inputStream the stream to calculate the message digest for * @throws NoSuchAlgorithmException if no Provider supports a MessageDigestSpi implementation for the specified * algorithm. */ public MessageDigestCalculatingInputStream(final InputStream inputStream) throws NoSuchAlgorithmException { this(inputStream, MessageDigest.getInstance("MD5")); } /** Returns the {@link MessageDigest}, which is being used for generating the * checksum. * Note: The checksum will only reflect the data, which has been read so far. * This is probably not, what you expect. Make sure, that the complete data has been * read, if that is what you want. The easiest way to do so is by invoking * {@link #consume()}. * @return the message digest used */ public MessageDigest getMessageDigest() { return messageDigest; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/NullInputStream.java0100644 0000000 0000000 00000025213 13612062727 030646 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.apache.commons.io.IOUtils.EOF; import java.io.EOFException; import java.io.IOException; import java.io.InputStream; /** * A functional, light weight {@link InputStream} that emulates * a stream of a specified size. *

* This implementation provides a light weight * object for testing with an {@link InputStream} * where the contents don't matter. *

*

* One use case would be for testing the handling of * large {@link InputStream} as it can emulate that * scenario without the overhead of actually processing * large numbers of bytes - significantly speeding up * test execution times. *

*

* This implementation returns zero from the method that * reads a byte and leaves the array unchanged in the read * methods that are passed a byte array. * If alternative data is required the {@code processByte()} and * {@code processBytes()} methods can be implemented to generate * data, for example: *

* *
 *  public class TestInputStream extends NullInputStream {
 *      public TestInputStream(int size) {
 *          super(size);
 *      }
 *      protected int processByte() {
 *          return ... // return required value here
 *      }
 *      protected void processBytes(byte[] bytes, int offset, int length) {
 *          for (int i = offset; i < length; i++) {
 *              bytes[i] = ... // set array value here
 *          }
 *      }
 *  }
 * 
* * @since 1.3 * */ public class NullInputStream extends InputStream { private final long size; private long position; private long mark = -1; private long readlimit; private boolean eof; private final boolean throwEofException; private final boolean markSupported; /** * Create an {@link InputStream} that emulates a size 0 stream * which supports marking and does not throw EOFException. * * @since 2.7 */ public NullInputStream() { this(0, true, false); } /** * Create an {@link InputStream} that emulates a specified size * which supports marking and does not throw EOFException. * * @param size The size of the input stream to emulate. */ public NullInputStream(final long size) { this(size, true, false); } /** * Create an {@link InputStream} that emulates a specified * size with option settings. * * @param size The size of the input stream to emulate. * @param markSupported Whether this instance will support * the {@code mark()} functionality. * @param throwEofException Whether this implementation * will throw an {@link EOFException} or return -1 when the * end of file is reached. */ public NullInputStream(final long size, final boolean markSupported, final boolean throwEofException) { this.size = size; this.markSupported = markSupported; this.throwEofException = throwEofException; } /** * Return the current position. * * @return the current position. */ public long getPosition() { return position; } /** * Return the size this {@link InputStream} emulates. * * @return The size of the input stream to emulate. */ public long getSize() { return size; } /** * Return the number of bytes that can be read. * * @return The number of bytes that can be read. */ @Override public int available() { final long avail = size - position; if (avail <= 0) { return 0; } if (avail > Integer.MAX_VALUE) { return Integer.MAX_VALUE; } return (int) avail; } /** * Close this input stream - resets the internal state to * the initial values. * * @throws IOException If an error occurs. */ @Override public void close() throws IOException { eof = false; position = 0; mark = -1; } /** * Mark the current position. * * @param readlimit The number of bytes before this marked position * is invalid. * @throws UnsupportedOperationException if mark is not supported. */ @Override public synchronized void mark(final int readlimit) { if (!markSupported) { throw UnsupportedOperationExceptions.mark(); } mark = position; this.readlimit = readlimit; } /** * Indicates whether mark is supported. * * @return Whether mark is supported or not. */ @Override public boolean markSupported() { return markSupported; } /** * Read a byte. * * @return Either The byte value returned by {@code processByte()} * or {@code -1} if the end of file has been reached and * {@code throwEofException} is set to {@code false}. * @throws EOFException if the end of file is reached and * {@code throwEofException} is set to {@code true}. * @throws IOException if trying to read past the end of file. */ @Override public int read() throws IOException { if (eof) { throw new IOException("Read after end of file"); } if (position == size) { return doEndOfFile(); } position++; return processByte(); } /** * Read some bytes into the specified array. * * @param bytes The byte array to read into * @return The number of bytes read or {@code -1} * if the end of file has been reached and * {@code throwEofException} is set to {@code false}. * @throws EOFException if the end of file is reached and * {@code throwEofException} is set to {@code true}. * @throws IOException if trying to read past the end of file. */ @Override public int read(final byte[] bytes) throws IOException { return read(bytes, 0, bytes.length); } /** * Read the specified number bytes into an array. * * @param bytes The byte array to read into. * @param offset The offset to start reading bytes into. * @param length The number of bytes to read. * @return The number of bytes read or {@code -1} * if the end of file has been reached and * {@code throwEofException} is set to {@code false}. * @throws EOFException if the end of file is reached and * {@code throwEofException} is set to {@code true}. * @throws IOException if trying to read past the end of file. */ @Override public int read(final byte[] bytes, final int offset, final int length) throws IOException { if (eof) { throw new IOException("Read after end of file"); } if (position == size) { return doEndOfFile(); } position += length; int returnLength = length; if (position > size) { returnLength = length - (int)(position - size); position = size; } processBytes(bytes, offset, returnLength); return returnLength; } /** * Reset the stream to the point when mark was last called. * * @throws UnsupportedOperationException if mark is not supported. * @throws IOException If no position has been marked * or the read limit has been exceed since the last position was * marked. */ @Override public synchronized void reset() throws IOException { if (!markSupported) { throw UnsupportedOperationExceptions.reset(); } if (mark < 0) { throw new IOException("No position has been marked"); } if (position > mark + readlimit) { throw new IOException("Marked position [" + mark + "] is no longer valid - passed the read limit [" + readlimit + "]"); } position = mark; eof = false; } /** * Skip a specified number of bytes. * * @param numberOfBytes The number of bytes to skip. * @return The number of bytes skipped or {@code -1} * if the end of file has been reached and * {@code throwEofException} is set to {@code false}. * @throws EOFException if the end of file is reached and * {@code throwEofException} is set to {@code true}. * @throws IOException if trying to read past the end of file. */ @Override public long skip(final long numberOfBytes) throws IOException { if (eof) { throw new IOException("Skip after end of file"); } if (position == size) { return doEndOfFile(); } position += numberOfBytes; long returnLength = numberOfBytes; if (position > size) { returnLength = numberOfBytes - (position - size); position = size; } return returnLength; } /** * Return a byte value for the {@code read()} method. *

* This implementation returns zero. * * @return This implementation always returns zero. */ protected int processByte() { // do nothing - overridable by subclass return 0; } /** * Process the bytes for the {@code read(byte[], offset, length)} * method. *

* This implementation leaves the byte array unchanged. * * @param bytes The byte array * @param offset The offset to start at. * @param length The number of bytes. */ protected void processBytes(final byte[] bytes, final int offset, final int length) { // do nothing - overridable by subclass } /** * Handle End of File. * * @return {@code -1} if {@code throwEofException} is * set to {@code false} * @throws EOFException if {@code throwEofException} is set * to {@code true}. */ private int doEndOfFile() throws EOFException { eof = true; if (throwEofException) { throw new EOFException(); } return EOF; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/NullReader.java0100644 0000000 0000000 00000024450 13612062727 027577 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.apache.commons.io.IOUtils.EOF; import java.io.EOFException; import java.io.IOException; import java.io.Reader; /** * A functional, light weight {@link Reader} that emulates * a reader of a specified size. *

* This implementation provides a light weight * object for testing with an {@link Reader} * where the contents don't matter. *

*

* One use case would be for testing the handling of * large {@link Reader} as it can emulate that * scenario without the overhead of actually processing * large numbers of characters - significantly speeding up * test execution times. *

*

* This implementation returns a space from the method that * reads a character and leaves the array unchanged in the read * methods that are passed a character array. * If alternative data is required the {@code processChar()} and * {@code processChars()} methods can be implemented to generate * data, for example: *

* *
 *  public class TestReader extends NullReader {
 *      public TestReader(int size) {
 *          super(size);
 *      }
 *      protected char processChar() {
 *          return ... // return required value here
 *      }
 *      protected void processChars(char[] chars, int offset, int length) {
 *          for (int i = offset; i < length; i++) {
 *              chars[i] = ... // set array value here
 *          }
 *      }
 *  }
 * 
* * @since 1.3 */ public class NullReader extends Reader { private final long size; private long position; private long mark = -1; private long readlimit; private boolean eof; private final boolean throwEofException; private final boolean markSupported; /** * Creates a {@link Reader} that emulates a size 0 reader * which supports marking and does not throw EOFException. * * @since 2.7 */ public NullReader() { this(0, true, false); } /** * Creates a {@link Reader} that emulates a specified size * which supports marking and does not throw EOFException. * * @param size The size of the reader to emulate. */ public NullReader(final long size) { this(size, true, false); } /** * Creates a {@link Reader} that emulates a specified * size with option settings. * * @param size The size of the reader to emulate. * @param markSupported Whether this instance will support * the {@code mark()} functionality. * @param throwEofException Whether this implementation * will throw an {@link EOFException} or return -1 when the * end of file is reached. */ public NullReader(final long size, final boolean markSupported, final boolean throwEofException) { this.size = size; this.markSupported = markSupported; this.throwEofException = throwEofException; } /** * Returns the current position. * * @return the current position. */ public long getPosition() { return position; } /** * Returns the size this {@link Reader} emulates. * * @return The size of the reader to emulate. */ public long getSize() { return size; } /** * Closes this Reader - resets the internal state to * the initial values. * * @throws IOException If an error occurs. */ @Override public void close() throws IOException { eof = false; position = 0; mark = -1; } /** * Marks the current position. * * @param readlimit The number of characters before this marked position * is invalid. * @throws UnsupportedOperationException if mark is not supported. */ @Override public synchronized void mark(final int readlimit) { if (!markSupported) { throw UnsupportedOperationExceptions.mark(); } mark = position; this.readlimit = readlimit; } /** * Indicates whether mark is supported. * * @return Whether mark is supported or not. */ @Override public boolean markSupported() { return markSupported; } /** * Reads a character. * * @return Either The character value returned by {@code processChar()} * or {@code -1} if the end of file has been reached and * {@code throwEofException} is set to {@code false}. * @throws EOFException if the end of file is reached and * {@code throwEofException} is set to {@code true}. * @throws IOException if trying to read past the end of file. */ @Override public int read() throws IOException { if (eof) { throw new IOException("Read after end of file"); } if (position == size) { return doEndOfFile(); } position++; return processChar(); } /** * Reads some characters into the specified array. * * @param chars The character array to read into * @return The number of characters read or {@code -1} * if the end of file has been reached and * {@code throwEofException} is set to {@code false}. * @throws EOFException if the end of file is reached and * {@code throwEofException} is set to {@code true}. * @throws IOException if trying to read past the end of file. */ @Override public int read(final char[] chars) throws IOException { return read(chars, 0, chars.length); } /** * Reads the specified number characters into an array. * * @param chars The character array to read into. * @param offset The offset to start reading characters into. * @param length The number of characters to read. * @return The number of characters read or {@code -1} * if the end of file has been reached and * {@code throwEofException} is set to {@code false}. * @throws EOFException if the end of file is reached and * {@code throwEofException} is set to {@code true}. * @throws IOException if trying to read past the end of file. */ @Override public int read(final char[] chars, final int offset, final int length) throws IOException { if (eof) { throw new IOException("Read after end of file"); } if (position == size) { return doEndOfFile(); } position += length; int returnLength = length; if (position > size) { returnLength = length - (int)(position - size); position = size; } processChars(chars, offset, returnLength); return returnLength; } /** * Resets the stream to the point when mark was last called. * * @throws UnsupportedOperationException if mark is not supported. * @throws IOException If no position has been marked * or the read limit has been exceed since the last position was * marked. */ @Override public synchronized void reset() throws IOException { if (!markSupported) { throw UnsupportedOperationExceptions.reset(); } if (mark < 0) { throw new IOException("No position has been marked"); } if (position > mark + readlimit) { throw new IOException("Marked position [" + mark + "] is no longer valid - passed the read limit [" + readlimit + "]"); } position = mark; eof = false; } /** * Skips a specified number of characters. * * @param numberOfChars The number of characters to skip. * @return The number of characters skipped or {@code -1} * if the end of file has been reached and * {@code throwEofException} is set to {@code false}. * @throws EOFException if the end of file is reached and * {@code throwEofException} is set to {@code true}. * @throws IOException if trying to read past the end of file. */ @Override public long skip(final long numberOfChars) throws IOException { if (eof) { throw new IOException("Skip after end of file"); } if (position == size) { return doEndOfFile(); } position += numberOfChars; long returnLength = numberOfChars; if (position > size) { returnLength = numberOfChars - (position - size); position = size; } return returnLength; } /** * Returns a character value for the {@code read()} method. *

* This implementation returns zero. *

* * @return This implementation always returns zero. */ protected int processChar() { // do nothing - overridable by subclass return 0; } /** * Process the characters for the {@code read(char[], offset, length)} * method. *

* This implementation leaves the character array unchanged. *

* * @param chars The character array * @param offset The offset to start at. * @param length The number of characters. */ protected void processChars(final char[] chars, final int offset, final int length) { // do nothing - overridable by subclass } /** * Handles End of File. * * @return {@code -1} if {@code throwEofException} is * set to {@code false} * @throws EOFException if {@code throwEofException} is set * to {@code true}. */ private int doEndOfFile() throws EOFException { eof = true; if (throwEofException) { throw new EOFException(); } return EOF; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/ObservableInputStream.java0100644 0000000 0000000 00000024760 13612062727 032026 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.apache.commons.io.IOUtils.EOF; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.apache.commons.io.IOUtils; /** * The {@link ObservableInputStream} allows, that an InputStream may be consumed by other receivers, apart from the * thread, which is reading it. The other consumers are implemented as instances of {@link Observer}. *

* A typical application may be the generation of a {@link java.security.MessageDigest} on the fly. *

*

* Note: The {@link ObservableInputStream} is not thread safe, as instances of InputStream usually * aren't. If you must access the stream from multiple threads, then synchronization, locking, or a similar means must * be used. *

* * @see MessageDigestCalculatingInputStream */ public class ObservableInputStream extends ProxyInputStream { /** * Abstracts observer callback for {@code ObservableInputStream}s. */ public static abstract class Observer { /** * Called to indicate that the {@link ObservableInputStream} has been closed. * * @throws IOException if an I/O error occurs. */ @SuppressWarnings("unused") // Possibly thrown from subclasses. public void closed() throws IOException { // noop } /** * Called to indicate that {@link InputStream#read(byte[])}, or {@link InputStream#read(byte[], int, int)} have * been called, and are about to invoke data. * * @param buffer The byte array, which has been passed to the read call, and where data has been stored. * @param offset The offset within the byte array, where data has been stored. * @param length The number of bytes, which have been stored in the byte array. * @throws IOException if an I/O error occurs. */ @SuppressWarnings("unused") // Possibly thrown from subclasses. public void data(final byte[] buffer, final int offset, final int length) throws IOException { // noop } /** * Called to indicate, that {@link InputStream#read()} has been invoked on the {@link ObservableInputStream}, * and will return a value. * * @param value The value, which is being returned. This will never be -1 (EOF), because, in that case, * {@link #finished()} will be invoked instead. * @throws IOException if an I/O error occurs. */ @SuppressWarnings("unused") // Possibly thrown from subclasses. public void data(final int value) throws IOException { // noop } /** * Called to indicate that an error occurred on the underlying stream. * * @param exception the exception to throw * @throws IOException if an I/O error occurs. */ public void error(final IOException exception) throws IOException { throw exception; } /** * Called to indicate that EOF has been seen on the underlying stream. This method may be called multiple times, * if the reader keeps invoking either of the read methods, and they will consequently keep returning EOF. * * @throws IOException if an I/O error occurs. */ @SuppressWarnings("unused") // Possibly thrown from subclasses. public void finished() throws IOException { // noop } } private final List observers; /** * Creates a new ObservableInputStream for the given InputStream. * * @param inputStream the input stream to observe. */ public ObservableInputStream(final InputStream inputStream) { this(inputStream, new ArrayList<>()); } /** * Creates a new ObservableInputStream for the given InputStream. * * @param inputStream the input stream to observe. * @param observers List of observer callbacks. */ private ObservableInputStream(final InputStream inputStream, final List observers) { super(inputStream); this.observers = observers; } /** * Creates a new ObservableInputStream for the given InputStream. * * @param inputStream the input stream to observe. * @param observers List of observer callbacks. * @since 2.9.0 */ public ObservableInputStream(final InputStream inputStream, final Observer... observers) { this(inputStream, Arrays.asList(observers)); } /** * Adds an Observer. * * @param observer the observer to add. */ public void add(final Observer observer) { observers.add(observer); } @Override public void close() throws IOException { IOException ioe = null; try { super.close(); } catch (final IOException e) { ioe = e; } if (ioe == null) { noteClosed(); } else { noteError(ioe); } } /** * Reads all data from the underlying {@link InputStream}, while notifying the observers. * * @throws IOException The underlying {@link InputStream}, or either of the observers has thrown an exception. */ public void consume() throws IOException { final byte[] buffer = IOUtils.byteArray(); while (read(buffer) != EOF) { // empty } } /** * Gets all currently registered observers. * * @return a list of the currently registered observers. * @since 2.9.0 */ public List getObservers() { return observers; } /** * Notifies the observers by invoking {@link Observer#finished()}. * * @throws IOException Some observer has thrown an exception, which is being passed down. */ protected void noteClosed() throws IOException { for (final Observer observer : getObservers()) { observer.closed(); } } /** * Notifies the observers by invoking {@link Observer#data(int)} with the given arguments. * * @param value Passed to the observers. * @throws IOException Some observer has thrown an exception, which is being passed down. */ protected void noteDataByte(final int value) throws IOException { for (final Observer observer : getObservers()) { observer.data(value); } } /** * Notifies the observers by invoking {@link Observer#data(byte[],int,int)} with the given arguments. * * @param buffer Passed to the observers. * @param offset Passed to the observers. * @param length Passed to the observers. * @throws IOException Some observer has thrown an exception, which is being passed down. */ protected void noteDataBytes(final byte[] buffer, final int offset, final int length) throws IOException { for (final Observer observer : getObservers()) { observer.data(buffer, offset, length); } } /** * Notifies the observers by invoking {@link Observer#error(IOException)} with the given argument. * * @param exception Passed to the observers. * @throws IOException Some observer has thrown an exception, which is being passed down. This may be the same * exception, which has been passed as an argument. */ protected void noteError(final IOException exception) throws IOException { for (final Observer observer : getObservers()) { observer.error(exception); } } /** * Notifies the observers by invoking {@link Observer#finished()}. * * @throws IOException Some observer has thrown an exception, which is being passed down. */ protected void noteFinished() throws IOException { for (final Observer observer : getObservers()) { observer.finished(); } } private void notify(final byte[] buffer, final int offset, final int result, final IOException ioe) throws IOException { if (ioe != null) { noteError(ioe); throw ioe; } if (result == EOF) { noteFinished(); } else if (result > 0) { noteDataBytes(buffer, offset, result); } } @Override public int read() throws IOException { int result = 0; IOException ioe = null; try { result = super.read(); } catch (final IOException ex) { ioe = ex; } if (ioe != null) { noteError(ioe); throw ioe; } if (result == EOF) { noteFinished(); } else { noteDataByte(result); } return result; } @Override public int read(final byte[] buffer) throws IOException { int result = 0; IOException ioe = null; try { result = super.read(buffer); } catch (final IOException ex) { ioe = ex; } notify(buffer, 0, result, ioe); return result; } @Override public int read(final byte[] buffer, final int offset, final int length) throws IOException { int result = 0; IOException ioe = null; try { result = super.read(buffer, offset, length); } catch (final IOException ex) { ioe = ex; } notify(buffer, offset, result, ioe); return result; } /** * Removes an Observer. * * @param observer the observer to remove */ public void remove(final Observer observer) { observers.remove(observer); } /** * Removes all Observers. */ public void removeAllObservers() { observers.clear(); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/ProxyInputStream.java0100644 0000000 0000000 00000017307 13612062727 031062 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.apache.commons.io.IOUtils.EOF; import java.io.FilterInputStream; import java.io.IOException; import java.io.InputStream; import org.apache.commons.io.IOUtils; /** * A Proxy stream which acts as expected, that is it passes the method * calls on to the proxied stream and doesn't change which methods are * being called. *

* It is an alternative base class to FilterInputStream * to increase reusability, because FilterInputStream changes the * methods being called, such as read(byte[]) to read(byte[], int, int). *

*

* See the protected methods for ways in which a subclass can easily decorate * a stream with custom pre-, post- or error processing functionality. *

*/ public abstract class ProxyInputStream extends FilterInputStream { /** * Constructs a new ProxyInputStream. * * @param proxy the InputStream to delegate to */ public ProxyInputStream(final InputStream proxy) { super(proxy); // the proxy is stored in a protected superclass variable named 'in' } /** * Invokes the delegate's {@code read()} method. * @return the byte read or -1 if the end of stream * @throws IOException if an I/O error occurs. */ @Override public int read() throws IOException { try { beforeRead(1); final int b = in.read(); afterRead(b != EOF ? 1 : EOF); return b; } catch (final IOException e) { handleIOException(e); return EOF; } } /** * Invokes the delegate's {@code read(byte[])} method. * @param bts the buffer to read the bytes into * @return the number of bytes read or EOF if the end of stream * @throws IOException if an I/O error occurs. */ @Override public int read(final byte[] bts) throws IOException { try { beforeRead(IOUtils.length(bts)); final int n = in.read(bts); afterRead(n); return n; } catch (final IOException e) { handleIOException(e); return EOF; } } /** * Invokes the delegate's {@code read(byte[], int, int)} method. * @param bts the buffer to read the bytes into * @param off The start offset * @param len The number of bytes to read * @return the number of bytes read or -1 if the end of stream * @throws IOException if an I/O error occurs. */ @Override public int read(final byte[] bts, final int off, final int len) throws IOException { try { beforeRead(len); final int n = in.read(bts, off, len); afterRead(n); return n; } catch (final IOException e) { handleIOException(e); return EOF; } } /** * Invokes the delegate's {@code skip(long)} method. * @param ln the number of bytes to skip * @return the actual number of bytes skipped * @throws IOException if an I/O error occurs. */ @Override public long skip(final long ln) throws IOException { try { return in.skip(ln); } catch (final IOException e) { handleIOException(e); return 0; } } /** * Invokes the delegate's {@code available()} method. * @return the number of available bytes * @throws IOException if an I/O error occurs. */ @Override public int available() throws IOException { try { return super.available(); } catch (final IOException e) { handleIOException(e); return 0; } } /** * Invokes the delegate's {@code close()} method. * @throws IOException if an I/O error occurs. */ @Override public void close() throws IOException { IOUtils.close(in, this::handleIOException); } /** * Invokes the delegate's {@code mark(int)} method. * @param readlimit read ahead limit */ @Override public synchronized void mark(final int readlimit) { in.mark(readlimit); } /** * Invokes the delegate's {@code reset()} method. * @throws IOException if an I/O error occurs. */ @Override public synchronized void reset() throws IOException { try { in.reset(); } catch (final IOException e) { handleIOException(e); } } /** * Invokes the delegate's {@code markSupported()} method. * @return true if mark is supported, otherwise false */ @Override public boolean markSupported() { return in.markSupported(); } /** * Invoked by the read methods before the call is proxied. The number * of bytes that the caller wanted to read (1 for the {@link #read()} * method, buffer length for {@link #read(byte[])}, etc.) is given as * an argument. *

* Subclasses can override this method to add common pre-processing * functionality without having to override all the read methods. * The default implementation does nothing. *

* Note this method is not called from {@link #skip(long)} or * {@link #reset()}. You need to explicitly override those methods if * you want to add pre-processing steps also to them. * * @since 2.0 * @param n number of bytes that the caller asked to be read * @throws IOException if the pre-processing fails */ @SuppressWarnings("unused") // Possibly thrown from subclasses. protected void beforeRead(final int n) throws IOException { // no-op } /** * Invoked by the read methods after the proxied call has returned * successfully. The number of bytes returned to the caller (or -1 if * the end of stream was reached) is given as an argument. *

* Subclasses can override this method to add common post-processing * functionality without having to override all the read methods. * The default implementation does nothing. *

* Note this method is not called from {@link #skip(long)} or * {@link #reset()}. You need to explicitly override those methods if * you want to add post-processing steps also to them. * * @since 2.0 * @param n number of bytes read, or -1 if the end of stream was reached * @throws IOException if the post-processing fails */ @SuppressWarnings("unused") // Possibly thrown from subclasses. protected void afterRead(final int n) throws IOException { // no-op } /** * Handle any IOExceptions thrown. *

* This method provides a point to implement custom exception * handling. The default behavior is to re-throw the exception. * @param e The IOException thrown * @throws IOException if an I/O error occurs. * @since 2.0 */ protected void handleIOException(final IOException e) throws IOException { throw e; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/ProxyReader.java0100644 0000000 0000000 00000020623 13612062727 030004 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.apache.commons.io.IOUtils.EOF; import java.io.FilterReader; import java.io.IOException; import java.io.Reader; import java.nio.CharBuffer; import org.apache.commons.io.IOUtils; /** * A Proxy stream which acts as expected, that is it passes the method * calls on to the proxied stream and doesn't change which methods are * being called. *

* It is an alternative base class to FilterReader * to increase reusability, because FilterReader changes the * methods being called, such as read(char[]) to read(char[], int, int). *

*/ public abstract class ProxyReader extends FilterReader { /** * Constructs a new ProxyReader. * * @param proxy the Reader to delegate to */ public ProxyReader(final Reader proxy) { super(proxy); // the proxy is stored in a protected superclass variable named 'in' } /** * Invokes the delegate's {@code read()} method. * @return the character read or -1 if the end of stream * @throws IOException if an I/O error occurs. */ @Override public int read() throws IOException { try { beforeRead(1); final int c = in.read(); afterRead(c != EOF ? 1 : EOF); return c; } catch (final IOException e) { handleIOException(e); return EOF; } } /** * Invokes the delegate's {@code read(char[])} method. * @param chr the buffer to read the characters into * @return the number of characters read or -1 if the end of stream * @throws IOException if an I/O error occurs. */ @Override public int read(final char[] chr) throws IOException { try { beforeRead(IOUtils.length(chr)); final int n = in.read(chr); afterRead(n); return n; } catch (final IOException e) { handleIOException(e); return EOF; } } /** * Invokes the delegate's {@code read(char[], int, int)} method. * @param chr the buffer to read the characters into * @param st The start offset * @param len The number of bytes to read * @return the number of characters read or -1 if the end of stream * @throws IOException if an I/O error occurs. */ @Override public int read(final char[] chr, final int st, final int len) throws IOException { try { beforeRead(len); final int n = in.read(chr, st, len); afterRead(n); return n; } catch (final IOException e) { handleIOException(e); return EOF; } } /** * Invokes the delegate's {@code read(CharBuffer)} method. * @param target the char buffer to read the characters into * @return the number of characters read or -1 if the end of stream * @throws IOException if an I/O error occurs. * @since 2.0 */ @Override public int read(final CharBuffer target) throws IOException { try { beforeRead(IOUtils.length(target)); final int n = in.read(target); afterRead(n); return n; } catch (final IOException e) { handleIOException(e); return EOF; } } /** * Invokes the delegate's {@code skip(long)} method. * @param ln the number of bytes to skip * @return the number of bytes to skipped or EOF if the end of stream * @throws IOException if an I/O error occurs. */ @Override public long skip(final long ln) throws IOException { try { return in.skip(ln); } catch (final IOException e) { handleIOException(e); return 0; } } /** * Invokes the delegate's {@code ready()} method. * @return true if the stream is ready to be read * @throws IOException if an I/O error occurs. */ @Override public boolean ready() throws IOException { try { return in.ready(); } catch (final IOException e) { handleIOException(e); return false; } } /** * Invokes the delegate's {@code close()} method. * @throws IOException if an I/O error occurs. */ @Override public void close() throws IOException { try { in.close(); } catch (final IOException e) { handleIOException(e); } } /** * Invokes the delegate's {@code mark(int)} method. * @param idx read ahead limit * @throws IOException if an I/O error occurs. */ @Override public synchronized void mark(final int idx) throws IOException { try { in.mark(idx); } catch (final IOException e) { handleIOException(e); } } /** * Invokes the delegate's {@code reset()} method. * @throws IOException if an I/O error occurs. */ @Override public synchronized void reset() throws IOException { try { in.reset(); } catch (final IOException e) { handleIOException(e); } } /** * Invokes the delegate's {@code markSupported()} method. * @return true if mark is supported, otherwise false */ @Override public boolean markSupported() { return in.markSupported(); } /** * Invoked by the read methods before the call is proxied. The number * of chars that the caller wanted to read (1 for the {@link #read()} * method, buffer length for {@link #read(char[])}, etc.) is given as * an argument. *

* Subclasses can override this method to add common pre-processing * functionality without having to override all the read methods. * The default implementation does nothing. *

* Note this method is not called from {@link #skip(long)} or * {@link #reset()}. You need to explicitly override those methods if * you want to add pre-processing steps also to them. * * @since 2.0 * @param n number of chars that the caller asked to be read * @throws IOException if the pre-processing fails */ @SuppressWarnings("unused") // Possibly thrown from subclasses. protected void beforeRead(final int n) throws IOException { // noop } /** * Invoked by the read methods after the proxied call has returned * successfully. The number of chars returned to the caller (or -1 if * the end of stream was reached) is given as an argument. *

* Subclasses can override this method to add common post-processing * functionality without having to override all the read methods. * The default implementation does nothing. *

* Note this method is not called from {@link #skip(long)} or * {@link #reset()}. You need to explicitly override those methods if * you want to add post-processing steps also to them. * * @since 2.0 * @param n number of chars read, or -1 if the end of stream was reached * @throws IOException if the post-processing fails */ @SuppressWarnings("unused") // Possibly thrown from subclasses. protected void afterRead(final int n) throws IOException { // noop } /** * Handle any IOExceptions thrown. *

* This method provides a point to implement custom exception * handling. The default behavior is to re-throw the exception. * @param e The IOException thrown * @throws IOException if an I/O error occurs. * @since 2.0 */ protected void handleIOException(final IOException e) throws IOException { throw e; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/QueueInputStream.java0100644 0000000 0000000 00000006423 13612062727 031022 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.apache.commons.io.IOUtils.EOF; import org.apache.commons.io.output.QueueOutputStream; import java.io.InputStream; import java.io.PipedInputStream; import java.io.PipedOutputStream; import java.util.Objects; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; /** * Simple alternative to JDK {@link java.io.PipedInputStream}; queue input stream provides what's written in queue * output stream. * *

* Example usage: *

*
 * QueueInputStream inputStream = new QueueInputStream();
 * QueueOutputStream outputStream = inputStream.newQueueOutputStream();
 *
 * outputStream.write("hello world".getBytes(UTF_8));
 * inputStream.read();
 * 
*

* Unlike JDK {@link PipedInputStream} and {@link PipedOutputStream}, queue input/output streams may be used safely in a * single thread or multiple threads. Also, unlike JDK classes, no special meaning is attached to initial or current * thread. Instances can be used longer after initial threads exited. *

*

* Closing a {@code QueueInputStream} has no effect. The methods in this class can be called after the stream has been * closed without generating an {@code IOException}. *

* * @see QueueOutputStream * @since 2.9.0 */ public class QueueInputStream extends InputStream { private final BlockingQueue blockingQueue; /** * Constructs a new instance with no limit to its internal buffer size. */ public QueueInputStream() { this(new LinkedBlockingQueue<>()); } /** * Constructs a new instance with given buffer * * @param blockingQueue backing queue for the stream */ public QueueInputStream(final BlockingQueue blockingQueue) { this.blockingQueue = Objects.requireNonNull(blockingQueue, "blockingQueue"); } /** * Creates a new QueueOutputStream instance connected to this. Writes to the output stream will be visible to this * input stream. * * @return QueueOutputStream connected to this stream */ public QueueOutputStream newQueueOutputStream() { return new QueueOutputStream(blockingQueue); } /** * Reads and returns a single byte. * * @return either the byte read or {@code -1} if the end of the stream has been reached */ @Override public int read() { final Integer value = blockingQueue.poll(); return value == null ? EOF : ((0xFF) & value); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/RandomAccessFileInputStream.java0100644 0000000 0000000 00000011337 13612062727 033100 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import java.io.IOException; import java.io.InputStream; import java.io.RandomAccessFile; import java.util.Objects; /** * Streams data from a {@link RandomAccessFile} starting at its current position. * * @since 2.8.0 */ public class RandomAccessFileInputStream extends InputStream { private final boolean closeOnClose; private final RandomAccessFile randomAccessFile; /** * Constructs a new instance configured to leave the underlying file open when this stream is closed. * * @param file The file to stream. */ public RandomAccessFileInputStream(final RandomAccessFile file) { this(file, false); } /** * Constructs a new instance. * * @param file The file to stream. * @param closeOnClose Whether to close the underlying file when this stream is closed. */ public RandomAccessFileInputStream(final RandomAccessFile file, final boolean closeOnClose) { this.randomAccessFile = Objects.requireNonNull(file, "file"); this.closeOnClose = closeOnClose; } /** * Returns an estimate of the number of bytes that can be read (or skipped over) from this input stream. * * If there are more than {@link Integer#MAX_VALUE} bytes available, return {@link Integer#MAX_VALUE}. * * @return An estimate of the number of bytes that can be read. * @throws IOException If an I/O error occurs. */ @Override public int available() throws IOException { final long avail = availableLong(); if (avail > Integer.MAX_VALUE) { return Integer.MAX_VALUE; } return (int) avail; } /** * Returns the number of bytes that can be read (or skipped over) from this input stream. * * @return The number of bytes that can be read. * @throws IOException If an I/O error occurs. */ public long availableLong() throws IOException { return randomAccessFile.length() - randomAccessFile.getFilePointer(); } @Override public void close() throws IOException { super.close(); if (closeOnClose) { randomAccessFile.close(); } } /** * Gets the underlying file. * * @return the underlying file. */ public RandomAccessFile getRandomAccessFile() { return randomAccessFile; } /** * Returns whether to close the underlying file when this stream is closed. * * @return Whether to close the underlying file when this stream is closed. */ public boolean isCloseOnClose() { return closeOnClose; } @Override public int read() throws IOException { return randomAccessFile.read(); } @Override public int read(final byte[] bytes) throws IOException { return randomAccessFile.read(bytes); } @Override public int read(final byte[] bytes, final int offset, final int length) throws IOException { return randomAccessFile.read(bytes, offset, length); } /** * Delegates to the underlying file. * * @param position See {@link RandomAccessFile#seek(long)}. * @throws IOException See {@link RandomAccessFile#seek(long)}. * @see RandomAccessFile#seek(long) */ private void seek(final long position) throws IOException { randomAccessFile.seek(position); } @Override public long skip(final long skipCount) throws IOException { if (skipCount <= 0) { return 0; } final long filePointer = randomAccessFile.getFilePointer(); final long fileLength = randomAccessFile.length(); if (filePointer >= fileLength) { return 0; } final long targetPos = filePointer + skipCount; final long newPos = targetPos > fileLength ? fileLength - 1 : targetPos; if (newPos > 0) { seek(newPos); } return randomAccessFile.getFilePointer() - filePointer; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/ReadAheadInputStream.java0100644 0000000 0000000 00000041142 13612062727 031531 0ustar00rootroot0000000 0000000 /* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.apache.commons.io.IOUtils.EOF; // import javax.annotation.concurrent.GuardedBy; import java.io.EOFException; import java.io.IOException; import java.io.InputStream; import java.io.InterruptedIOException; import java.nio.ByteBuffer; import java.util.Objects; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; /** * Implements {@link InputStream} to asynchronously read ahead from an underlying input stream when a specified amount * of data has been read from the current buffer. It does so by maintaining two buffers: an active buffer and a read * ahead buffer. The active buffer contains data which should be returned when a read() call is issued. The read ahead * buffer is used to asynchronously read from the underlying input stream. When the current active buffer is exhausted, * we flip the two buffers so that we can start reading from the read ahead buffer without being blocked by disk I/O. *

* This class was ported and adapted from Apache Spark commit 933dc6cb7b3de1d8ccaf73d124d6eb95b947ed19. *

* * @since 2.9.0 */ public class ReadAheadInputStream extends InputStream { private static final ThreadLocal oneByte = ThreadLocal.withInitial(() -> new byte[1]); /** * Creates a new daemon executor service. * * @return a new daemon executor service. */ private static ExecutorService newExecutorService() { return Executors.newSingleThreadExecutor(ReadAheadInputStream::newThread); } /** * Creates a new daemon thread. * * @param r the thread's runnable. * @return a new daemon thread. */ private static Thread newThread(final Runnable r) { final Thread thread = new Thread(r, "commons-io-read-ahead"); thread.setDaemon(true); return thread; } private final ReentrantLock stateChangeLock = new ReentrantLock(); // @GuardedBy("stateChangeLock") private ByteBuffer activeBuffer; // @GuardedBy("stateChangeLock") private ByteBuffer readAheadBuffer; // @GuardedBy("stateChangeLock") private boolean endOfStream; // @GuardedBy("stateChangeLock") // true if async read is in progress private boolean readInProgress; // @GuardedBy("stateChangeLock") // true if read is aborted due to an exception in reading from underlying input stream. private boolean readAborted; // @GuardedBy("stateChangeLock") private Throwable readException; // @GuardedBy("stateChangeLock") // whether the close method is called. private boolean isClosed; // @GuardedBy("stateChangeLock") // true when the close method will close the underlying input stream. This is valid only if // `isClosed` is true. private boolean isUnderlyingInputStreamBeingClosed; // @GuardedBy("stateChangeLock") // whether there is a read ahead task running, private boolean isReading; // Whether there is a reader waiting for data. private final AtomicBoolean isWaiting = new AtomicBoolean(false); private final InputStream underlyingInputStream; private final ExecutorService executorService; private final boolean shutdownExecutorService; private final Condition asyncReadComplete = stateChangeLock.newCondition(); /** * Creates an instance with the specified buffer size and read-ahead threshold * * @param inputStream The underlying input stream. * @param bufferSizeInBytes The buffer size. */ public ReadAheadInputStream(final InputStream inputStream, final int bufferSizeInBytes) { this(inputStream, bufferSizeInBytes, newExecutorService(), true); } /** * Creates an instance with the specified buffer size and read-ahead threshold * * @param inputStream The underlying input stream. * @param bufferSizeInBytes The buffer size. * @param executorService An executor service for the read-ahead thread. */ public ReadAheadInputStream(final InputStream inputStream, final int bufferSizeInBytes, final ExecutorService executorService) { this(inputStream, bufferSizeInBytes, executorService, false); } /** * Creates an instance with the specified buffer size and read-ahead threshold * * @param inputStream The underlying input stream. * @param bufferSizeInBytes The buffer size. * @param executorService An executor service for the read-ahead thread. * @param shutdownExecutorService Whether or not to shutdown the given ExecutorService on close. */ private ReadAheadInputStream(final InputStream inputStream, final int bufferSizeInBytes, final ExecutorService executorService, final boolean shutdownExecutorService) { if (bufferSizeInBytes <= 0) { throw new IllegalArgumentException( "bufferSizeInBytes should be greater than 0, but the value is " + bufferSizeInBytes); } this.executorService = Objects.requireNonNull(executorService, "executorService"); this.underlyingInputStream = Objects.requireNonNull(inputStream, "inputStream"); this.shutdownExecutorService = shutdownExecutorService; this.activeBuffer = ByteBuffer.allocate(bufferSizeInBytes); this.readAheadBuffer = ByteBuffer.allocate(bufferSizeInBytes); this.activeBuffer.flip(); this.readAheadBuffer.flip(); } @Override public int available() throws IOException { stateChangeLock.lock(); // Make sure we have no integer overflow. try { return (int) Math.min(Integer.MAX_VALUE, (long) activeBuffer.remaining() + readAheadBuffer.remaining()); } finally { stateChangeLock.unlock(); } } private void checkReadException() throws IOException { if (readAborted) { if (readException instanceof IOException) { throw (IOException) readException; } throw new IOException(readException); } } @Override public void close() throws IOException { boolean isSafeToCloseUnderlyingInputStream = false; stateChangeLock.lock(); try { if (isClosed) { return; } isClosed = true; if (!isReading) { // Nobody is reading, so we can close the underlying input stream in this method. isSafeToCloseUnderlyingInputStream = true; // Flip this to make sure the read ahead task will not close the underlying input stream. isUnderlyingInputStreamBeingClosed = true; } } finally { stateChangeLock.unlock(); } if (shutdownExecutorService) { try { executorService.shutdownNow(); executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS); } catch (final InterruptedException e) { final InterruptedIOException iio = new InterruptedIOException(e.getMessage()); iio.initCause(e); throw iio; } finally { if (isSafeToCloseUnderlyingInputStream) { underlyingInputStream.close(); } } } } private void closeUnderlyingInputStreamIfNecessary() { boolean needToCloseUnderlyingInputStream = false; stateChangeLock.lock(); try { isReading = false; if (isClosed && !isUnderlyingInputStreamBeingClosed) { // close method cannot close underlyingInputStream because we were reading. needToCloseUnderlyingInputStream = true; } } finally { stateChangeLock.unlock(); } if (needToCloseUnderlyingInputStream) { try { underlyingInputStream.close(); } catch (final IOException e) { // TODO ? } } } private boolean isEndOfStream() { return !activeBuffer.hasRemaining() && !readAheadBuffer.hasRemaining() && endOfStream; } @Override public int read() throws IOException { if (activeBuffer.hasRemaining()) { // short path - just get one byte. return activeBuffer.get() & 0xFF; } final byte[] oneByteArray = oneByte.get(); return read(oneByteArray, 0, 1) == EOF ? -1 : oneByteArray[0] & 0xFF; } @Override public int read(final byte[] b, final int offset, int len) throws IOException { if (offset < 0 || len < 0 || len > b.length - offset) { throw new IndexOutOfBoundsException(); } if (len == 0) { return 0; } if (!activeBuffer.hasRemaining()) { // No remaining in active buffer - lock and switch to write ahead buffer. stateChangeLock.lock(); try { waitForAsyncReadComplete(); if (!readAheadBuffer.hasRemaining()) { // The first read. readAsync(); waitForAsyncReadComplete(); if (isEndOfStream()) { return EOF; } } // Swap the newly read read ahead buffer in place of empty active buffer. swapBuffers(); // After swapping buffers, trigger another async read for read ahead buffer. readAsync(); } finally { stateChangeLock.unlock(); } } len = Math.min(len, activeBuffer.remaining()); activeBuffer.get(b, offset, len); return len; } /** Read data from underlyingInputStream to readAheadBuffer asynchronously. */ private void readAsync() throws IOException { stateChangeLock.lock(); final byte[] arr; try { arr = readAheadBuffer.array(); if (endOfStream || readInProgress) { return; } checkReadException(); readAheadBuffer.position(0); readAheadBuffer.flip(); readInProgress = true; } finally { stateChangeLock.unlock(); } executorService.execute(() -> { stateChangeLock.lock(); try { if (isClosed) { readInProgress = false; return; } // Flip this so that the close method will not close the underlying input stream when we // are reading. isReading = true; } finally { stateChangeLock.unlock(); } // Please note that it is safe to release the lock and read into the read ahead buffer // because either of following two conditions will hold: // // 1. The active buffer has data available to read so the reader will not read from the read ahead buffer. // // 2. This is the first time read is called or the active buffer is exhausted, in that case the reader waits // for this async read to complete. // // So there is no race condition in both the situations. int read = 0; int off = 0, len = arr.length; Throwable exception = null; try { // try to fill the read ahead buffer. // if a reader is waiting, possibly return early. do { read = underlyingInputStream.read(arr, off, len); if (read <= 0) { break; } off += read; len -= read; } while (len > 0 && !isWaiting.get()); } catch (final Throwable ex) { exception = ex; if (ex instanceof Error) { // `readException` may not be reported to the user. Rethrow Error to make sure at least // The user can see Error in UncaughtExceptionHandler. throw (Error) ex; } } finally { stateChangeLock.lock(); try { readAheadBuffer.limit(off); if (read < 0 || (exception instanceof EOFException)) { endOfStream = true; } else if (exception != null) { readAborted = true; readException = exception; } readInProgress = false; signalAsyncReadComplete(); } finally { stateChangeLock.unlock(); } closeUnderlyingInputStreamIfNecessary(); } }); } private void signalAsyncReadComplete() { stateChangeLock.lock(); try { asyncReadComplete.signalAll(); } finally { stateChangeLock.unlock(); } } @Override public long skip(final long n) throws IOException { if (n <= 0L) { return 0L; } if (n <= activeBuffer.remaining()) { // Only skipping from active buffer is sufficient activeBuffer.position((int) n + activeBuffer.position()); return n; } stateChangeLock.lock(); long skipped; try { skipped = skipInternal(n); } finally { stateChangeLock.unlock(); } return skipped; } /** * Internal skip function which should be called only from skip(). The assumption is that the stateChangeLock is * already acquired in the caller before calling this function. * * @param n the number of bytes to be skipped. * @return the actual number of bytes skipped. */ private long skipInternal(final long n) throws IOException { assert stateChangeLock.isLocked(); waitForAsyncReadComplete(); if (isEndOfStream()) { return 0; } if (available() >= n) { // we can skip from the internal buffers int toSkip = (int) n; // We need to skip from both active buffer and read ahead buffer toSkip -= activeBuffer.remaining(); assert toSkip > 0; // skipping from activeBuffer already handled. activeBuffer.position(0); activeBuffer.flip(); readAheadBuffer.position(toSkip + readAheadBuffer.position()); swapBuffers(); // Trigger async read to emptied read ahead buffer. readAsync(); return n; } final int skippedBytes = available(); final long toSkip = n - skippedBytes; activeBuffer.position(0); activeBuffer.flip(); readAheadBuffer.position(0); readAheadBuffer.flip(); final long skippedFromInputStream = underlyingInputStream.skip(toSkip); readAsync(); return skippedBytes + skippedFromInputStream; } /** * Flips the active and read ahead buffer */ private void swapBuffers() { final ByteBuffer temp = activeBuffer; activeBuffer = readAheadBuffer; readAheadBuffer = temp; } private void waitForAsyncReadComplete() throws IOException { stateChangeLock.lock(); try { isWaiting.set(true); // There is only one reader, and one writer, so the writer should signal only once, // but a while loop checking the wake up condition is still needed to avoid spurious wakeups. while (readInProgress) { asyncReadComplete.await(); } } catch (final InterruptedException e) { final InterruptedIOException iio = new InterruptedIOException(e.getMessage()); iio.initCause(e); throw iio; } finally { isWaiting.set(false); stateChangeLock.unlock(); } checkReadException(); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/ReaderInputStream.java0100644 0000000 0000000 00000026533 13612062727 031144 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.apache.commons.io.IOUtils.EOF; import java.io.IOException; import java.io.InputStream; import java.io.Reader; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.Charset; import java.nio.charset.CharsetEncoder; import java.nio.charset.CoderResult; import java.nio.charset.CodingErrorAction; import java.util.Objects; /** * {@link InputStream} implementation that reads a character stream from a {@link Reader} * and transforms it to a byte stream using a specified charset encoding. The stream * is transformed using a {@link CharsetEncoder} object, guaranteeing that all charset * encodings supported by the JRE are handled correctly. In particular for charsets such as * UTF-16, the implementation ensures that one and only one byte order marker * is produced. *

* Since in general it is not possible to predict the number of characters to be read from the * {@link Reader} to satisfy a read request on the {@link ReaderInputStream}, all reads from * the {@link Reader} are buffered. There is therefore no well defined correlation * between the current position of the {@link Reader} and that of the {@link ReaderInputStream}. * This also implies that in general there is no need to wrap the underlying {@link Reader} * in a {@link java.io.BufferedReader}. *

* {@link ReaderInputStream} implements the inverse transformation of {@link java.io.InputStreamReader}; * in the following example, reading from {@code in2} would return the same byte * sequence as reading from {@code in} (provided that the initial byte sequence is legal * with respect to the charset encoding): *

 * InputStream inputStream = ...
 * Charset cs = ...
 * InputStreamReader reader = new InputStreamReader(inputStream, cs);
 * ReaderInputStream in2 = new ReaderInputStream(reader, cs);
* * {@link ReaderInputStream} implements the same transformation as {@link java.io.OutputStreamWriter}, * except that the control flow is reversed: both classes transform a character stream * into a byte stream, but {@link java.io.OutputStreamWriter} pushes data to the underlying stream, * while {@link ReaderInputStream} pulls it from the underlying stream. *

* Note that while there are use cases where there is no alternative to using * this class, very often the need to use this class is an indication of a flaw * in the design of the code. This class is typically used in situations where an existing * API only accepts an {@link InputStream}, but where the most natural way to produce the data * is as a character stream, i.e. by providing a {@link Reader} instance. An example of a situation * where this problem may appear is when implementing the {@code javax.activation.DataSource} * interface from the Java Activation Framework. *

* Given the fact that the {@link Reader} class doesn't provide any way to predict whether the next * read operation will block or not, it is not possible to provide a meaningful * implementation of the {@link InputStream#available()} method. A call to this method * will always return 0. Also, this class doesn't support {@link InputStream#mark(int)}. *

*

* Instances of {@link ReaderInputStream} are not thread safe. *

* * @see org.apache.commons.io.output.WriterOutputStream * * @since 2.0 */ public class ReaderInputStream extends InputStream { private static final int DEFAULT_BUFFER_SIZE = 1024; private final Reader reader; private final CharsetEncoder encoder; /** * CharBuffer used as input for the decoder. It should be reasonably * large as we read data from the underlying Reader into this buffer. */ private final CharBuffer encoderIn; /** * ByteBuffer used as output for the decoder. This buffer can be small * as it is only used to transfer data from the decoder to the * buffer provided by the caller. */ private final ByteBuffer encoderOut; private CoderResult lastCoderResult; private boolean endOfInput; /** * Construct a new {@link ReaderInputStream}. * * @param reader the target {@link Reader} * @param encoder the charset encoder * @since 2.1 */ public ReaderInputStream(final Reader reader, final CharsetEncoder encoder) { this(reader, encoder, DEFAULT_BUFFER_SIZE); } /** * Construct a new {@link ReaderInputStream}. * * @param reader the target {@link Reader} * @param encoder the charset encoder * @param bufferSize the size of the input buffer in number of characters * @since 2.1 */ public ReaderInputStream(final Reader reader, final CharsetEncoder encoder, final int bufferSize) { this.reader = reader; this.encoder = encoder; this.encoderIn = CharBuffer.allocate(bufferSize); this.encoderIn.flip(); this.encoderOut = ByteBuffer.allocate(128); this.encoderOut.flip(); } /** * Construct a new {@link ReaderInputStream}. * * @param reader the target {@link Reader} * @param charset the charset encoding * @param bufferSize the size of the input buffer in number of characters */ public ReaderInputStream(final Reader reader, final Charset charset, final int bufferSize) { this(reader, charset.newEncoder() .onMalformedInput(CodingErrorAction.REPLACE) .onUnmappableCharacter(CodingErrorAction.REPLACE), bufferSize); } /** * Construct a new {@link ReaderInputStream} with a default input buffer size of * {@value #DEFAULT_BUFFER_SIZE} characters. * * @param reader the target {@link Reader} * @param charset the charset encoding */ public ReaderInputStream(final Reader reader, final Charset charset) { this(reader, charset, DEFAULT_BUFFER_SIZE); } /** * Construct a new {@link ReaderInputStream}. * * @param reader the target {@link Reader} * @param charsetName the name of the charset encoding * @param bufferSize the size of the input buffer in number of characters */ public ReaderInputStream(final Reader reader, final String charsetName, final int bufferSize) { this(reader, Charset.forName(charsetName), bufferSize); } /** * Construct a new {@link ReaderInputStream} with a default input buffer size of * {@value #DEFAULT_BUFFER_SIZE} characters. * * @param reader the target {@link Reader} * @param charsetName the name of the charset encoding */ public ReaderInputStream(final Reader reader, final String charsetName) { this(reader, charsetName, DEFAULT_BUFFER_SIZE); } /** * Construct a new {@link ReaderInputStream} that uses the default character encoding * with a default input buffer size of {@value #DEFAULT_BUFFER_SIZE} characters. * * @param reader the target {@link Reader} * @deprecated 2.5 use {@link #ReaderInputStream(Reader, Charset)} instead */ @Deprecated public ReaderInputStream(final Reader reader) { this(reader, Charset.defaultCharset()); } /** * Fills the internal char buffer from the reader. * * @throws IOException * If an I/O error occurs */ private void fillBuffer() throws IOException { if (!endOfInput && (lastCoderResult == null || lastCoderResult.isUnderflow())) { encoderIn.compact(); final int position = encoderIn.position(); // We don't use Reader#read(CharBuffer) here because it is more efficient // to write directly to the underlying char array (the default implementation // copies data to a temporary char array). final int c = reader.read(encoderIn.array(), position, encoderIn.remaining()); if (c == EOF) { endOfInput = true; } else { encoderIn.position(position+c); } encoderIn.flip(); } encoderOut.compact(); lastCoderResult = encoder.encode(encoderIn, encoderOut, endOfInput); encoderOut.flip(); } /** * Read the specified number of bytes into an array. * * @param array the byte array to read into * @param off the offset to start reading bytes into * @param len the number of bytes to read * @return the number of bytes read or {@code -1} * if the end of the stream has been reached * @throws IOException if an I/O error occurs. */ @Override public int read(final byte[] array, int off, int len) throws IOException { Objects.requireNonNull(array, "array"); if (len < 0 || off < 0 || (off + len) > array.length) { throw new IndexOutOfBoundsException("Array Size=" + array.length + ", offset=" + off + ", length=" + len); } int read = 0; if (len == 0) { return 0; // Always return 0 if len == 0 } while (len > 0) { if (encoderOut.hasRemaining()) { final int c = Math.min(encoderOut.remaining(), len); encoderOut.get(array, off, c); off += c; len -= c; read += c; } else { fillBuffer(); if (endOfInput && !encoderOut.hasRemaining()) { break; } } } return read == 0 && endOfInput ? EOF : read; } /** * Read the specified number of bytes into an array. * * @param b the byte array to read into * @return the number of bytes read or {@code -1} * if the end of the stream has been reached * @throws IOException if an I/O error occurs. */ @Override public int read(final byte[] b) throws IOException { return read(b, 0, b.length); } /** * Read a single byte. * * @return either the byte read or {@code -1} if the end of the stream * has been reached * @throws IOException if an I/O error occurs. */ @Override public int read() throws IOException { for (;;) { if (encoderOut.hasRemaining()) { return encoderOut.get() & 0xFF; } fillBuffer(); if (endOfInput && !encoderOut.hasRemaining()) { return EOF; } } } /** * Close the stream. This method will cause the underlying {@link Reader} * to be closed. * @throws IOException if an I/O error occurs. */ @Override public void close() throws IOException { reader.close(); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/ReversedLinesFileReader.java0100644 0000000 0000000 00000044577 13612062727 032253 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import java.io.Closeable; import java.io.File; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import java.nio.channels.SeekableByteChannel; import java.nio.charset.Charset; import java.nio.charset.CharsetEncoder; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardOpenOption; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.apache.commons.io.Charsets; import org.apache.commons.io.IOUtils; import org.apache.commons.io.StandardLineSeparator; /** * Reads lines in a file reversely (similar to a BufferedReader, but starting at * the last line). Useful for e.g. searching in log files. * * @since 2.2 */ public class ReversedLinesFileReader implements Closeable { private class FilePart { private final long no; private final byte[] data; private byte[] leftOver; private int currentLastBytePos; /** * ctor * * @param no the part number * @param length its length * @param leftOverOfLastFilePart remainder * @throws IOException if there is a problem reading the file */ private FilePart(final long no, final int length, final byte[] leftOverOfLastFilePart) throws IOException { this.no = no; final int dataLength = length + (leftOverOfLastFilePart != null ? leftOverOfLastFilePart.length : 0); this.data = new byte[dataLength]; final long off = (no - 1) * blockSize; // read data if (no > 0 /* file not empty */) { channel.position(off); final int countRead = channel.read(ByteBuffer.wrap(data, 0, length)); if (countRead != length) { throw new IllegalStateException("Count of requested bytes and actually read bytes don't match"); } } // copy left over part into data arr if (leftOverOfLastFilePart != null) { System.arraycopy(leftOverOfLastFilePart, 0, data, length, leftOverOfLastFilePart.length); } this.currentLastBytePos = data.length - 1; this.leftOver = null; } /** * Creates the buffer containing any left over bytes. */ private void createLeftOver() { final int lineLengthBytes = currentLastBytePos + 1; if (lineLengthBytes > 0) { // create left over for next block leftOver = IOUtils.byteArray(lineLengthBytes); System.arraycopy(data, 0, leftOver, 0, lineLengthBytes); } else { leftOver = null; } currentLastBytePos = -1; } /** * Finds the new-line sequence and return its length. * * @param data buffer to scan * @param i start offset in buffer * @return length of newline sequence or 0 if none found */ private int getNewLineMatchByteCount(final byte[] data, final int i) { for (final byte[] newLineSequence : newLineSequences) { boolean match = true; for (int j = newLineSequence.length - 1; j >= 0; j--) { final int k = i + j - (newLineSequence.length - 1); match &= k >= 0 && data[k] == newLineSequence[j]; } if (match) { return newLineSequence.length; } } return 0; } /** * Reads a line. * * @return the line or null */ private String readLine() { String line = null; int newLineMatchByteCount; final boolean isLastFilePart = no == 1; int i = currentLastBytePos; while (i > -1) { if (!isLastFilePart && i < avoidNewlineSplitBufferSize) { // avoidNewlineSplitBuffer: for all except the last file part we // take a few bytes to the next file part to avoid splitting of newlines createLeftOver(); break; // skip last few bytes and leave it to the next file part } // --- check for newline --- if ((newLineMatchByteCount = getNewLineMatchByteCount(data, i)) > 0 /* found newline */) { final int lineStart = i + 1; final int lineLengthBytes = currentLastBytePos - lineStart + 1; if (lineLengthBytes < 0) { throw new IllegalStateException("Unexpected negative line length=" + lineLengthBytes); } final byte[] lineData = IOUtils.byteArray(lineLengthBytes); System.arraycopy(data, lineStart, lineData, 0, lineLengthBytes); line = new String(lineData, charset); currentLastBytePos = i - newLineMatchByteCount; break; // found line } // --- move cursor --- i -= byteDecrement; // --- end of file part handling --- if (i < 0) { createLeftOver(); break; // end of file part } } // --- last file part handling --- if (isLastFilePart && leftOver != null) { // there will be no line break anymore, this is the first line of the file line = new String(leftOver, charset); leftOver = null; } return line; } /** * Handles block rollover * * @return the new FilePart or null * @throws IOException if there was a problem reading the file */ private FilePart rollOver() throws IOException { if (currentLastBytePos > -1) { throw new IllegalStateException("Current currentLastCharPos unexpectedly positive... " + "last readLine() should have returned something! currentLastCharPos=" + currentLastBytePos); } if (no > 1) { return new FilePart(no - 1, blockSize, leftOver); } // NO 1 was the last FilePart, we're finished if (leftOver != null) { throw new IllegalStateException("Unexpected leftover of the last block: leftOverOfThisFilePart=" + new String(leftOver, charset)); } return null; } } private static final String EMPTY_STRING = ""; private static final int DEFAULT_BLOCK_SIZE = IOUtils.DEFAULT_BUFFER_SIZE; private final int blockSize; private final Charset charset; private final SeekableByteChannel channel; private final long totalByteLength; private final long totalBlockCount; private final byte[][] newLineSequences; private final int avoidNewlineSplitBufferSize; private final int byteDecrement; private FilePart currentFilePart; private boolean trailingNewlineOfFileSkipped; /** * Creates a ReversedLinesFileReader with default block size of 4KB and the * platform's default encoding. * * @param file the file to be read * @throws IOException if an I/O error occurs. * @deprecated 2.5 use {@link #ReversedLinesFileReader(File, Charset)} instead */ @Deprecated public ReversedLinesFileReader(final File file) throws IOException { this(file, DEFAULT_BLOCK_SIZE, Charset.defaultCharset()); } /** * Creates a ReversedLinesFileReader with default block size of 4KB and the * specified encoding. * * @param file the file to be read * @param charset the charset to use, null uses the default Charset. * @throws IOException if an I/O error occurs. * @since 2.5 */ public ReversedLinesFileReader(final File file, final Charset charset) throws IOException { this(file.toPath(), charset); } /** * Creates a ReversedLinesFileReader with the given block size and encoding. * * @param file the file to be read * @param blockSize size of the internal buffer (for ideal performance this * should match with the block size of the underlying file * system). * @param charset the encoding of the file, null uses the default Charset. * @throws IOException if an I/O error occurs. * @since 2.3 */ public ReversedLinesFileReader(final File file, final int blockSize, final Charset charset) throws IOException { this(file.toPath(), blockSize, charset); } /** * Creates a ReversedLinesFileReader with the given block size and encoding. * * @param file the file to be read * @param blockSize size of the internal buffer (for ideal performance this * should match with the block size of the underlying file * system). * @param charsetName the encoding of the file, null uses the default Charset. * @throws IOException if an I/O error occurs * @throws java.nio.charset.UnsupportedCharsetException thrown instead of * {@link UnsupportedEncodingException} * in version 2.2 if the * encoding is not * supported. */ public ReversedLinesFileReader(final File file, final int blockSize, final String charsetName) throws IOException { this(file.toPath(), blockSize, charsetName); } /** * Creates a ReversedLinesFileReader with default block size of 4KB and the * specified encoding. * * @param file the file to be read * @param charset the charset to use, null uses the default Charset. * @throws IOException if an I/O error occurs. * @since 2.7 */ public ReversedLinesFileReader(final Path file, final Charset charset) throws IOException { this(file, DEFAULT_BLOCK_SIZE, charset); } /** * Creates a ReversedLinesFileReader with the given block size and encoding. * * @param file the file to be read * @param blockSize size of the internal buffer (for ideal performance this * should match with the block size of the underlying file * system). * @param charset the encoding of the file, null uses the default Charset. * @throws IOException if an I/O error occurs. * @since 2.7 */ public ReversedLinesFileReader(final Path file, final int blockSize, final Charset charset) throws IOException { this.blockSize = blockSize; this.charset = Charsets.toCharset(charset); // --- check & prepare encoding --- final CharsetEncoder charsetEncoder = this.charset.newEncoder(); final float maxBytesPerChar = charsetEncoder.maxBytesPerChar(); if (maxBytesPerChar == 1f) { // all one byte encodings are no problem byteDecrement = 1; } else if (this.charset == StandardCharsets.UTF_8) { // UTF-8 works fine out of the box, for multibyte sequences a second UTF-8 byte // can never be a newline byte // http://en.wikipedia.org/wiki/UTF-8 byteDecrement = 1; } else if (this.charset == Charset.forName("Shift_JIS") || // Same as for UTF-8 // http://www.herongyang.com/Unicode/JIS-Shift-JIS-Encoding.html this.charset == Charset.forName("windows-31j") || // Windows code page 932 (Japanese) this.charset == Charset.forName("x-windows-949") || // Windows code page 949 (Korean) this.charset == Charset.forName("gbk") || // Windows code page 936 (Simplified Chinese) this.charset == Charset.forName("x-windows-950")) { // Windows code page 950 (Traditional Chinese) byteDecrement = 1; } else if (this.charset == StandardCharsets.UTF_16BE || this.charset == StandardCharsets.UTF_16LE) { // UTF-16 new line sequences are not allowed as second tuple of four byte // sequences, // however byte order has to be specified byteDecrement = 2; } else if (this.charset == StandardCharsets.UTF_16) { throw new UnsupportedEncodingException( "For UTF-16, you need to specify the byte order (use UTF-16BE or " + "UTF-16LE)"); } else { throw new UnsupportedEncodingException( "Encoding " + charset + " is not supported yet (feel free to " + "submit a patch)"); } // NOTE: The new line sequences are matched in the order given, so it is // important that \r\n is BEFORE \n this.newLineSequences = new byte[][] { StandardLineSeparator.CRLF.getBytes(this.charset), StandardLineSeparator.LF.getBytes(this.charset), StandardLineSeparator.CR.getBytes(this.charset) }; this.avoidNewlineSplitBufferSize = newLineSequences[0].length; // Open file this.channel = Files.newByteChannel(file, StandardOpenOption.READ); this.totalByteLength = channel.size(); int lastBlockLength = (int) (this.totalByteLength % blockSize); if (lastBlockLength > 0) { this.totalBlockCount = this.totalByteLength / blockSize + 1; } else { this.totalBlockCount = this.totalByteLength / blockSize; if (this.totalByteLength > 0) { lastBlockLength = blockSize; } } this.currentFilePart = new FilePart(totalBlockCount, lastBlockLength, null); } /** * Creates a ReversedLinesFileReader with the given block size and encoding. * * @param file the file to be read * @param blockSize size of the internal buffer (for ideal performance this * should match with the block size of the underlying file * system). * @param charsetName the encoding of the file, null uses the default Charset. * @throws IOException if an I/O error occurs * @throws java.nio.charset.UnsupportedCharsetException thrown instead of * {@link UnsupportedEncodingException} * in version 2.2 if the * encoding is not * supported. * @since 2.7 */ public ReversedLinesFileReader(final Path file, final int blockSize, final String charsetName) throws IOException { this(file, blockSize, Charsets.toCharset(charsetName)); } /** * Closes underlying resources. * * @throws IOException if an I/O error occurs. */ @Override public void close() throws IOException { channel.close(); } /** * Returns the lines of the file from bottom to top. * * @return the next line or null if the start of the file is reached * @throws IOException if an I/O error occurs. */ public String readLine() throws IOException { String line = currentFilePart.readLine(); while (line == null) { currentFilePart = currentFilePart.rollOver(); if (currentFilePart == null) { // no more fileparts: we're done, leave line set to null break; } line = currentFilePart.readLine(); } // aligned behavior with BufferedReader that doesn't return a last, empty line if (EMPTY_STRING.equals(line) && !trailingNewlineOfFileSkipped) { trailingNewlineOfFileSkipped = true; line = readLine(); } return line; } /** * Returns {@code lineCount} lines of the file from bottom to top. *

* If there are less than {@code lineCount} lines in the file, then that's what * you get. *

*

* Note: You can easily flip the result with {@link Collections#reverse(List)}. *

* * @param lineCount How many lines to read. * @return A new list * @throws IOException if an I/O error occurs. * @since 2.8.0 */ public List readLines(final int lineCount) throws IOException { if (lineCount < 0) { throw new IllegalArgumentException("lineCount < 0"); } final ArrayList arrayList = new ArrayList<>(lineCount); for (int i = 0; i < lineCount; i++) { final String line = readLine(); if (line == null) { return arrayList; } arrayList.add(line); } return arrayList; } /** * Returns the last {@code lineCount} lines of the file. *

* If there are less than {@code lineCount} lines in the file, then that's what * you get. *

* * @param lineCount How many lines to read. * @return A String. * @throws IOException if an I/O error occurs. * @since 2.8.0 */ public String toString(final int lineCount) throws IOException { final List lines = readLines(lineCount); Collections.reverse(lines); return lines.isEmpty() ? EMPTY_STRING : String.join(System.lineSeparator(), lines) + System.lineSeparator(); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/SequenceReader.java0100644 0000000 0000000 00000006570 13612062727 030440 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.apache.commons.io.IOUtils.EOF; import java.io.IOException; import java.io.Reader; import java.util.Arrays; import java.util.Iterator; import java.util.Objects; /** * Provides the contents of multiple Readers in sequence. * * @since 2.7 */ public class SequenceReader extends Reader { private Reader reader; private Iterator readers; /** * Construct a new instance with readers * * @param readers the readers to read */ public SequenceReader(final Iterable readers) { this.readers = Objects.requireNonNull(readers, "readers").iterator(); this.reader = nextReader(); } /** * Construct a new instance with readers * * @param readers the readers to read */ public SequenceReader(final Reader... readers) { this(Arrays.asList(readers)); } /* * (non-Javadoc) * * @see java.io.Reader#close() */ @Override public void close() throws IOException { this.readers = null; this.reader = null; } /** * Returns the next available reader or null if done. * * @return the next available reader or null */ private Reader nextReader() { return this.readers.hasNext() ? this.readers.next() : null; } /* * (non-Javadoc) * * @see java.io.Reader#read(char[], int, int) */ @Override public int read() throws IOException { int c = EOF; while (reader != null) { c = reader.read(); if (c != EOF) { break; } reader = nextReader(); } return c; } /* * (non-Javadoc) * * @see java.io.Reader#read() */ @Override public int read(final char[] cbuf, int off, int len) throws IOException { Objects.requireNonNull(cbuf, "cbuf"); if (len < 0 || off < 0 || off + len > cbuf.length) { throw new IndexOutOfBoundsException("Array Size=" + cbuf.length + ", offset=" + off + ", length=" + len); } int count = 0; while (reader != null) { final int readLen = reader.read(cbuf, off, len); if (readLen == EOF) { reader = nextReader(); } else { count += readLen; off += readLen; len -= readLen; if (len <= 0) { break; } } } if (count > 0) { return count; } return EOF; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/SwappedDataInputStream.java0100644 0000000 0000000 00000017247 13612062727 032141 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.apache.commons.io.IOUtils.EOF; import java.io.DataInput; import java.io.EOFException; import java.io.IOException; import java.io.InputStream; import org.apache.commons.io.EndianUtils; /** * DataInput for systems relying on little endian data formats. When read, values will be changed from little endian to * big endian formats for internal usage. *

* Origin of code: Avalon Excalibur (IO) *

* */ public class SwappedDataInputStream extends ProxyInputStream implements DataInput { /** * Constructs a SwappedDataInputStream. * * @param input InputStream to read from */ public SwappedDataInputStream(final InputStream input) { super(input); } /** * Return {@link #readByte()} != 0 * * @return false if the byte read is zero, otherwise true * @throws IOException if an I/O error occurs. * @throws EOFException if an end of file is reached unexpectedly */ @Override public boolean readBoolean() throws IOException, EOFException { return 0 != readByte(); } /** * Invokes the delegate's {@code read()} method. * * @return the byte read or -1 if the end of stream * @throws IOException if an I/O error occurs. * @throws EOFException if an end of file is reached unexpectedly */ @Override public byte readByte() throws IOException, EOFException { return (byte) in.read(); } /** * Reads a character delegating to {@link #readShort()}. * * @return the byte read or -1 if the end of stream * @throws IOException if an I/O error occurs. * @throws EOFException if an end of file is reached unexpectedly */ @Override public char readChar() throws IOException, EOFException { return (char) readShort(); } /** * Delegates to {@link EndianUtils#readSwappedDouble(InputStream)}. * * @return the read long * @throws IOException if an I/O error occurs. * @throws EOFException if an end of file is reached unexpectedly */ @Override public double readDouble() throws IOException, EOFException { return EndianUtils.readSwappedDouble(in); } /** * Delegates to {@link EndianUtils#readSwappedFloat(InputStream)}. * * @return the read long * @throws IOException if an I/O error occurs. * @throws EOFException if an end of file is reached unexpectedly */ @Override public float readFloat() throws IOException, EOFException { return EndianUtils.readSwappedFloat(in); } /** * Invokes the delegate's {@code read(byte[] data, int, int)} method. * * @param data the buffer to read the bytes into * @throws EOFException if an end of file is reached unexpectedly * @throws IOException if an I/O error occurs. */ @Override public void readFully(final byte[] data) throws IOException, EOFException { readFully(data, 0, data.length); } /** * Invokes the delegate's {@code read(byte[] data, int, int)} method. * * @param data the buffer to read the bytes into * @param offset The start offset * @param length The number of bytes to read * @throws EOFException if an end of file is reached unexpectedly * @throws IOException if an I/O error occurs. */ @Override public void readFully(final byte[] data, final int offset, final int length) throws IOException, EOFException { int remaining = length; while (remaining > 0) { final int location = offset + length - remaining; final int count = read(data, location, remaining); if (EOF == count) { throw new EOFException(); } remaining -= count; } } /** * Delegates to {@link EndianUtils#readSwappedInteger(InputStream)}. * * @return the read long * @throws EOFException if an end of file is reached unexpectedly * @throws IOException if an I/O error occurs. */ @Override public int readInt() throws IOException, EOFException { return EndianUtils.readSwappedInteger(in); } /** * Not currently supported - throws {@link UnsupportedOperationException}. * * @return the line read * @throws EOFException if an end of file is reached unexpectedly * @throws IOException if an I/O error occurs. */ @Override public String readLine() throws IOException, EOFException { throw UnsupportedOperationExceptions.method("readLine"); } /** * Delegates to {@link EndianUtils#readSwappedLong(InputStream)}. * * @return the read long * @throws EOFException if an end of file is reached unexpectedly * @throws IOException if an I/O error occurs. */ @Override public long readLong() throws IOException, EOFException { return EndianUtils.readSwappedLong(in); } /** * Delegates to {@link EndianUtils#readSwappedShort(InputStream)}. * * @return the read long * @throws EOFException if an end of file is reached unexpectedly * @throws IOException if an I/O error occurs. */ @Override public short readShort() throws IOException, EOFException { return EndianUtils.readSwappedShort(in); } /** * Invokes the delegate's {@code read()} method. * * @return the byte read or -1 if the end of stream * @throws EOFException if an end of file is reached unexpectedly * @throws IOException if an I/O error occurs. */ @Override public int readUnsignedByte() throws IOException, EOFException { return in.read(); } /** * Delegates to {@link EndianUtils#readSwappedUnsignedShort(InputStream)}. * * @return the read long * @throws EOFException if an end of file is reached unexpectedly * @throws IOException if an I/O error occurs. */ @Override public int readUnsignedShort() throws IOException, EOFException { return EndianUtils.readSwappedUnsignedShort(in); } /** * Not currently supported - throws {@link UnsupportedOperationException}. * * @return UTF String read * @throws EOFException if an end of file is reached unexpectedly * @throws IOException if an I/O error occurs. */ @Override public String readUTF() throws IOException, EOFException { throw UnsupportedOperationExceptions.method("readUTF"); } /** * Invokes the delegate's {@code skip(int)} method. * * @param count the number of bytes to skip * @return the number of bytes to skipped or -1 if the end of stream * @throws EOFException if an end of file is reached unexpectedly * @throws IOException if an I/O error occurs. */ @Override public int skipBytes(final int count) throws IOException, EOFException { return (int) in.skip(count); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/TaggedInputStream.java0100644 0000000 0000000 00000007770 13612062727 031137 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import java.io.IOException; import java.io.InputStream; import java.io.Serializable; import java.util.UUID; import org.apache.commons.io.TaggedIOException; /** * An input stream decorator that tags potential exceptions so that the * stream that caused the exception can easily be identified. This is * done by using the {@link TaggedIOException} class to wrap all thrown * {@link IOException}s. See below for an example of using this class. *
 * TaggedInputStream stream = new TaggedInputStream(...);
 * try {
 *     // Processing that may throw an IOException either from this stream
 *     // or from some other IO activity like temporary files, etc.
 *     processStream(stream);
 * } catch (IOException e) {
 *     if (stream.isCauseOf(e)) {
 *         // The exception was caused by this stream.
 *         // Use e.getCause() to get the original exception.
 *     } else {
 *         // The exception was caused by something else.
 *     }
 * }
 * 
*

* Alternatively, the {@link #throwIfCauseOf(Throwable)} method can be * used to let higher levels of code handle the exception caused by this * stream while other processing errors are being taken care of at this * lower level. *

*
 * TaggedInputStream stream = new TaggedInputStream(...);
 * try {
 *     processStream(stream);
 * } catch (IOException e) {
 *     stream.throwIfCauseOf(e);
 *     // ... or process the exception that was caused by something else
 * }
 * 
* * @see TaggedIOException * @since 2.0 */ public class TaggedInputStream extends ProxyInputStream { /** * The unique tag associated with exceptions from stream. */ private final Serializable tag = UUID.randomUUID(); /** * Creates a tagging decorator for the given input stream. * * @param proxy input stream to be decorated */ public TaggedInputStream(final InputStream proxy) { super(proxy); } /** * Tests if the given exception was caused by this stream. * * @param exception an exception * @return {@code true} if the exception was thrown by this stream, * {@code false} otherwise */ public boolean isCauseOf(final Throwable exception) { return TaggedIOException.isTaggedWith(exception, tag); } /** * Re-throws the original exception thrown by this stream. This method * first checks whether the given exception is a {@link TaggedIOException} * wrapper created by this decorator, and then unwraps and throws the * original wrapped exception. Returns normally if the exception was * not thrown by this stream. * * @param throwable an exception * @throws IOException original exception, if any, thrown by this stream */ public void throwIfCauseOf(final Throwable throwable) throws IOException { TaggedIOException.throwCauseIfTaggedWith(throwable, tag); } /** * Tags any IOExceptions thrown, wrapping and re-throwing. * * @param e The IOException thrown * @throws IOException if an I/O error occurs. */ @Override protected void handleIOException(final IOException e) throws IOException { throw new TaggedIOException(e, tag); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/TaggedReader.java0100644 0000000 0000000 00000007630 13612062727 030061 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import java.io.IOException; import java.io.Reader; import java.io.Serializable; import java.util.UUID; import org.apache.commons.io.TaggedIOException; /** * A reader decorator that tags potential exceptions so that the reader that caused the exception can easily be * identified. This is done by using the {@link TaggedIOException} class to wrap all thrown {@link IOException}s. See * below for an example of using this class. * *
 * TaggedReader reader = new TaggedReader(...);
 * try {
 *     // Processing that may throw an IOException either from this reader
 *     // or from some other IO activity like temporary files, etc.
 *     processReader(reader);
 * } catch (IOException e) {
 *     if (reader.isCauseOf(e)) {
 *         // The exception was caused by this reader.
 *         // Use e.getCause() to get the original exception.
 *     } else {
 *         // The exception was caused by something else.
 *     }
 * }
 * 
*

* Alternatively, the {@link #throwIfCauseOf(Throwable)} method can be used to let higher levels of code handle the * exception caused by this reader while other processing errors are being taken care of at this lower level. *

* *
 * TaggedReader reader = new TaggedReader(...);
 * try {
 *     processReader(reader);
 * } catch (IOException e) {
 *     reader.throwIfCauseOf(e);
 *     // ... or process the exception that was caused by something else
 * }
 * 
* * @see TaggedIOException * @since 2.7 */ public class TaggedReader extends ProxyReader { /** * The unique tag associated with exceptions from reader. */ private final Serializable tag = UUID.randomUUID(); /** * Creates a tagging decorator for the given reader. * * @param proxy reader to be decorated */ public TaggedReader(final Reader proxy) { super(proxy); } /** * Tests if the given exception was caused by this reader. * * @param exception an exception * @return {@code true} if the exception was thrown by this reader, {@code false} otherwise */ public boolean isCauseOf(final Throwable exception) { return TaggedIOException.isTaggedWith(exception, tag); } /** * Re-throws the original exception thrown by this reader. This method first checks whether the given exception is a * {@link TaggedIOException} wrapper created by this decorator, and then unwraps and throws the original wrapped * exception. Returns normally if the exception was not thrown by this reader. * * @param throwable an exception * @throws IOException original exception, if any, thrown by this reader */ public void throwIfCauseOf(final Throwable throwable) throws IOException { TaggedIOException.throwCauseIfTaggedWith(throwable, tag); } /** * Tags any IOExceptions thrown, wrapping and re-throwing. * * @param e The IOException thrown * @throws IOException if an I/O error occurs. */ @Override protected void handleIOException(final IOException e) throws IOException { throw new TaggedIOException(e, tag); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/Tailer.java0100644 0000000 0000000 00000051362 13612062727 026764 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.apache.commons.io.IOUtils.CR; import static org.apache.commons.io.IOUtils.EOF; import static org.apache.commons.io.IOUtils.LF; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.charset.Charset; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; /** * Simple implementation of the unix "tail -f" functionality. * *

1. Create a TailerListener implementation

*

* First you need to create a {@link TailerListener} implementation * ({@link TailerListenerAdapter} is provided for convenience so that you don't have to * implement every method). *

* *

For example:

*
 *  public class MyTailerListener extends TailerListenerAdapter {
 *      public void handle(String line) {
 *          System.out.println(line);
 *      }
 *  }
* *

2. Using a Tailer

* *

* You can create and use a Tailer in one of three ways: *

*
    *
  • Using one of the static helper methods: *
      *
    • {@link Tailer#create(File, TailerListener)}
    • *
    • {@link Tailer#create(File, TailerListener, long)}
    • *
    • {@link Tailer#create(File, TailerListener, long, boolean)}
    • *
    *
  • *
  • Using an {@link java.util.concurrent.Executor}
  • *
  • Using an {@link Thread}
  • *
* *

* An example of each of these is shown below. *

* *

2.1 Using the static helper method

* *
 *      TailerListener listener = new MyTailerListener();
 *      Tailer tailer = Tailer.create(file, listener, delay);
* *

2.2 Using an Executor

* *
 *      TailerListener listener = new MyTailerListener();
 *      Tailer tailer = new Tailer(file, listener, delay);
 *
 *      // stupid executor impl. for demo purposes
 *      Executor executor = new Executor() {
 *          public void execute(Runnable command) {
 *              command.run();
 *           }
 *      };
 *
 *      executor.execute(tailer);
 * 
* * *

2.3 Using a Thread

*
 *      TailerListener listener = new MyTailerListener();
 *      Tailer tailer = new Tailer(file, listener, delay);
 *      Thread thread = new Thread(tailer);
 *      thread.setDaemon(true); // optional
 *      thread.start();
* *

3. Stopping a Tailer

*

Remember to stop the tailer when you have done with it:

*
 *      tailer.stop();
 * 
* *

4. Interrupting a Tailer

*

You can interrupt the thread a tailer is running on by calling {@link Thread#interrupt()}. *

*
 *      thread.interrupt();
 * 
*

* If you interrupt a tailer, the tailer listener is called with the {@link InterruptedException}. *

*

* The file is read using the default charset; this can be overridden if necessary. *

* @see TailerListener * @see TailerListenerAdapter * @since 2.0 * @since 2.5 Updated behavior and documentation for {@link Thread#interrupt()} */ public class Tailer implements Runnable { private static final int DEFAULT_DELAY_MILLIS = 1000; private static final String RAF_MODE = "r"; // The default charset used for reading files private static final Charset DEFAULT_CHARSET = Charset.defaultCharset(); /** * Buffer on top of RandomAccessFile. */ private final byte[] inbuf; /** * The file which will be tailed. */ private final File file; /** * The character set that will be used to read the file. */ private final Charset charset; /** * The amount of time to wait for the file to be updated. */ private final long delayMillis; /** * Whether to tail from the end or start of file */ private final boolean end; /** * The listener to notify of events when tailing. */ private final TailerListener listener; /** * Whether to close and reopen the file whilst waiting for more input. */ private final boolean reOpen; /** * The tailer will run as long as this value is true. */ private volatile boolean run = true; /** * Creates a Tailer for the given file, starting from the beginning, with the default delay of 1.0s. * @param file The file to follow. * @param listener the TailerListener to use. */ public Tailer(final File file, final TailerListener listener) { this(file, listener, DEFAULT_DELAY_MILLIS); } /** * Creates a Tailer for the given file, starting from the beginning. * @param file the file to follow. * @param listener the TailerListener to use. * @param delayMillis the delay between checks of the file for new content in milliseconds. */ public Tailer(final File file, final TailerListener listener, final long delayMillis) { this(file, listener, delayMillis, false); } /** * Creates a Tailer for the given file, with a delay other than the default 1.0s. * @param file the file to follow. * @param listener the TailerListener to use. * @param delayMillis the delay between checks of the file for new content in milliseconds. * @param end Set to true to tail from the end of the file, false to tail from the beginning of the file. */ public Tailer(final File file, final TailerListener listener, final long delayMillis, final boolean end) { this(file, listener, delayMillis, end, IOUtils.DEFAULT_BUFFER_SIZE); } /** * Creates a Tailer for the given file, with a delay other than the default 1.0s. * @param file the file to follow. * @param listener the TailerListener to use. * @param delayMillis the delay between checks of the file for new content in milliseconds. * @param end Set to true to tail from the end of the file, false to tail from the beginning of the file. * @param reOpen if true, close and reopen the file between reading chunks */ public Tailer(final File file, final TailerListener listener, final long delayMillis, final boolean end, final boolean reOpen) { this(file, listener, delayMillis, end, reOpen, IOUtils.DEFAULT_BUFFER_SIZE); } /** * Creates a Tailer for the given file, with a specified buffer size. * @param file the file to follow. * @param listener the TailerListener to use. * @param delayMillis the delay between checks of the file for new content in milliseconds. * @param end Set to true to tail from the end of the file, false to tail from the beginning of the file. * @param bufSize Buffer size */ public Tailer(final File file, final TailerListener listener, final long delayMillis, final boolean end, final int bufSize) { this(file, listener, delayMillis, end, false, bufSize); } /** * Creates a Tailer for the given file, with a specified buffer size. * @param file the file to follow. * @param listener the TailerListener to use. * @param delayMillis the delay between checks of the file for new content in milliseconds. * @param end Set to true to tail from the end of the file, false to tail from the beginning of the file. * @param reOpen if true, close and reopen the file between reading chunks * @param bufSize Buffer size */ public Tailer(final File file, final TailerListener listener, final long delayMillis, final boolean end, final boolean reOpen, final int bufSize) { this(file, DEFAULT_CHARSET, listener, delayMillis, end, reOpen, bufSize); } /** * Creates a Tailer for the given file, with a specified buffer size. * @param file the file to follow. * @param charset the Charset to be used for reading the file * @param listener the TailerListener to use. * @param delayMillis the delay between checks of the file for new content in milliseconds. * @param end Set to true to tail from the end of the file, false to tail from the beginning of the file. * @param reOpen if true, close and reopen the file between reading chunks * @param bufSize Buffer size */ public Tailer(final File file, final Charset charset, final TailerListener listener, final long delayMillis, final boolean end, final boolean reOpen , final int bufSize) { this.file = file; this.delayMillis = delayMillis; this.end = end; this.inbuf = IOUtils.byteArray(bufSize); // Save and prepare the listener this.listener = listener; listener.init(this); this.reOpen = reOpen; this.charset = charset; } /** * Creates and starts a Tailer for the given file. * * @param file the file to follow. * @param listener the TailerListener to use. * @param delayMillis the delay between checks of the file for new content in milliseconds. * @param end Set to true to tail from the end of the file, false to tail from the beginning of the file. * @param bufSize buffer size. * @return The new tailer */ public static Tailer create(final File file, final TailerListener listener, final long delayMillis, final boolean end, final int bufSize) { return create(file, listener, delayMillis, end, false, bufSize); } /** * Creates and starts a Tailer for the given file. * * @param file the file to follow. * @param listener the TailerListener to use. * @param delayMillis the delay between checks of the file for new content in milliseconds. * @param end Set to true to tail from the end of the file, false to tail from the beginning of the file. * @param reOpen whether to close/reopen the file between chunks * @param bufSize buffer size. * @return The new tailer */ public static Tailer create(final File file, final TailerListener listener, final long delayMillis, final boolean end, final boolean reOpen, final int bufSize) { return create(file, DEFAULT_CHARSET, listener, delayMillis, end, reOpen, bufSize); } /** * Creates and starts a Tailer for the given file. * * @param file the file to follow. * @param charset the character set to use for reading the file * @param listener the TailerListener to use. * @param delayMillis the delay between checks of the file for new content in milliseconds. * @param end Set to true to tail from the end of the file, false to tail from the beginning of the file. * @param reOpen whether to close/reopen the file between chunks * @param bufSize buffer size. * @return The new tailer */ public static Tailer create(final File file, final Charset charset, final TailerListener listener, final long delayMillis, final boolean end, final boolean reOpen ,final int bufSize) { final Tailer tailer = new Tailer(file, charset, listener, delayMillis, end, reOpen, bufSize); final Thread thread = new Thread(tailer); thread.setDaemon(true); thread.start(); return tailer; } /** * Creates and starts a Tailer for the given file with default buffer size. * * @param file the file to follow. * @param listener the TailerListener to use. * @param delayMillis the delay between checks of the file for new content in milliseconds. * @param end Set to true to tail from the end of the file, false to tail from the beginning of the file. * @return The new tailer */ public static Tailer create(final File file, final TailerListener listener, final long delayMillis, final boolean end) { return create(file, listener, delayMillis, end, IOUtils.DEFAULT_BUFFER_SIZE); } /** * Creates and starts a Tailer for the given file with default buffer size. * * @param file the file to follow. * @param listener the TailerListener to use. * @param delayMillis the delay between checks of the file for new content in milliseconds. * @param end Set to true to tail from the end of the file, false to tail from the beginning of the file. * @param reOpen whether to close/reopen the file between chunks * @return The new tailer */ public static Tailer create(final File file, final TailerListener listener, final long delayMillis, final boolean end, final boolean reOpen) { return create(file, listener, delayMillis, end, reOpen, IOUtils.DEFAULT_BUFFER_SIZE); } /** * Creates and starts a Tailer for the given file, starting at the beginning of the file * * @param file the file to follow. * @param listener the TailerListener to use. * @param delayMillis the delay between checks of the file for new content in milliseconds. * @return The new tailer */ public static Tailer create(final File file, final TailerListener listener, final long delayMillis) { return create(file, listener, delayMillis, false); } /** * Creates and starts a Tailer for the given file, starting at the beginning of the file * with the default delay of 1.0s * * @param file the file to follow. * @param listener the TailerListener to use. * @return The new tailer */ public static Tailer create(final File file, final TailerListener listener) { return create(file, listener, DEFAULT_DELAY_MILLIS, false); } /** * Return the file. * * @return the file */ public File getFile() { return file; } /** * Gets whether to keep on running. * * @return whether to keep on running. * @since 2.5 */ protected boolean getRun() { return run; } /** * Return the delay in milliseconds. * * @return the delay in milliseconds. */ public long getDelay() { return delayMillis; } /** * Follows changes in the file, calling the TailerListener's handle method for each new line. */ @Override public void run() { RandomAccessFile reader = null; try { long last = 0; // The last time the file was checked for changes long position = 0; // position within the file // Open the file while (getRun() && reader == null) { try { reader = new RandomAccessFile(file, RAF_MODE); } catch (final FileNotFoundException e) { listener.fileNotFound(); } if (reader == null) { Thread.sleep(delayMillis); } else { // The current position in the file position = end ? file.length() : 0; last = FileUtils.lastModified(file); reader.seek(position); } } while (getRun()) { final boolean newer = FileUtils.isFileNewer(file, last); // IO-279, must be done first // Check the file length to see if it was rotated final long length = file.length(); if (length < position) { // File was rotated listener.fileRotated(); // Reopen the reader after rotation ensuring that the old file is closed iff we re-open it // successfully try (RandomAccessFile save = reader) { reader = new RandomAccessFile(file, RAF_MODE); // At this point, we're sure that the old file is rotated // Finish scanning the old file and then we'll start with the new one try { readLines(save); } catch (final IOException ioe) { listener.handle(ioe); } position = 0; } catch (final FileNotFoundException e) { // in this case we continue to use the previous reader and position values listener.fileNotFound(); Thread.sleep(delayMillis); } continue; } // File was not rotated // See if the file needs to be read again if (length > position) { // The file has more content than it did last time position = readLines(reader); last = FileUtils.lastModified(file); } else if (newer) { /* * This can happen if the file is truncated or overwritten with the exact same length of * information. In cases like this, the file position needs to be reset */ position = 0; reader.seek(position); // cannot be null here // Now we can read new lines position = readLines(reader); last = FileUtils.lastModified(file); } if (reOpen && reader != null) { reader.close(); } Thread.sleep(delayMillis); if (getRun() && reOpen) { reader = new RandomAccessFile(file, RAF_MODE); reader.seek(position); } } } catch (final InterruptedException e) { Thread.currentThread().interrupt(); listener.handle(e); } catch (final Exception e) { listener.handle(e); } finally { try { if (reader != null) { reader.close(); } } catch (final IOException e) { listener.handle(e); } stop(); } } /** * Allows the tailer to complete its current loop and return. */ public void stop() { this.run = false; } /** * Read new lines. * * @param reader The file to read * @return The new position after the lines have been read * @throws java.io.IOException if an I/O error occurs. */ private long readLines(final RandomAccessFile reader) throws IOException { try (ByteArrayOutputStream lineBuf = new ByteArrayOutputStream(64)) { long pos = reader.getFilePointer(); long rePos = pos; // position to re-read int num; boolean seenCR = false; while (getRun() && ((num = reader.read(inbuf)) != EOF)) { for (int i = 0; i < num; i++) { final byte ch = inbuf[i]; switch (ch) { case LF: seenCR = false; // swallow CR before LF listener.handle(new String(lineBuf.toByteArray(), charset)); lineBuf.reset(); rePos = pos + i + 1; break; case CR: if (seenCR) { lineBuf.write(CR); } seenCR = true; break; default: if (seenCR) { seenCR = false; // swallow final CR listener.handle(new String(lineBuf.toByteArray(), charset)); lineBuf.reset(); rePos = pos + i + 1; } lineBuf.write(ch); } } pos = reader.getFilePointer(); } reader.seek(rePos); // Ensure we can re-read if necessary if (listener instanceof TailerListenerAdapter) { ((TailerListenerAdapter) listener).endOfFileReached(); } return rePos; } } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/TailerListener.java0100644 0000000 0000000 00000003705 13612062727 030470 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; /** * Listener for events from a {@link Tailer}. * * @since 2.0 */ public interface TailerListener { /** * The tailer will call this method during construction, * giving the listener a method of stopping the tailer. * @param tailer the tailer. */ void init(Tailer tailer); /** * This method is called if the tailed file is not found. *

* Note: this is called from the tailer thread. */ void fileNotFound(); /** * Called if a file rotation is detected. * * This method is called before the file is reopened, and fileNotFound may * be called if the new file has not yet been created. *

* Note: this is called from the tailer thread. */ void fileRotated(); /** * Handles a line from a Tailer. *

* Note: this is called from the tailer thread. * @param line the line. */ void handle(String line); /** * Handles an Exception . *

* Note: this is called from the tailer thread. * @param ex the exception. */ void handle(Exception ex); } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/TailerListenerAdapter.java0100644 0000000 0000000 00000004505 13612062727 031770 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; /** * {@link TailerListener} Adapter. * * @since 2.0 */ public class TailerListenerAdapter implements TailerListener { /** * The tailer will call this method during construction, * giving the listener a method of stopping the tailer. * @param tailer the tailer. */ @Override public void init(final Tailer tailer) { // noop } /** * This method is called if the tailed file is not found. */ @Override public void fileNotFound() { // noop } /** * Called if a file rotation is detected. * * This method is called before the file is reopened, and fileNotFound may * be called if the new file has not yet been created. */ @Override public void fileRotated() { // noop } /** * Handles a line from a Tailer. * @param line the line. */ @Override public void handle(final String line) { // noop } /** * Handles an Exception . * @param ex the exception. */ @Override public void handle(final Exception ex) { // noop } /** * Called each time the Tailer reaches the end of the file. * * Note: this is called from the tailer thread. * * Note: a future version of commons-io will pull this method up to the TailerListener interface, * for now clients must subclass this class to use this feature. * * @since 2.5 */ public void endOfFileReached() { // noop } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/TeeInputStream.java0100644 0000000 0000000 00000012217 13612062727 030451 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.apache.commons.io.IOUtils.EOF; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; /** * InputStream proxy that transparently writes a copy of all bytes read * from the proxied stream to a given OutputStream. Using {@link #skip(long)} * or {@link #mark(int)}/{@link #reset()} on the stream will result on some * bytes from the input stream being skipped or duplicated in the output * stream. *

* The proxied input stream is closed when the {@link #close()} method is * called on this proxy. You may configure whether the input stream closes the * output stream. *

* * @since 1.4 * @see ObservableInputStream */ public class TeeInputStream extends ProxyInputStream { /** * The output stream that will receive a copy of all bytes read from the * proxied input stream. */ private final OutputStream branch; /** * Flag for closing the associated output stream when this stream is closed. */ private final boolean closeBranch; /** * Creates a TeeInputStream that proxies the given {@link InputStream} * and copies all read bytes to the given {@link OutputStream}. The given * output stream will not be closed when this stream gets closed. * * @param input input stream to be proxied * @param branch output stream that will receive a copy of all bytes read */ public TeeInputStream(final InputStream input, final OutputStream branch) { this(input, branch, false); } /** * Creates a TeeInputStream that proxies the given {@link InputStream} * and copies all read bytes to the given {@link OutputStream}. The given * output stream will be closed when this stream gets closed if the * closeBranch parameter is {@code true}. * * @param input input stream to be proxied * @param branch output stream that will receive a copy of all bytes read * @param closeBranch flag for closing also the output stream when this * stream is closed */ public TeeInputStream( final InputStream input, final OutputStream branch, final boolean closeBranch) { super(input); this.branch = branch; this.closeBranch = closeBranch; } /** * Closes the proxied input stream and, if so configured, the associated * output stream. An exception thrown from one stream will not prevent * closing of the other stream. * * @throws IOException if either of the streams could not be closed */ @Override public void close() throws IOException { try { super.close(); } finally { if (closeBranch) { branch.close(); } } } /** * Reads a single byte from the proxied input stream and writes it to * the associated output stream. * * @return next byte from the stream, or -1 if the stream has ended * @throws IOException if the stream could not be read (or written) */ @Override public int read() throws IOException { final int ch = super.read(); if (ch != EOF) { branch.write(ch); } return ch; } /** * Reads bytes from the proxied input stream and writes the read bytes * to the associated output stream. * * @param bts byte buffer * @param st start offset within the buffer * @param end maximum number of bytes to read * @return number of bytes read, or -1 if the stream has ended * @throws IOException if the stream could not be read (or written) */ @Override public int read(final byte[] bts, final int st, final int end) throws IOException { final int n = super.read(bts, st, end); if (n != EOF) { branch.write(bts, st, n); } return n; } /** * Reads bytes from the proxied input stream and writes the read bytes * to the associated output stream. * * @param bts byte buffer * @return number of bytes read, or -1 if the stream has ended * @throws IOException if the stream could not be read (or written) */ @Override public int read(final byte[] bts) throws IOException { final int n = super.read(bts); if (n != EOF) { branch.write(bts, 0, n); } return n; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/TeeReader.java0100644 0000000 0000000 00000013711 13612062727 027400 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.apache.commons.io.IOUtils.EOF; import java.io.IOException; import java.io.Reader; import java.io.Writer; import java.nio.CharBuffer; /** * Reader proxy that transparently writes a copy of all characters read from the proxied reader to a given Reader. Using * {@link #skip(long)} or {@link #mark(int)}/{@link #reset()} on the reader will result on some characters from the * reader being skipped or duplicated in the writer. *

* The proxied reader is closed when the {@link #close()} method is called on this proxy. You may configure whether the * reader closes the writer. *

* * @since 2.7 */ public class TeeReader extends ProxyReader { /** * The writer that will receive a copy of all characters read from the proxied reader. */ private final Writer branch; /** * Flag for closing the associated writer when this reader is closed. */ private final boolean closeBranch; /** * Creates a TeeReader that proxies the given {@link Reader} and copies all read characters to the given * {@link Writer}. The given writer will not be closed when this reader gets closed. * * @param input reader to be proxied * @param branch writer that will receive a copy of all characters read */ public TeeReader(final Reader input, final Writer branch) { this(input, branch, false); } /** * Creates a TeeReader that proxies the given {@link Reader} and copies all read characters to the given * {@link Writer}. The given writer will be closed when this reader gets closed if the closeBranch parameter is * {@code true}. * * @param input reader to be proxied * @param branch writer that will receive a copy of all characters read * @param closeBranch flag for closing also the writer when this reader is closed */ public TeeReader(final Reader input, final Writer branch, final boolean closeBranch) { super(input); this.branch = branch; this.closeBranch = closeBranch; } /** * Closes the proxied reader and, if so configured, the associated writer. An exception thrown from the reader will * not prevent closing of the writer. * * @throws IOException if either the reader or writer could not be closed */ @Override public void close() throws IOException { try { super.close(); } finally { if (closeBranch) { branch.close(); } } } /** * Reads a single character from the proxied reader and writes it to the associated writer. * * @return next character from the reader, or -1 if the reader has ended * @throws IOException if the reader could not be read (or written) */ @Override public int read() throws IOException { final int ch = super.read(); if (ch != EOF) { branch.write(ch); } return ch; } /** * Reads characters from the proxied reader and writes the read characters to the associated writer. * * @param chr character buffer * @return number of characters read, or -1 if the reader has ended * @throws IOException if the reader could not be read (or written) */ @Override public int read(final char[] chr) throws IOException { final int n = super.read(chr); if (n != EOF) { branch.write(chr, 0, n); } return n; } /** * Reads characters from the proxied reader and writes the read characters to the associated writer. * * @param chr character buffer * @param st start offset within the buffer * @param end maximum number of characters to read * @return number of characters read, or -1 if the reader has ended * @throws IOException if the reader could not be read (or written) */ @Override public int read(final char[] chr, final int st, final int end) throws IOException { final int n = super.read(chr, st, end); if (n != EOF) { branch.write(chr, st, n); } return n; } /** * Reads characters from the proxied reader and writes the read characters to the associated writer. * * @param target character buffer * @return number of characters read, or -1 if the reader has ended * @throws IOException if the reader could not be read (or written) */ @Override public int read(final CharBuffer target) throws IOException { final int originalPosition = target.position(); final int n = super.read(target); if (n != EOF) { // Appending can only be done after resetting the CharBuffer to the // right position and limit. final int newPosition = target.position(); final int newLimit = target.limit(); try { target.position(originalPosition).limit(newPosition); branch.append(target); } finally { // Reset the CharBuffer as if the appending never happened. target.position(newPosition).limit(newLimit); } } return n; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/TimestampedObserver.java0100644 0000000 0000000 00000005255 13612062727 031530 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import java.io.IOException; import java.time.Duration; import java.time.Instant; import org.apache.commons.io.input.ObservableInputStream.Observer; /** * An observer with timestamps. *

* For example: *

* *
 * final TimestampedObserver timetampedObserver = new TimestampedObserver();
 * try (final ObservableInputStream inputStream = new ObservableInputStream(...),
 *     timetampedObserver)) {
 *     ...
 * }
 * System.out.printf("IO duration: %s%n", timetampedObserver.getOpenToCloseDuration());
 * 
* * @since 2.9.0 */ public class TimestampedObserver extends Observer { private volatile Instant closeInstant; private final Instant openInstant = Instant.now(); @Override public void closed() throws IOException { closeInstant = Instant.now(); } /** * Gets the instant for when this instance was closed. * * @return the instant for when closed was called. */ public Instant getCloseInstant() { return closeInstant; } /** * Gets the Duration between creation and close. * * @return the Duration between creation and close. */ public Duration getOpenToCloseDuration() { return Duration.between(openInstant, closeInstant); } /** * Gets the Duration between creation and now. * * @return the Duration between creation and now. */ public Duration getOpenToNowDuration() { return Duration.between(openInstant, Instant.now()); } /** * Gets the instant for when this instance was created. * * @return the instant for when this instance was created. */ public Instant getOpenInstant() { return openInstant; } @Override public String toString() { return "TimestampedObserver [openInstant=" + openInstant + ", closeInstant=" + closeInstant + "]"; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/UnixLineEndingInputStream.java0100644 0000000 0000000 00000007214 13612062727 032615 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.apache.commons.io.IOUtils.CR; import static org.apache.commons.io.IOUtils.EOF; import static org.apache.commons.io.IOUtils.LF; import java.io.IOException; import java.io.InputStream; /** * A filtering input stream that ensures the content will have UNIX-style line endings, LF. * * @since 2.5 */ public class UnixLineEndingInputStream extends InputStream { private boolean slashNSeen; private boolean slashRSeen; private boolean eofSeen; private final InputStream target; private final boolean ensureLineFeedAtEndOfFile; /** * Creates an input stream that filters another stream * * @param in The input stream to wrap * @param ensureLineFeedAtEndOfFile true to ensure that the file ends with LF */ public UnixLineEndingInputStream(final InputStream in, final boolean ensureLineFeedAtEndOfFile) { this.target = in; this.ensureLineFeedAtEndOfFile = ensureLineFeedAtEndOfFile; } /** * Reads the next item from the target, updating internal flags in the process * @return the next int read from the target stream * @throws IOException upon error */ private int readWithUpdate() throws IOException { final int target = this.target.read(); eofSeen = target == EOF; if (eofSeen) { return target; } slashNSeen = target == LF; slashRSeen = target == CR; return target; } /** * {@inheritDoc} */ @Override public int read() throws IOException { final boolean previousWasSlashR = slashRSeen; if (eofSeen) { return eofGame(previousWasSlashR); } final int target = readWithUpdate(); if (eofSeen) { return eofGame(previousWasSlashR); } if (slashRSeen) { return LF; } if (previousWasSlashR && slashNSeen) { return read(); } return target; } /** * Handles the EOF-handling at the end of the stream * @param previousWasSlashR Indicates if the last seen was a \r * @return The next char to output to the stream */ private int eofGame(final boolean previousWasSlashR) { if (previousWasSlashR || !ensureLineFeedAtEndOfFile) { return EOF; } if (!slashNSeen) { slashNSeen = true; return LF; } return EOF; } /** * Closes the stream. Also closes the underlying stream. * @throws IOException upon error */ @Override public void close() throws IOException { super.close(); target.close(); } /** * {@inheritDoc} */ @Override public synchronized void mark(final int readlimit) { throw UnsupportedOperationExceptions.mark(); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/UnsupportedOperationExceptions.java0100644 0000000 0000000 00000004401 13612062727 034007 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; /** * Package-private factory for {@link UnsupportedOperationException} to provide messages with consistent formatting. * *

* TODO Consider making this public and use from LineIterator but this feels like it belongs in LANG rather than IO. *

*/ class UnsupportedOperationExceptions { private static final String MARK_RESET = "mark/reset"; /** * Creates a new instance of UnsupportedOperationException for a {@code mark} method. * * @return a new instance of UnsupportedOperationException */ static UnsupportedOperationException mark() { // Use the same message as in java.io.InputStream.reset() in OpenJDK 8.0.275-1. return method(MARK_RESET); } /** * Creates a new instance of UnsupportedOperationException for the given unsupported a {@code method} name. * * @param method A method name * @return a new instance of UnsupportedOperationException */ static UnsupportedOperationException method(final String method) { return new UnsupportedOperationException(method + " not supported"); } /** * Creates a new instance of UnsupportedOperationException for a {@code reset} method. * * @return a new instance of UnsupportedOperationException */ static UnsupportedOperationException reset() { // Use the same message as in java.io.InputStream.reset() in OpenJDK 8.0.275-1. return method(MARK_RESET); } } ././@LongLink0100644 0000000 0000000 00000000150 13612062727 011635 Lustar 0000000 0000000 commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/UnsynchronizedByteArrayInputStream.javacommons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/UnsynchronizedByteArrayInputStream.j0100644 0000000 0000000 00000012146 13612062727 034112 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import java.io.InputStream; import java.util.Objects; import static java.lang.Math.min; /** * This is an alternative to {@link java.io.ByteArrayInputStream} * which removes the synchronization overhead for non-concurrent * access; as such this class is not thread-safe. * * @since 2.7 */ //@NotThreadSafe public class UnsynchronizedByteArrayInputStream extends InputStream { /** * The end of stream marker. */ public static final int END_OF_STREAM = -1; /** * The underlying data buffer. */ private final byte[] data; /** * End Of Data. * * Similar to data.length, * i.e. the last readable offset + 1. */ private final int eod; /** * Current offset in the data buffer. */ private int offset; /** * The current mark (if any). */ private int markedOffset; /** * Creates a new byte array input stream. * * @param data the buffer */ public UnsynchronizedByteArrayInputStream(final byte[] data) { this.data = Objects.requireNonNull(data, "data"); this.offset = 0; this.eod = data.length; this.markedOffset = this.offset; } /** * Creates a new byte array input stream. * * @param data the buffer * @param offset the offset into the buffer * * @throws IllegalArgumentException if the offset is less than zero */ public UnsynchronizedByteArrayInputStream(final byte[] data, final int offset) { Objects.requireNonNull(data, "data"); if (offset < 0) { throw new IllegalArgumentException("offset cannot be negative"); } this.data = data; this.offset = min(offset, data.length > 0 ? data.length : offset); this.eod = data.length; this.markedOffset = this.offset; } /** * Creates a new byte array input stream. * * @param data the buffer * @param offset the offset into the buffer * @param length the length of the buffer * * @throws IllegalArgumentException if the offset or length less than zero */ public UnsynchronizedByteArrayInputStream(final byte[] data, final int offset, final int length) { if (offset < 0) { throw new IllegalArgumentException("offset cannot be negative"); } if (length < 0) { throw new IllegalArgumentException("length cannot be negative"); } this.data = Objects.requireNonNull(data, "data"); this.offset = min(offset, data.length > 0 ? data.length : offset); this.eod = min(this.offset + length, data.length); this.markedOffset = this.offset; } @Override public int available() { return offset < eod ? eod - offset : 0; } @Override public int read() { return offset < eod ? data[offset++] & 0xff : END_OF_STREAM; } @Override public int read(final byte[] dest) { Objects.requireNonNull(dest, "dest"); return read(dest, 0, dest.length); } @Override public int read(final byte[] dest, final int off, final int len) { Objects.requireNonNull(dest, "dest"); if (off < 0 || len < 0 || off + len > dest.length) { throw new IndexOutOfBoundsException(); } if (offset >= eod) { return END_OF_STREAM; } int actualLen = eod - offset; if (len < actualLen) { actualLen = len; } if (actualLen <= 0) { return 0; } System.arraycopy(data, offset, dest, off, actualLen); offset += actualLen; return actualLen; } @Override public long skip(final long n) { if (n < 0) { throw new IllegalArgumentException("Skipping backward is not supported"); } long actualSkip = eod - offset; if (n < actualSkip) { actualSkip = n; } offset += actualSkip; return actualSkip; } @Override public boolean markSupported() { return true; } @SuppressWarnings("sync-override") @Override public void mark(final int readlimit) { this.markedOffset = this.offset; } @SuppressWarnings("sync-override") @Override public void reset() { this.offset = this.markedOffset; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/WindowsLineEndingInputStream.java0100644 0000000 0000000 00000007343 13612062727 033327 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.apache.commons.io.IOUtils.CR; import static org.apache.commons.io.IOUtils.EOF; import static org.apache.commons.io.IOUtils.LF; import java.io.IOException; import java.io.InputStream; /** * A filtering input stream that ensures the content will have Windows line endings, CRLF. * * @since 2.5 */ public class WindowsLineEndingInputStream extends InputStream { private boolean slashRSeen; private boolean slashNSeen; private boolean injectSlashN; private boolean eofSeen; private final InputStream target; private final boolean ensureLineFeedAtEndOfFile; /** * Creates an input stream that filters another stream * * @param in The input stream to wrap * @param ensureLineFeedAtEndOfFile true to ensure that the file ends with CRLF */ public WindowsLineEndingInputStream(final InputStream in, final boolean ensureLineFeedAtEndOfFile) { this.target = in; this.ensureLineFeedAtEndOfFile = ensureLineFeedAtEndOfFile; } /** * Reads the next item from the target, updating internal flags in the process * @return the next int read from the target stream * @throws IOException upon error */ private int readWithUpdate() throws IOException { final int target = this.target.read(); eofSeen = target == EOF; if (eofSeen) { return target; } slashRSeen = target == CR; slashNSeen = target == LF; return target; } /** * {@inheritDoc} */ @Override public int read() throws IOException { if (eofSeen) { return eofGame(); } if (injectSlashN) { injectSlashN = false; return LF; } final boolean prevWasSlashR = slashRSeen; final int target = readWithUpdate(); if (eofSeen) { return eofGame(); } if ((target == LF) && !prevWasSlashR) { injectSlashN = true; return CR; } return target; } /** * Handles the EOF-handling at the end of the stream * @return The next char to output to the stream */ private int eofGame() { if (!ensureLineFeedAtEndOfFile) { return EOF; } if (!slashNSeen && !slashRSeen) { slashRSeen = true; return CR; } if (!slashNSeen) { slashRSeen = false; slashNSeen = true; return LF; } return EOF; } /** * Closes the stream. Also closes the underlying stream. * @throws IOException upon error */ @Override public void close() throws IOException { super.close(); target.close(); } /** * {@inheritDoc} */ @Override public synchronized void mark(final int readlimit) { throw UnsupportedOperationExceptions.mark(); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/XmlStreamReader.java0100644 0000000 0000000 00000102064 13612062727 030577 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.io.StringReader; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLConnection; import java.nio.file.Files; import java.nio.file.Path; import java.text.MessageFormat; import java.util.Locale; import java.util.Objects; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.commons.io.ByteOrderMark; import org.apache.commons.io.IOUtils; /** * Character stream that handles all the necessary Voodoo to figure out the * charset encoding of the XML document within the stream. *

* IMPORTANT: This class is not related in any way to the org.xml.sax.XMLReader. * This one IS a character stream. *

*

* All this has to be done without consuming characters from the stream, if not * the XML parser will not recognized the document as a valid XML. This is not * 100% true, but it's close enough (UTF-8 BOM is not handled by all parsers * right now, XmlStreamReader handles it and things work in all parsers). *

*

* The XmlStreamReader class handles the charset encoding of XML documents in * Files, raw streams and HTTP streams by offering a wide set of constructors. *

*

* By default the charset encoding detection is lenient, the constructor with * the lenient flag can be used for a script (following HTTP MIME and XML * specifications). All this is nicely explained by Mark Pilgrim in his blog, * Determining the character encoding of a feed. *

*

* Originally developed for ROME under * Apache License 2.0. *

* * @see org.apache.commons.io.output.XmlStreamWriter * @since 2.0 */ public class XmlStreamReader extends Reader { private static final String UTF_8 = "UTF-8"; private static final String US_ASCII = "US-ASCII"; private static final String UTF_16BE = "UTF-16BE"; private static final String UTF_16LE = "UTF-16LE"; private static final String UTF_32BE = "UTF-32BE"; private static final String UTF_32LE = "UTF-32LE"; private static final String UTF_16 = "UTF-16"; private static final String UTF_32 = "UTF-32"; private static final String EBCDIC = "CP1047"; private static final ByteOrderMark[] BOMS = { ByteOrderMark.UTF_8, ByteOrderMark.UTF_16BE, ByteOrderMark.UTF_16LE, ByteOrderMark.UTF_32BE, ByteOrderMark.UTF_32LE }; // UTF_16LE and UTF_32LE have the same two starting BOM bytes. private static final ByteOrderMark[] XML_GUESS_BYTES = { new ByteOrderMark(UTF_8, 0x3C, 0x3F, 0x78, 0x6D), new ByteOrderMark(UTF_16BE, 0x00, 0x3C, 0x00, 0x3F), new ByteOrderMark(UTF_16LE, 0x3C, 0x00, 0x3F, 0x00), new ByteOrderMark(UTF_32BE, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x6D), new ByteOrderMark(UTF_32LE, 0x3C, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x6D, 0x00, 0x00, 0x00), new ByteOrderMark(EBCDIC, 0x4C, 0x6F, 0xA7, 0x94) }; private static final Pattern CHARSET_PATTERN = Pattern .compile("charset=[\"']?([.[^; \"']]*)[\"']?"); /** * Pattern capturing the encoding of the "xml" processing instruction. */ public static final Pattern ENCODING_PATTERN = Pattern.compile( "<\\?xml.*encoding[\\s]*=[\\s]*((?:\".[^\"]*\")|(?:'.[^']*'))", Pattern.MULTILINE); private static final String RAW_EX_1 = "Invalid encoding, BOM [{0}] XML guess [{1}] XML prolog [{2}] encoding mismatch"; private static final String RAW_EX_2 = "Invalid encoding, BOM [{0}] XML guess [{1}] XML prolog [{2}] unknown BOM"; private static final String HTTP_EX_1 = "Invalid encoding, CT-MIME [{0}] CT-Enc [{1}] BOM [{2}] XML guess [{3}] XML prolog [{4}], BOM must be NULL"; private static final String HTTP_EX_2 = "Invalid encoding, CT-MIME [{0}] CT-Enc [{1}] BOM [{2}] XML guess [{3}] XML prolog [{4}], encoding mismatch"; private static final String HTTP_EX_3 = "Invalid encoding, CT-MIME [{0}] CT-Enc [{1}] BOM [{2}] XML guess [{3}] XML prolog [{4}], Invalid MIME"; /** * Returns charset parameter value, NULL if not present, NULL if * httpContentType is NULL. * * @param httpContentType the HTTP content type * @return The content type encoding (upcased) */ static String getContentTypeEncoding(final String httpContentType) { String encoding = null; if (httpContentType != null) { final int i = httpContentType.indexOf(";"); if (i > -1) { final String postMime = httpContentType.substring(i + 1); final Matcher m = CHARSET_PATTERN.matcher(postMime); encoding = m.find() ? m.group(1) : null; encoding = encoding != null ? encoding.toUpperCase(Locale.ROOT) : null; } } return encoding; } /** * Returns MIME type or NULL if httpContentType is NULL. * * @param httpContentType the HTTP content type * @return The mime content type */ static String getContentTypeMime(final String httpContentType) { String mime = null; if (httpContentType != null) { final int i = httpContentType.indexOf(";"); if (i >= 0) { mime = httpContentType.substring(0, i); } else { mime = httpContentType; } mime = mime.trim(); } return mime; } /** * Returns the encoding declared in the , NULL if none. * * @param inputStream InputStream to create the reader from. * @param guessedEnc guessed encoding * @return the encoding declared in the * @throws IOException thrown if there is a problem reading the stream. */ private static String getXmlProlog(final InputStream inputStream, final String guessedEnc) throws IOException { String encoding = null; if (guessedEnc != null) { final byte[] bytes = IOUtils.byteArray(); inputStream.mark(IOUtils.DEFAULT_BUFFER_SIZE); int offset = 0; int max = IOUtils.DEFAULT_BUFFER_SIZE; int c = inputStream.read(bytes, offset, max); int firstGT = -1; String xmlProlog = ""; // avoid possible NPE warning (cannot happen; this just silences the warning) while (c != -1 && firstGT == -1 && offset < IOUtils.DEFAULT_BUFFER_SIZE) { offset += c; max -= c; c = inputStream.read(bytes, offset, max); xmlProlog = new String(bytes, 0, offset, guessedEnc); firstGT = xmlProlog.indexOf('>'); } if (firstGT == -1) { if (c == -1) { throw new IOException("Unexpected end of XML stream"); } throw new IOException( "XML prolog or ROOT element not found on first " + offset + " bytes"); } final int bytesRead = offset; if (bytesRead > 0) { inputStream.reset(); final BufferedReader bReader = new BufferedReader(new StringReader( xmlProlog.substring(0, firstGT + 1))); final StringBuffer prolog = new StringBuffer(); String line; while ((line = bReader.readLine()) != null) { prolog.append(line); } final Matcher m = ENCODING_PATTERN.matcher(prolog); if (m.find()) { encoding = m.group(1).toUpperCase(Locale.ROOT); encoding = encoding.substring(1, encoding.length() - 1); } } } return encoding; } /** * Indicates if the MIME type belongs to the APPLICATION XML family. * * @param mime The mime type * @return true if the mime type belongs to the APPLICATION XML family, * otherwise false */ static boolean isAppXml(final String mime) { return mime != null && (mime.equals("application/xml") || mime.equals("application/xml-dtd") || mime.equals("application/xml-external-parsed-entity") || mime.startsWith("application/") && mime.endsWith("+xml")); } /** * Indicates if the MIME type belongs to the TEXT XML family. * * @param mime The mime type * @return true if the mime type belongs to the TEXT XML family, * otherwise false */ static boolean isTextXml(final String mime) { return mime != null && (mime.equals("text/xml") || mime.equals("text/xml-external-parsed-entity") || mime.startsWith("text/") && mime.endsWith("+xml")); } private final Reader reader; private final String encoding; private final String defaultEncoding; /** * Creates a Reader for a File. *

* It looks for the UTF-8 BOM first, if none sniffs the XML prolog charset, * if this is also missing defaults to UTF-8. *

* It does a lenient charset encoding detection, check the constructor with * the lenient parameter for details. * * @param file File to create a Reader from. * @throws IOException thrown if there is a problem reading the file. */ public XmlStreamReader(final File file) throws IOException { this(Objects.requireNonNull(file, "file").toPath()); } /** * Creates a Reader for a raw InputStream. *

* It follows the same logic used for files. *

* It does a lenient charset encoding detection, check the constructor with * the lenient parameter for details. * * @param inputStream InputStream to create a Reader from. * @throws IOException thrown if there is a problem reading the stream. */ public XmlStreamReader(final InputStream inputStream) throws IOException { this(inputStream, true); } /** * Creates a Reader for a raw InputStream. *

* It follows the same logic used for files. *

* If lenient detection is indicated and the detection above fails as per * specifications it then attempts the following: *

* If the content type was 'text/html' it replaces it with 'text/xml' and * tries the detection again. *

* Else if the XML prolog had a charset encoding that encoding is used. *

* Else if the content type had a charset encoding that encoding is used. *

* Else 'UTF-8' is used. *

* If lenient detection is indicated an XmlStreamReaderException is never * thrown. * * @param inputStream InputStream to create a Reader from. * @param lenient indicates if the charset encoding detection should be * relaxed. * @throws IOException thrown if there is a problem reading the stream. * @throws XmlStreamReaderException thrown if the charset encoding could not * be determined according to the specs. */ public XmlStreamReader(final InputStream inputStream, final boolean lenient) throws IOException { this(inputStream, lenient, null); } /** * Creates a Reader for a raw InputStream. *

* It follows the same logic used for files. *

* If lenient detection is indicated and the detection above fails as per * specifications it then attempts the following: *

* If the content type was 'text/html' it replaces it with 'text/xml' and * tries the detection again. *

* Else if the XML prolog had a charset encoding that encoding is used. *

* Else if the content type had a charset encoding that encoding is used. *

* Else 'UTF-8' is used. *

* If lenient detection is indicated an XmlStreamReaderException is never * thrown. * * @param inputStream InputStream to create a Reader from. * @param lenient indicates if the charset encoding detection should be * relaxed. * @param defaultEncoding The default encoding * @throws IOException thrown if there is a problem reading the stream. * @throws XmlStreamReaderException thrown if the charset encoding could not * be determined according to the specs. */ @SuppressWarnings("resource") // InputStream is managed through a InputStreamReader in this instance. public XmlStreamReader(final InputStream inputStream, final boolean lenient, final String defaultEncoding) throws IOException { Objects.requireNonNull(inputStream, "inputStream"); this.defaultEncoding = defaultEncoding; final BOMInputStream bom = new BOMInputStream(new BufferedInputStream(inputStream, IOUtils.DEFAULT_BUFFER_SIZE), false, BOMS); final BOMInputStream pis = new BOMInputStream(bom, true, XML_GUESS_BYTES); this.encoding = doRawStream(bom, pis, lenient); this.reader = new InputStreamReader(pis, encoding); } /** * Creates a Reader using an InputStream and the associated content-type * header. *

* First it checks if the stream has BOM. If there is not BOM checks the * content-type encoding. If there is not content-type encoding checks the * XML prolog encoding. If there is not XML prolog encoding uses the default * encoding mandated by the content-type MIME type. *

* It does a lenient charset encoding detection, check the constructor with * the lenient parameter for details. * * @param inputStream InputStream to create the reader from. * @param httpContentType content-type header to use for the resolution of * the charset encoding. * @throws IOException thrown if there is a problem reading the file. */ public XmlStreamReader(final InputStream inputStream, final String httpContentType) throws IOException { this(inputStream, httpContentType, true); } /** * Creates a Reader using an InputStream and the associated content-type * header. This constructor is lenient regarding the encoding detection. *

* First it checks if the stream has BOM. If there is not BOM checks the * content-type encoding. If there is not content-type encoding checks the * XML prolog encoding. If there is not XML prolog encoding uses the default * encoding mandated by the content-type MIME type. *

* If lenient detection is indicated and the detection above fails as per * specifications it then attempts the following: *

* If the content type was 'text/html' it replaces it with 'text/xml' and * tries the detection again. *

* Else if the XML prolog had a charset encoding that encoding is used. *

* Else if the content type had a charset encoding that encoding is used. *

* Else 'UTF-8' is used. *

* If lenient detection is indicated an XmlStreamReaderException is never * thrown. * * @param inputStream InputStream to create the reader from. * @param httpContentType content-type header to use for the resolution of * the charset encoding. * @param lenient indicates if the charset encoding detection should be * relaxed. * @throws IOException thrown if there is a problem reading the file. * @throws XmlStreamReaderException thrown if the charset encoding could not * be determined according to the specs. */ public XmlStreamReader(final InputStream inputStream, final String httpContentType, final boolean lenient) throws IOException { this(inputStream, httpContentType, lenient, null); } /** * Creates a Reader using an InputStream and the associated content-type * header. This constructor is lenient regarding the encoding detection. *

* First it checks if the stream has BOM. If there is not BOM checks the * content-type encoding. If there is not content-type encoding checks the * XML prolog encoding. If there is not XML prolog encoding uses the default * encoding mandated by the content-type MIME type. *

* If lenient detection is indicated and the detection above fails as per * specifications it then attempts the following: *

* If the content type was 'text/html' it replaces it with 'text/xml' and * tries the detection again. *

* Else if the XML prolog had a charset encoding that encoding is used. *

* Else if the content type had a charset encoding that encoding is used. *

* Else 'UTF-8' is used. *

* If lenient detection is indicated an XmlStreamReaderException is never * thrown. * * @param inputStream InputStream to create the reader from. * @param httpContentType content-type header to use for the resolution of * the charset encoding. * @param lenient indicates if the charset encoding detection should be * relaxed. * @param defaultEncoding The default encoding * @throws IOException thrown if there is a problem reading the file. * @throws XmlStreamReaderException thrown if the charset encoding could not * be determined according to the specs. */ @SuppressWarnings("resource") // InputStream is managed through a InputStreamReader in this instance. public XmlStreamReader(final InputStream inputStream, final String httpContentType, final boolean lenient, final String defaultEncoding) throws IOException { Objects.requireNonNull(inputStream, "inputStream"); this.defaultEncoding = defaultEncoding; final BOMInputStream bom = new BOMInputStream(new BufferedInputStream(inputStream, IOUtils.DEFAULT_BUFFER_SIZE), false, BOMS); final BOMInputStream pis = new BOMInputStream(bom, true, XML_GUESS_BYTES); this.encoding = processHttpStream(bom, pis, httpContentType, lenient); this.reader = new InputStreamReader(pis, encoding); } /** * Creates a Reader for a File. *

* It looks for the UTF-8 BOM first, if none sniffs the XML prolog charset, * if this is also missing defaults to UTF-8. *

* It does a lenient charset encoding detection, check the constructor with * the lenient parameter for details. * * @param file File to create a Reader from. * @throws IOException thrown if there is a problem reading the file. * @since 2.11.0 */ @SuppressWarnings("resource") // InputStream is managed through another reader in this instance. public XmlStreamReader(final Path file) throws IOException { this(Files.newInputStream(Objects.requireNonNull(file, "file"))); } /** * Creates a Reader using the InputStream of a URL. *

* If the URL is not of type HTTP and there is not 'content-type' header in * the fetched data it uses the same logic used for Files. *

* If the URL is a HTTP Url or there is a 'content-type' header in the * fetched data it uses the same logic used for an InputStream with * content-type. *

* It does a lenient charset encoding detection, check the constructor with * the lenient parameter for details. * * @param url URL to create a Reader from. * @throws IOException thrown if there is a problem reading the stream of * the URL. */ public XmlStreamReader(final URL url) throws IOException { this(Objects.requireNonNull(url, "url").openConnection(), null); } /** * Creates a Reader using the InputStream of a URLConnection. *

* If the URLConnection is not of type HttpURLConnection and there is not * 'content-type' header in the fetched data it uses the same logic used for * files. *

* If the URLConnection is a HTTP Url or there is a 'content-type' header in * the fetched data it uses the same logic used for an InputStream with * content-type. *

* It does a lenient charset encoding detection, check the constructor with * the lenient parameter for details. * * @param conn URLConnection to create a Reader from. * @param defaultEncoding The default encoding * @throws IOException thrown if there is a problem reading the stream of * the URLConnection. */ public XmlStreamReader(final URLConnection conn, final String defaultEncoding) throws IOException { Objects.requireNonNull(conn, "conn"); this.defaultEncoding = defaultEncoding; final boolean lenient = true; final String contentType = conn.getContentType(); final InputStream inputStream = conn.getInputStream(); @SuppressWarnings("resource") // managed by the InputStreamReader tracked by this instance final BOMInputStream bom = new BOMInputStream(new BufferedInputStream(inputStream, IOUtils.DEFAULT_BUFFER_SIZE), false, BOMS); final BOMInputStream pis = new BOMInputStream(bom, true, XML_GUESS_BYTES); if (conn instanceof HttpURLConnection || contentType != null) { this.encoding = processHttpStream(bom, pis, contentType, lenient); } else { this.encoding = doRawStream(bom, pis, lenient); } this.reader = new InputStreamReader(pis, encoding); } /** * Calculate the HTTP encoding. * * @param httpContentType The HTTP content type * @param bomEnc BOM encoding * @param xmlGuessEnc XML Guess encoding * @param xmlEnc XML encoding * @param lenient indicates if the charset encoding detection should be * relaxed. * @return the HTTP encoding * @throws IOException thrown if there is a problem reading the stream. */ String calculateHttpEncoding(final String httpContentType, final String bomEnc, final String xmlGuessEnc, final String xmlEnc, final boolean lenient) throws IOException { // Lenient and has XML encoding if (lenient && xmlEnc != null) { return xmlEnc; } // Determine mime/encoding content types from HTTP Content Type final String cTMime = getContentTypeMime(httpContentType); final String cTEnc = getContentTypeEncoding(httpContentType); final boolean appXml = isAppXml(cTMime); final boolean textXml = isTextXml(cTMime); // Mime type NOT "application/xml" or "text/xml" if (!appXml && !textXml) { final String msg = MessageFormat.format(HTTP_EX_3, cTMime, cTEnc, bomEnc, xmlGuessEnc, xmlEnc); throw new XmlStreamReaderException(msg, cTMime, cTEnc, bomEnc, xmlGuessEnc, xmlEnc); } // No content type encoding if (cTEnc == null) { if (appXml) { return calculateRawEncoding(bomEnc, xmlGuessEnc, xmlEnc); } return defaultEncoding == null ? US_ASCII : defaultEncoding; } // UTF-16BE or UTF-16LE content type encoding if (cTEnc.equals(UTF_16BE) || cTEnc.equals(UTF_16LE)) { if (bomEnc != null) { final String msg = MessageFormat.format(HTTP_EX_1, cTMime, cTEnc, bomEnc, xmlGuessEnc, xmlEnc); throw new XmlStreamReaderException(msg, cTMime, cTEnc, bomEnc, xmlGuessEnc, xmlEnc); } return cTEnc; } // UTF-16 content type encoding if (cTEnc.equals(UTF_16)) { if (bomEnc != null && bomEnc.startsWith(UTF_16)) { return bomEnc; } final String msg = MessageFormat.format(HTTP_EX_2, cTMime, cTEnc, bomEnc, xmlGuessEnc, xmlEnc); throw new XmlStreamReaderException(msg, cTMime, cTEnc, bomEnc, xmlGuessEnc, xmlEnc); } // UTF-32BE or UTF-132E content type encoding if (cTEnc.equals(UTF_32BE) || cTEnc.equals(UTF_32LE)) { if (bomEnc != null) { final String msg = MessageFormat.format(HTTP_EX_1, cTMime, cTEnc, bomEnc, xmlGuessEnc, xmlEnc); throw new XmlStreamReaderException(msg, cTMime, cTEnc, bomEnc, xmlGuessEnc, xmlEnc); } return cTEnc; } // UTF-32 content type encoding if (cTEnc.equals(UTF_32)) { if (bomEnc != null && bomEnc.startsWith(UTF_32)) { return bomEnc; } final String msg = MessageFormat.format(HTTP_EX_2, cTMime, cTEnc, bomEnc, xmlGuessEnc, xmlEnc); throw new XmlStreamReaderException(msg, cTMime, cTEnc, bomEnc, xmlGuessEnc, xmlEnc); } return cTEnc; } /** * Calculate the raw encoding. * * @param bomEnc BOM encoding * @param xmlGuessEnc XML Guess encoding * @param xmlEnc XML encoding * @return the raw encoding * @throws IOException thrown if there is a problem reading the stream. */ String calculateRawEncoding(final String bomEnc, final String xmlGuessEnc, final String xmlEnc) throws IOException { // BOM is Null if (bomEnc == null) { if (xmlGuessEnc == null || xmlEnc == null) { return defaultEncoding == null ? UTF_8 : defaultEncoding; } if (xmlEnc.equals(UTF_16) && (xmlGuessEnc.equals(UTF_16BE) || xmlGuessEnc.equals(UTF_16LE))) { return xmlGuessEnc; } return xmlEnc; } // BOM is UTF-8 if (bomEnc.equals(UTF_8)) { if (xmlGuessEnc != null && !xmlGuessEnc.equals(UTF_8)) { final String msg = MessageFormat.format(RAW_EX_1, bomEnc, xmlGuessEnc, xmlEnc); throw new XmlStreamReaderException(msg, bomEnc, xmlGuessEnc, xmlEnc); } if (xmlEnc != null && !xmlEnc.equals(UTF_8)) { final String msg = MessageFormat.format(RAW_EX_1, bomEnc, xmlGuessEnc, xmlEnc); throw new XmlStreamReaderException(msg, bomEnc, xmlGuessEnc, xmlEnc); } return bomEnc; } // BOM is UTF-16BE or UTF-16LE if (bomEnc.equals(UTF_16BE) || bomEnc.equals(UTF_16LE)) { if (xmlGuessEnc != null && !xmlGuessEnc.equals(bomEnc)) { final String msg = MessageFormat.format(RAW_EX_1, bomEnc, xmlGuessEnc, xmlEnc); throw new XmlStreamReaderException(msg, bomEnc, xmlGuessEnc, xmlEnc); } if (xmlEnc != null && !xmlEnc.equals(UTF_16) && !xmlEnc.equals(bomEnc)) { final String msg = MessageFormat.format(RAW_EX_1, bomEnc, xmlGuessEnc, xmlEnc); throw new XmlStreamReaderException(msg, bomEnc, xmlGuessEnc, xmlEnc); } return bomEnc; } // BOM is UTF-32BE or UTF-32LE if (bomEnc.equals(UTF_32BE) || bomEnc.equals(UTF_32LE)) { if (xmlGuessEnc != null && !xmlGuessEnc.equals(bomEnc)) { final String msg = MessageFormat.format(RAW_EX_1, bomEnc, xmlGuessEnc, xmlEnc); throw new XmlStreamReaderException(msg, bomEnc, xmlGuessEnc, xmlEnc); } if (xmlEnc != null && !xmlEnc.equals(UTF_32) && !xmlEnc.equals(bomEnc)) { final String msg = MessageFormat.format(RAW_EX_1, bomEnc, xmlGuessEnc, xmlEnc); throw new XmlStreamReaderException(msg, bomEnc, xmlGuessEnc, xmlEnc); } return bomEnc; } // BOM is something else final String msg = MessageFormat.format(RAW_EX_2, bomEnc, xmlGuessEnc, xmlEnc); throw new XmlStreamReaderException(msg, bomEnc, xmlGuessEnc, xmlEnc); } /** * Closes the XmlStreamReader stream. * * @throws IOException thrown if there was a problem closing the stream. */ @Override public void close() throws IOException { reader.close(); } /** * Do lenient detection. * * @param httpContentType content-type header to use for the resolution of * the charset encoding. * @param ex The thrown exception * @return the encoding * @throws IOException thrown if there is a problem reading the stream. */ private String doLenientDetection(String httpContentType, XmlStreamReaderException ex) throws IOException { if (httpContentType != null && httpContentType.startsWith("text/html")) { httpContentType = httpContentType.substring("text/html".length()); httpContentType = "text/xml" + httpContentType; try { return calculateHttpEncoding(httpContentType, ex.getBomEncoding(), ex.getXmlGuessEncoding(), ex.getXmlEncoding(), true); } catch (final XmlStreamReaderException ex2) { ex = ex2; } } String encoding = ex.getXmlEncoding(); if (encoding == null) { encoding = ex.getContentTypeEncoding(); } if (encoding == null) { encoding = defaultEncoding == null ? UTF_8 : defaultEncoding; } return encoding; } /** * Process the raw stream. * * @param bom BOMInputStream to detect byte order marks * @param pis BOMInputStream to guess XML encoding * @param lenient indicates if the charset encoding detection should be * relaxed. * @return the encoding to be used * @throws IOException thrown if there is a problem reading the stream. */ private String doRawStream(final BOMInputStream bom, final BOMInputStream pis, final boolean lenient) throws IOException { final String bomEnc = bom.getBOMCharsetName(); final String xmlGuessEnc = pis.getBOMCharsetName(); final String xmlEnc = getXmlProlog(pis, xmlGuessEnc); try { return calculateRawEncoding(bomEnc, xmlGuessEnc, xmlEnc); } catch (final XmlStreamReaderException ex) { if (lenient) { return doLenientDetection(null, ex); } throw ex; } } /** * Returns the default encoding to use if none is set in HTTP content-type, * XML prolog and the rules based on content-type are not adequate. *

* If it is NULL the content-type based rules are used. * * @return the default encoding to use. */ public String getDefaultEncoding() { return defaultEncoding; } /** * Returns the charset encoding of the XmlStreamReader. * * @return charset encoding. */ public String getEncoding() { return encoding; } /** * Process a HTTP stream. * * @param bom BOMInputStream to detect byte order marks * @param pis BOMInputStream to guess XML encoding * @param httpContentType The HTTP content type * @param lenient indicates if the charset encoding detection should be * relaxed. * @return the encoding to be used * @throws IOException thrown if there is a problem reading the stream. */ private String processHttpStream(final BOMInputStream bom, final BOMInputStream pis, final String httpContentType, final boolean lenient) throws IOException { final String bomEnc = bom.getBOMCharsetName(); final String xmlGuessEnc = pis.getBOMCharsetName(); final String xmlEnc = getXmlProlog(pis, xmlGuessEnc); try { return calculateHttpEncoding(httpContentType, bomEnc, xmlGuessEnc, xmlEnc, lenient); } catch (final XmlStreamReaderException ex) { if (lenient) { return doLenientDetection(httpContentType, ex); } throw ex; } } /** * Invokes the underlying reader's {@code read(char[], int, int)} method. * @param buf the buffer to read the characters into * @param offset The start offset * @param len The number of bytes to read * @return the number of characters read or -1 if the end of stream * @throws IOException if an I/O error occurs. */ @Override public int read(final char[] buf, final int offset, final int len) throws IOException { return reader.read(buf, offset, len); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/XmlStreamReaderException.java0100644 0000000 0000000 00000010723 13612062727 032456 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import java.io.IOException; /** * The XmlStreamReaderException is thrown by the XmlStreamReader constructors if * the charset encoding can not be determined according to the XML 1.0 * specification and RFC 3023. *

* The exception returns the unconsumed InputStream to allow the application to * do an alternate processing with the stream. Note that the original * InputStream given to the XmlStreamReader cannot be used as that one has been * already read. *

* * @since 2.0 */ public class XmlStreamReaderException extends IOException { private static final long serialVersionUID = 1L; private final String bomEncoding; private final String xmlGuessEncoding; private final String xmlEncoding; private final String contentTypeMime; private final String contentTypeEncoding; /** * Creates an exception instance if the charset encoding could not be * determined. *

* Instances of this exception are thrown by the XmlStreamReader. *

* * @param msg message describing the reason for the exception. * @param bomEnc BOM encoding. * @param xmlGuessEnc XML guess encoding. * @param xmlEnc XML prolog encoding. */ public XmlStreamReaderException(final String msg, final String bomEnc, final String xmlGuessEnc, final String xmlEnc) { this(msg, null, null, bomEnc, xmlGuessEnc, xmlEnc); } /** * Creates an exception instance if the charset encoding could not be * determined. *

* Instances of this exception are thrown by the XmlStreamReader. *

* * @param msg message describing the reason for the exception. * @param ctMime MIME type in the content-type. * @param ctEnc encoding in the content-type. * @param bomEnc BOM encoding. * @param xmlGuessEnc XML guess encoding. * @param xmlEnc XML prolog encoding. */ public XmlStreamReaderException(final String msg, final String ctMime, final String ctEnc, final String bomEnc, final String xmlGuessEnc, final String xmlEnc) { super(msg); contentTypeMime = ctMime; contentTypeEncoding = ctEnc; bomEncoding = bomEnc; xmlGuessEncoding = xmlGuessEnc; xmlEncoding = xmlEnc; } /** * Returns the BOM encoding found in the InputStream. * * @return the BOM encoding, null if none. */ public String getBomEncoding() { return bomEncoding; } /** * Returns the encoding guess based on the first bytes of the InputStream. * * @return the encoding guess, null if it couldn't be guessed. */ public String getXmlGuessEncoding() { return xmlGuessEncoding; } /** * Returns the encoding found in the XML prolog of the InputStream. * * @return the encoding of the XML prolog, null if none. */ public String getXmlEncoding() { return xmlEncoding; } /** * Returns the MIME type in the content-type used to attempt determining the * encoding. * * @return the MIME type in the content-type, null if there was not * content-type or the encoding detection did not involve HTTP. */ public String getContentTypeMime() { return contentTypeMime; } /** * Returns the encoding in the content-type used to attempt determining the * encoding. * * @return the encoding in the content-type, null if there was not * content-type, no encoding in it or the encoding detection did not * involve HTTP. */ public String getContentTypeEncoding() { return contentTypeEncoding; } } ././@LongLink0100644 0000000 0000000 00000000146 13612062727 011642 Lustar 0000000 0000000 commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/buffer/CircularBufferInputStream.javacommons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/buffer/CircularBufferInputStream.jav0100644 0000000 0000000 00000011670 13612062727 033744 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input.buffer; import static org.apache.commons.io.IOUtils.EOF; import java.io.IOException; import java.io.InputStream; import java.util.Objects; import org.apache.commons.io.IOUtils; /** * Implements a buffered input stream, which is internally based on a {@link CircularByteBuffer}. Unlike the * {@link java.io.BufferedInputStream}, this one doesn't need to reallocate byte arrays internally. */ public class CircularBufferInputStream extends InputStream { /** What we are streaming, used to fill the internal buffer. */ protected final InputStream in; /** Internal buffer. */ protected final CircularByteBuffer buffer; /** Internal buffer size. */ protected final int bufferSize; /** Whether we've see the input stream EOF. */ private boolean eof; /** * Creates a new instance, which filters the given input stream, and uses the given buffer size. * * @param inputStream The input stream, which is being buffered. * @param bufferSize The size of the {@link CircularByteBuffer}, which is used internally. */ public CircularBufferInputStream(final InputStream inputStream, final int bufferSize) { if (bufferSize <= 0) { throw new IllegalArgumentException("Invalid bufferSize: " + bufferSize); } this.in = Objects.requireNonNull(inputStream, "inputStream"); this.buffer = new CircularByteBuffer(bufferSize); this.bufferSize = bufferSize; this.eof = false; } /** * Creates a new instance, which filters the given input stream, and uses a reasonable default buffer size * ({@link IOUtils#DEFAULT_BUFFER_SIZE}). * * @param inputStream The input stream, which is being buffered. */ public CircularBufferInputStream(final InputStream inputStream) { this(inputStream, IOUtils.DEFAULT_BUFFER_SIZE); } /** * Fills the buffer with the contents of the input stream. * * @throws IOException in case of an error while reading from the input stream. */ protected void fillBuffer() throws IOException { if (eof) { return; } int space = buffer.getSpace(); final byte[] buf = IOUtils.byteArray(space); while (space > 0) { final int res = in.read(buf, 0, space); if (res == EOF) { eof = true; return; } if (res > 0) { buffer.add(buf, 0, res); space -= res; } } } /** * Fills the buffer from the input stream until the given number of bytes have been added to the buffer. * * @param count number of byte to fill into the buffer * @return true if the buffer has bytes * @throws IOException in case of an error while reading from the input stream. */ protected boolean haveBytes(final int count) throws IOException { if (buffer.getCurrentNumberOfBytes() < count) { fillBuffer(); } return buffer.hasBytes(); } @Override public int read() throws IOException { if (!haveBytes(1)) { return EOF; } return buffer.read() & 0xFF; // return unsigned byte } @Override public int read(final byte[] buffer) throws IOException { return read(buffer, 0, buffer.length); } @Override public int read(final byte[] targetBuffer, final int offset, final int length) throws IOException { Objects.requireNonNull(targetBuffer, "targetBuffer"); if (offset < 0) { throw new IllegalArgumentException("Offset must not be negative"); } if (length < 0) { throw new IllegalArgumentException("Length must not be negative"); } if (!haveBytes(length)) { return EOF; } final int result = Math.min(length, buffer.getCurrentNumberOfBytes()); for (int i = 0; i < result; i++) { targetBuffer[offset + i] = buffer.read(); } return result; } @Override public void close() throws IOException { in.close(); eof = true; buffer.clear(); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/buffer/CircularByteBuffer.java0100644 0000000 0000000 00000024111 13612062727 032527 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input.buffer; import java.util.Objects; import org.apache.commons.io.IOUtils; /** * A buffer, which doesn't need reallocation of byte arrays, because it * reuses a single byte array. This works particularly well, if reading * from the buffer takes place at the same time than writing to. Such is the * case, for example, when using the buffer within a filtering input stream, * like the {@link CircularBufferInputStream}. */ public class CircularByteBuffer { private final byte[] buffer; private int startOffset; private int endOffset; private int currentNumberOfBytes; /** * Creates a new instance with the given buffer size. * * @param size the size of buffer to create */ public CircularByteBuffer(final int size) { buffer = IOUtils.byteArray(size); startOffset = 0; endOffset = 0; currentNumberOfBytes = 0; } /** * Creates a new instance with a reasonable default buffer size ({@link IOUtils#DEFAULT_BUFFER_SIZE}). */ public CircularByteBuffer() { this(IOUtils.DEFAULT_BUFFER_SIZE); } /** * Returns the next byte from the buffer, removing it at the same time, so * that following invocations won't return it again. * * @return The byte, which is being returned. * @throws IllegalStateException The buffer is empty. Use {@link #hasBytes()}, * or {@link #getCurrentNumberOfBytes()}, to prevent this exception. */ public byte read() { if (currentNumberOfBytes <= 0) { throw new IllegalStateException("No bytes available."); } final byte b = buffer[startOffset]; --currentNumberOfBytes; if (++startOffset == buffer.length) { startOffset = 0; } return b; } /** * Returns the given number of bytes from the buffer by storing them in * the given byte array at the given offset. * * @param targetBuffer The byte array, where to add bytes. * @param targetOffset The offset, where to store bytes in the byte array. * @param length The number of bytes to return. * @throws NullPointerException The byte array {@code pBuffer} is null. * @throws IllegalArgumentException Either of {@code pOffset}, or {@code length} is negative, * or the length of the byte array {@code targetBuffer} is too small. * @throws IllegalStateException The buffer doesn't hold the given number * of bytes. Use {@link #getCurrentNumberOfBytes()} to prevent this * exception. */ public void read(final byte[] targetBuffer, final int targetOffset, final int length) { Objects.requireNonNull(targetBuffer, "targetBuffer"); if (targetOffset < 0 || targetOffset >= targetBuffer.length) { throw new IllegalArgumentException("Invalid offset: " + targetOffset); } if (length < 0 || length > buffer.length) { throw new IllegalArgumentException("Invalid length: " + length); } if (targetOffset + length > targetBuffer.length) { throw new IllegalArgumentException("The supplied byte array contains only " + targetBuffer.length + " bytes, but offset, and length would require " + (targetOffset + length - 1)); } if (currentNumberOfBytes < length) { throw new IllegalStateException("Currently, there are only " + currentNumberOfBytes + "in the buffer, not " + length); } int offset = targetOffset; for (int i = 0; i < length; i++) { targetBuffer[offset++] = buffer[startOffset]; --currentNumberOfBytes; if (++startOffset == buffer.length) { startOffset = 0; } } } /** * Adds a new byte to the buffer, which will eventually be returned by following * invocations of {@link #read()}. * * @param value The byte, which is being added to the buffer. * @throws IllegalStateException The buffer is full. Use {@link #hasSpace()}, * or {@link #getSpace()}, to prevent this exception. */ public void add(final byte value) { if (currentNumberOfBytes >= buffer.length) { throw new IllegalStateException("No space available"); } buffer[endOffset] = value; ++currentNumberOfBytes; if (++endOffset == buffer.length) { endOffset = 0; } } /** * Returns, whether the next bytes in the buffer are exactly those, given by * {@code sourceBuffer}, {@code offset}, and {@code length}. No bytes are being * removed from the buffer. If the result is true, then the following invocations * of {@link #read()} are guaranteed to return exactly those bytes. * * @param sourceBuffer the buffer to compare against * @param offset start offset * @param length length to compare * @return True, if the next invocations of {@link #read()} will return the * bytes at offsets {@code pOffset}+0, {@code pOffset}+1, ..., * {@code pOffset}+{@code length}-1 of byte array {@code pBuffer}. * @throws IllegalArgumentException Either of {@code pOffset}, or {@code length} is negative. * @throws NullPointerException The byte array {@code pBuffer} is null. */ public boolean peek(final byte[] sourceBuffer, final int offset, final int length) { Objects.requireNonNull(sourceBuffer, "Buffer"); if (offset < 0 || offset >= sourceBuffer.length) { throw new IllegalArgumentException("Invalid offset: " + offset); } if (length < 0 || length > buffer.length) { throw new IllegalArgumentException("Invalid length: " + length); } if (length < currentNumberOfBytes) { return false; } int localOffset = startOffset; for (int i = 0; i < length; i++) { if (buffer[localOffset] != sourceBuffer[i + offset]) { return false; } if (++localOffset == buffer.length) { localOffset = 0; } } return true; } /** * Adds the given bytes to the buffer. This is the same as invoking {@link #add(byte)} * for the bytes at offsets {@code offset+0}, {@code offset+1}, ..., * {@code offset+length-1} of byte array {@code targetBuffer}. * * @param targetBuffer the buffer to copy * @param offset start offset * @param length length to copy * @throws IllegalStateException The buffer doesn't have sufficient space. Use * {@link #getSpace()} to prevent this exception. * @throws IllegalArgumentException Either of {@code offset}, or {@code length} is negative. * @throws NullPointerException The byte array {@code pBuffer} is null. */ public void add(final byte[] targetBuffer, final int offset, final int length) { Objects.requireNonNull(targetBuffer, "Buffer"); if (offset < 0 || offset >= targetBuffer.length) { throw new IllegalArgumentException("Invalid offset: " + offset); } if (length < 0) { throw new IllegalArgumentException("Invalid length: " + length); } if (currentNumberOfBytes + length > buffer.length) { throw new IllegalStateException("No space available"); } for (int i = 0; i < length; i++) { buffer[endOffset] = targetBuffer[offset + i]; if (++endOffset == buffer.length) { endOffset = 0; } } currentNumberOfBytes += length; } /** * Returns, whether there is currently room for a single byte in the buffer. * Same as {@link #hasSpace(int) hasSpace(1)}. * * @return true if there is space for a byte * @see #hasSpace(int) * @see #getSpace() */ public boolean hasSpace() { return currentNumberOfBytes < buffer.length; } /** * Returns, whether there is currently room for the given number of bytes in the buffer. * * @param count the byte count * @return true if there is space for the given number of bytes * @see #hasSpace() * @see #getSpace() */ public boolean hasSpace(final int count) { return currentNumberOfBytes + count <= buffer.length; } /** * Returns, whether the buffer is currently holding, at least, a single byte. * * @return true if the buffer is not empty */ public boolean hasBytes() { return currentNumberOfBytes > 0; } /** * Returns the number of bytes, that can currently be added to the buffer. * * @return the number of bytes that can be added */ public int getSpace() { return buffer.length - currentNumberOfBytes; } /** * Returns the number of bytes, that are currently present in the buffer. * * @return the number of bytes */ public int getCurrentNumberOfBytes() { return currentNumberOfBytes; } /** * Removes all bytes from the buffer. */ public void clear() { startOffset = 0; endOffset = 0; currentNumberOfBytes = 0; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/buffer/PeekableInputStream.java0100644 0000000 0000000 00000006715 13612062727 032723 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input.buffer; import java.io.IOException; import java.io.InputStream; import java.util.Objects; /** * Implements a buffered input stream, which allows to peek into the buffers first bytes. This comes in handy when * manually implementing scanners, lexers, parsers, and the like. */ public class PeekableInputStream extends CircularBufferInputStream { /** * Creates a new instance, which filters the given input stream, and uses the given buffer size. * * @param inputStream The input stream, which is being buffered. * @param bufferSize The size of the {@link CircularByteBuffer}, which is used internally. */ public PeekableInputStream(final InputStream inputStream, final int bufferSize) { super(inputStream, bufferSize); } /** * Creates a new instance, which filters the given input stream, and uses a reasonable default buffer size (8192). * * @param inputStream The input stream, which is being buffered. */ public PeekableInputStream(final InputStream inputStream) { super(inputStream); } /** * Returns whether the next bytes in the buffer are as given by {@code sourceBuffer}. This is equivalent to * {@link #peek(byte[], int, int)} with {@code offset} == 0, and {@code length} == {@code sourceBuffer.length} * * @param sourceBuffer the buffer to compare against * @return true if the next bytes are as given * @throws IOException Refilling the buffer failed. */ public boolean peek(final byte[] sourceBuffer) throws IOException { Objects.requireNonNull(sourceBuffer, "sourceBuffer"); return peek(sourceBuffer, 0, sourceBuffer.length); } /** * Returns whether the next bytes in the buffer are as given by {@code sourceBuffer}, {code offset}, and * {@code length}. * * @param sourceBuffer the buffer to compare against * @param offset the start offset * @param length the length to compare * @return true if the next bytes in the buffer are as given * @throws IOException if there is a problem calling fillBuffer() */ public boolean peek(final byte[] sourceBuffer, final int offset, final int length) throws IOException { Objects.requireNonNull(sourceBuffer, "sourceBuffer"); if (sourceBuffer.length > bufferSize) { throw new IllegalArgumentException("Peek request size of " + sourceBuffer.length + " bytes exceeds buffer size of " + bufferSize + " bytes"); } if (buffer.getCurrentNumberOfBytes() < sourceBuffer.length) { fillBuffer(); } return buffer.peek(sourceBuffer, offset, length); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/buffer/package.html0100644 0000000 0000000 00000001772 13612062727 030433 0ustar00rootroot0000000 0000000

This package provides implementations of buffered input classes, such as CircularBufferInputStream and PeekableInputStream.

commons-io-2.11.0-src/src/main/java/org/apache/commons/io/input/package.html0100644 0000000 0000000 00000001726 13612062727 027161 0ustar00rootroot0000000 0000000

This package provides implementations of input classes, such as InputStream and Reader.

commons-io-2.11.0-src/src/main/java/org/apache/commons/io/monitor/FileAlterationListener.java0100644 0000000 0000000 00000004421 13612062727 032476 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.monitor; import java.io.File; /** * A listener that receives events of file system modifications. *

* Register {@link FileAlterationListener}s with a {@link FileAlterationObserver}. * * @see FileAlterationObserver * * @since 2.0 */ public interface FileAlterationListener { /** * File system observer started checking event. * * @param observer The file system observer */ void onStart(final FileAlterationObserver observer); /** * Directory created Event. * * @param directory The directory created */ void onDirectoryCreate(final File directory); /** * Directory changed Event. * * @param directory The directory changed */ void onDirectoryChange(final File directory); /** * Directory deleted Event. * * @param directory The directory deleted */ void onDirectoryDelete(final File directory); /** * File created Event. * * @param file The file created */ void onFileCreate(final File file); /** * File changed Event. * * @param file The file changed */ void onFileChange(final File file); /** * File deleted Event. * * @param file The file deleted */ void onFileDelete(final File file); /** * File system observer finished checking event. * * @param observer The file system observer */ void onStop(final FileAlterationObserver observer); } ././@LongLink0100644 0000000 0000000 00000000145 13612062727 011641 Lustar 0000000 0000000 commons-io-2.11.0-src/src/main/java/org/apache/commons/io/monitor/FileAlterationListenerAdaptor.javacommons-io-2.11.0-src/src/main/java/org/apache/commons/io/monitor/FileAlterationListenerAdaptor.java0100644 0000000 0000000 00000005235 13612062727 034015 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.monitor; import java.io.File; /** * Convenience {@link FileAlterationListener} implementation that does nothing. * * @see FileAlterationObserver * * @since 2.0 */ public class FileAlterationListenerAdaptor implements FileAlterationListener { /** * File system observer started checking event. * * @param observer The file system observer (ignored) */ @Override public void onStart(final FileAlterationObserver observer) { // noop } /** * Directory created Event. * * @param directory The directory created (ignored) */ @Override public void onDirectoryCreate(final File directory) { // noop } /** * Directory changed Event. * * @param directory The directory changed (ignored) */ @Override public void onDirectoryChange(final File directory) { // noop } /** * Directory deleted Event. * * @param directory The directory deleted (ignored) */ @Override public void onDirectoryDelete(final File directory) { // noop } /** * File created Event. * * @param file The file created (ignored) */ @Override public void onFileCreate(final File file) { // noop } /** * File changed Event. * * @param file The file changed (ignored) */ @Override public void onFileChange(final File file) { // noop } /** * File deleted Event. * * @param file The file deleted (ignored) */ @Override public void onFileDelete(final File file) { // noop } /** * File system observer finished checking event. * * @param observer The file system observer (ignored) */ @Override public void onStop(final FileAlterationObserver observer) { // noop } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/monitor/FileAlterationMonitor.java0100644 0000000 0000000 00000015006 13612062727 032341 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.monitor; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.ThreadFactory; /** * A runnable that spawns a monitoring thread triggering any * registered {@link FileAlterationObserver} at a specified interval. * * @see FileAlterationObserver * @since 2.0 */ public final class FileAlterationMonitor implements Runnable { private static final FileAlterationObserver[] EMPTY_ARRAY = {}; private final long interval; private final List observers = new CopyOnWriteArrayList<>(); private Thread thread; private ThreadFactory threadFactory; private volatile boolean running; /** * Constructs a monitor with a default interval of 10 seconds. */ public FileAlterationMonitor() { this(10000); } /** * Constructs a monitor with the specified interval. * * @param interval The amount of time in milliseconds to wait between * checks of the file system. */ public FileAlterationMonitor(final long interval) { this.interval = interval; } /** * Constructs a monitor with the specified interval and collection of observers. * * @param interval The amount of time in milliseconds to wait between * checks of the file system. * @param observers The collection of observers to add to the monitor. * @since 2.9.0 */ public FileAlterationMonitor(final long interval, final Collection observers) { // @formatter:off this(interval, Optional .ofNullable(observers) .orElse(Collections.emptyList()) .toArray(EMPTY_ARRAY) ); // @formatter:on } /** * Constructs a monitor with the specified interval and set of observers. * * @param interval The amount of time in milliseconds to wait between * checks of the file system. * @param observers The set of observers to add to the monitor. */ public FileAlterationMonitor(final long interval, final FileAlterationObserver... observers) { this(interval); if (observers != null) { for (final FileAlterationObserver observer : observers) { addObserver(observer); } } } /** * Returns the interval. * * @return the interval */ public long getInterval() { return interval; } /** * Sets the thread factory. * * @param threadFactory the thread factory */ public synchronized void setThreadFactory(final ThreadFactory threadFactory) { this.threadFactory = threadFactory; } /** * Adds a file system observer to this monitor. * * @param observer The file system observer to add */ public void addObserver(final FileAlterationObserver observer) { if (observer != null) { observers.add(observer); } } /** * Removes a file system observer from this monitor. * * @param observer The file system observer to remove */ public void removeObserver(final FileAlterationObserver observer) { if (observer != null) { while (observers.remove(observer)) { // empty } } } /** * Returns the set of {@link FileAlterationObserver} registered with * this monitor. * * @return The set of {@link FileAlterationObserver} */ public Iterable getObservers() { return observers; } /** * Starts monitoring. * * @throws Exception if an error occurs initializing the observer */ public synchronized void start() throws Exception { if (running) { throw new IllegalStateException("Monitor is already running"); } for (final FileAlterationObserver observer : observers) { observer.initialize(); } running = true; if (threadFactory != null) { thread = threadFactory.newThread(this); } else { thread = new Thread(this); } thread.start(); } /** * Stops monitoring. * * @throws Exception if an error occurs initializing the observer */ public synchronized void stop() throws Exception { stop(interval); } /** * Stops monitoring. * * @param stopInterval the amount of time in milliseconds to wait for the thread to finish. * A value of zero will wait until the thread is finished (see {@link Thread#join(long)}). * @throws Exception if an error occurs initializing the observer * @since 2.1 */ public synchronized void stop(final long stopInterval) throws Exception { if (!running) { throw new IllegalStateException("Monitor is not running"); } running = false; try { thread.interrupt(); thread.join(stopInterval); } catch (final InterruptedException e) { Thread.currentThread().interrupt(); } for (final FileAlterationObserver observer : observers) { observer.destroy(); } } /** * Runs this monitor. */ @Override public void run() { while (running) { for (final FileAlterationObserver observer : observers) { observer.checkAndNotify(); } if (!running) { break; } try { Thread.sleep(interval); } catch (final InterruptedException ignored) { // ignore } } } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/monitor/FileAlterationObserver.java0100644 0000000 0000000 00000041007 13612062727 032501 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.monitor; import java.io.File; import java.io.FileFilter; import java.io.Serializable; import java.util.Arrays; import java.util.Comparator; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOCase; import org.apache.commons.io.comparator.NameFileComparator; /** * FileAlterationObserver represents the state of files below a root directory, * checking the file system and notifying listeners of create, change or * delete events. *

* To use this implementation: *

    *
  • Create {@link FileAlterationListener} implementation(s) that process * the file/directory create, change and delete events
  • *
  • Register the listener(s) with a {@link FileAlterationObserver} for * the appropriate directory.
  • *
  • Either register the observer(s) with a {@link FileAlterationMonitor} or * run manually.
  • *
* *

Basic Usage

* Create a {@link FileAlterationObserver} for the directory and register the listeners: *
 *      File directory = new File(new File("."), "src");
 *      FileAlterationObserver observer = new FileAlterationObserver(directory);
 *      observer.addListener(...);
 *      observer.addListener(...);
 * 
* To manually observe a directory, initialize the observer and invoked the * {@link #checkAndNotify()} method as required: *
 *      // initialize
 *      observer.init();
 *      ...
 *      // invoke as required
 *      observer.checkAndNotify();
 *      ...
 *      observer.checkAndNotify();
 *      ...
 *      // finished
 *      observer.finish();
 * 
* Alternatively, register the observer(s) with a {@link FileAlterationMonitor}, * which creates a new thread, invoking the observer at the specified interval: *
 *      long interval = ...
 *      FileAlterationMonitor monitor = new FileAlterationMonitor(interval);
 *      monitor.addObserver(observer);
 *      monitor.start();
 *      ...
 *      monitor.stop();
 * 
* *

File Filters

* This implementation can monitor portions of the file system * by using {@link FileFilter}s to observe only the files and/or directories * that are of interest. This makes it more efficient and reduces the * noise from unwanted file system events. *

* Commons IO has a good range of * useful, ready made * File Filter * implementations for this purpose. *

* For example, to only observe 1) visible directories and 2) files with a ".java" suffix * in a root directory called "src" you could set up a {@link FileAlterationObserver} in the following * way: *

 *      // Create a FileFilter
 *      IOFileFilter directories = FileFilterUtils.and(
 *                                      FileFilterUtils.directoryFileFilter(),
 *                                      HiddenFileFilter.VISIBLE);
 *      IOFileFilter files       = FileFilterUtils.and(
 *                                      FileFilterUtils.fileFileFilter(),
 *                                      FileFilterUtils.suffixFileFilter(".java"));
 *      IOFileFilter filter = FileFilterUtils.or(directories, files);
 *
 *      // Create the File system observer and register File Listeners
 *      FileAlterationObserver observer = new FileAlterationObserver(new File("src"), filter);
 *      observer.addListener(...);
 *      observer.addListener(...);
 * 
* *

FileEntry

* {@link FileEntry} represents the state of a file or directory, capturing * {@link File} attributes at a point in time. Custom implementations of * {@link FileEntry} can be used to capture additional properties that the * basic implementation does not support. The {@link FileEntry#refresh(File)} * method is used to determine if a file or directory has changed since the last * check and stores the current state of the {@link File}'s properties. * * @see FileAlterationListener * @see FileAlterationMonitor * * @since 2.0 */ public class FileAlterationObserver implements Serializable { private static final long serialVersionUID = 1185122225658782848L; private final List listeners = new CopyOnWriteArrayList<>(); private final FileEntry rootEntry; private final FileFilter fileFilter; private final Comparator comparator; /** * Constructs an observer for the specified directory. * * @param directoryName the name of the directory to observe */ public FileAlterationObserver(final String directoryName) { this(new File(directoryName)); } /** * Constructs an observer for the specified directory and file filter. * * @param directoryName the name of the directory to observe * @param fileFilter The file filter or null if none */ public FileAlterationObserver(final String directoryName, final FileFilter fileFilter) { this(new File(directoryName), fileFilter); } /** * Construct an observer for the specified directory, file filter and * file comparator. * * @param directoryName the name of the directory to observe * @param fileFilter The file filter or null if none * @param caseSensitivity what case sensitivity to use comparing file names, null means system sensitive */ public FileAlterationObserver(final String directoryName, final FileFilter fileFilter, final IOCase caseSensitivity) { this(new File(directoryName), fileFilter, caseSensitivity); } /** * Constructs an observer for the specified directory. * * @param directory the directory to observe */ public FileAlterationObserver(final File directory) { this(directory, null); } /** * Constructs an observer for the specified directory and file filter. * * @param directory the directory to observe * @param fileFilter The file filter or null if none */ public FileAlterationObserver(final File directory, final FileFilter fileFilter) { this(directory, fileFilter, null); } /** * Constructs an observer for the specified directory, file filter and * file comparator. * * @param directory the directory to observe * @param fileFilter The file filter or null if none * @param caseSensitivity what case sensitivity to use comparing file names, null means system sensitive */ public FileAlterationObserver(final File directory, final FileFilter fileFilter, final IOCase caseSensitivity) { this(new FileEntry(directory), fileFilter, caseSensitivity); } /** * Constructs an observer for the specified directory, file filter and * file comparator. * * @param rootEntry the root directory to observe * @param fileFilter The file filter or null if none * @param caseSensitivity what case sensitivity to use comparing file names, null means system sensitive */ protected FileAlterationObserver(final FileEntry rootEntry, final FileFilter fileFilter, final IOCase caseSensitivity) { if (rootEntry == null) { throw new IllegalArgumentException("Root entry is missing"); } if (rootEntry.getFile() == null) { throw new IllegalArgumentException("Root directory is missing"); } this.rootEntry = rootEntry; this.fileFilter = fileFilter; if (caseSensitivity == null || caseSensitivity.equals(IOCase.SYSTEM)) { this.comparator = NameFileComparator.NAME_SYSTEM_COMPARATOR; } else if (caseSensitivity.equals(IOCase.INSENSITIVE)) { this.comparator = NameFileComparator.NAME_INSENSITIVE_COMPARATOR; } else { this.comparator = NameFileComparator.NAME_COMPARATOR; } } /** * Returns the directory being observed. * * @return the directory being observed */ public File getDirectory() { return rootEntry.getFile(); } /** * Returns the fileFilter. * * @return the fileFilter * @since 2.1 */ public FileFilter getFileFilter() { return fileFilter; } /** * Adds a file system listener. * * @param listener The file system listener */ public void addListener(final FileAlterationListener listener) { if (listener != null) { listeners.add(listener); } } /** * Removes a file system listener. * * @param listener The file system listener */ public void removeListener(final FileAlterationListener listener) { if (listener != null) { while (listeners.remove(listener)) { // empty } } } /** * Returns the set of registered file system listeners. * * @return The file system listeners */ public Iterable getListeners() { return listeners; } /** * Initializes the observer. * * @throws Exception if an error occurs */ @SuppressWarnings("unused") // Possibly thrown from subclasses. public void initialize() throws Exception { rootEntry.refresh(rootEntry.getFile()); final FileEntry[] children = doListFiles(rootEntry.getFile(), rootEntry); rootEntry.setChildren(children); } /** * Final processing. * * @throws Exception if an error occurs */ @SuppressWarnings("unused") // Possibly thrown from subclasses. public void destroy() throws Exception { // noop } /** * Checks whether the file and its children have been created, modified or deleted. */ public void checkAndNotify() { /* fire onStart() */ for (final FileAlterationListener listener : listeners) { listener.onStart(this); } /* fire directory/file events */ final File rootFile = rootEntry.getFile(); if (rootFile.exists()) { checkAndNotify(rootEntry, rootEntry.getChildren(), listFiles(rootFile)); } else if (rootEntry.isExists()) { checkAndNotify(rootEntry, rootEntry.getChildren(), FileUtils.EMPTY_FILE_ARRAY); } else { // Didn't exist and still doesn't } /* fire onStop() */ for (final FileAlterationListener listener : listeners) { listener.onStop(this); } } /** * Compares two file lists for files which have been created, modified or deleted. * * @param parent The parent entry * @param previous The original list of files * @param files The current list of files */ private void checkAndNotify(final FileEntry parent, final FileEntry[] previous, final File[] files) { int c = 0; final FileEntry[] current = files.length > 0 ? new FileEntry[files.length] : FileEntry.EMPTY_FILE_ENTRY_ARRAY; for (final FileEntry entry : previous) { while (c < files.length && comparator.compare(entry.getFile(), files[c]) > 0) { current[c] = createFileEntry(parent, files[c]); doCreate(current[c]); c++; } if (c < files.length && comparator.compare(entry.getFile(), files[c]) == 0) { doMatch(entry, files[c]); checkAndNotify(entry, entry.getChildren(), listFiles(files[c])); current[c] = entry; c++; } else { checkAndNotify(entry, entry.getChildren(), FileUtils.EMPTY_FILE_ARRAY); doDelete(entry); } } for (; c < files.length; c++) { current[c] = createFileEntry(parent, files[c]); doCreate(current[c]); } parent.setChildren(current); } /** * Creates a new file entry for the specified file. * * @param parent The parent file entry * @param file The file to create an entry for * @return A new file entry */ private FileEntry createFileEntry(final FileEntry parent, final File file) { final FileEntry entry = parent.newChildInstance(file); entry.refresh(file); final FileEntry[] children = doListFiles(file, entry); entry.setChildren(children); return entry; } /** * Lists the files * @param file The file to list files for * @param entry the parent entry * @return The child files */ private FileEntry[] doListFiles(final File file, final FileEntry entry) { final File[] files = listFiles(file); final FileEntry[] children = files.length > 0 ? new FileEntry[files.length] : FileEntry.EMPTY_FILE_ENTRY_ARRAY; for (int i = 0; i < files.length; i++) { children[i] = createFileEntry(entry, files[i]); } return children; } /** * Fires directory/file created events to the registered listeners. * * @param entry The file entry */ private void doCreate(final FileEntry entry) { for (final FileAlterationListener listener : listeners) { if (entry.isDirectory()) { listener.onDirectoryCreate(entry.getFile()); } else { listener.onFileCreate(entry.getFile()); } } final FileEntry[] children = entry.getChildren(); for (final FileEntry aChildren : children) { doCreate(aChildren); } } /** * Fires directory/file change events to the registered listeners. * * @param entry The previous file system entry * @param file The current file */ private void doMatch(final FileEntry entry, final File file) { if (entry.refresh(file)) { for (final FileAlterationListener listener : listeners) { if (entry.isDirectory()) { listener.onDirectoryChange(file); } else { listener.onFileChange(file); } } } } /** * Fires directory/file delete events to the registered listeners. * * @param entry The file entry */ private void doDelete(final FileEntry entry) { for (final FileAlterationListener listener : listeners) { if (entry.isDirectory()) { listener.onDirectoryDelete(entry.getFile()); } else { listener.onFileDelete(entry.getFile()); } } } /** * Lists the contents of a directory * * @param file The file to list the contents of * @return the directory contents or a zero length array if * the empty or the file is not a directory */ private File[] listFiles(final File file) { File[] children = null; if (file.isDirectory()) { children = fileFilter == null ? file.listFiles() : file.listFiles(fileFilter); } if (children == null) { children = FileUtils.EMPTY_FILE_ARRAY; } if (comparator != null && children.length > 1) { Arrays.sort(children, comparator); } return children; } /** * Returns a String representation of this observer. * * @return a String representation of this observer */ @Override public String toString() { final StringBuilder builder = new StringBuilder(); builder.append(getClass().getSimpleName()); builder.append("[file='"); builder.append(getDirectory().getPath()); builder.append('\''); if (fileFilter != null) { builder.append(", "); builder.append(fileFilter.toString()); } builder.append(", listeners="); builder.append(listeners.size()); builder.append("]"); return builder.toString(); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/monitor/FileEntry.java0100644 0000000 0000000 00000017133 13612062727 027773 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.monitor; import java.io.File; import java.io.IOException; import java.io.Serializable; import java.nio.file.Files; import org.apache.commons.io.FileUtils; /** * The state of a file or directory, capturing the following {@link File} attributes at a point in time. *
    *
  • File Name (see {@link File#getName()})
  • *
  • Exists - whether the file exists or not (see {@link File#exists()})
  • *
  • Directory - whether the file is a directory or not (see {@link File#isDirectory()})
  • *
  • Last Modified Date/Time (see {@link FileUtils#lastModifiedUnchecked(File)})
  • *
  • Length (see {@link File#length()}) - directories treated as zero
  • *
  • Children - contents of a directory (see {@link File#listFiles(java.io.FileFilter)})
  • *
* *

Custom Implementations

*

* If the state of additional {@link File} attributes is required then create a custom * {@link FileEntry} with properties for those attributes. Override the * {@link #newChildInstance(File)} to return a new instance of the appropriate type. * You may also want to override the {@link #refresh(File)} method. *

* @see FileAlterationObserver * @since 2.0 */ public class FileEntry implements Serializable { private static final long serialVersionUID = -2505664948818681153L; static final FileEntry[] EMPTY_FILE_ENTRY_ARRAY = {}; private final FileEntry parent; private FileEntry[] children; private final File file; private String name; private boolean exists; private boolean directory; private long lastModified; private long length; /** * Construct a new monitor for a specified {@link File}. * * @param file The file being monitored */ public FileEntry(final File file) { this(null, file); } /** * Construct a new monitor for a specified {@link File}. * * @param parent The parent * @param file The file being monitored */ public FileEntry(final FileEntry parent, final File file) { if (file == null) { throw new IllegalArgumentException("File is missing"); } this.file = file; this.parent = parent; this.name = file.getName(); } /** * Refresh the attributes from the {@link File}, indicating * whether the file has changed. *

* This implementation refreshes the {@code name}, {@code exists}, * {@code directory}, {@code lastModified} and {@code length} * properties. *

* The {@code exists}, {@code directory}, {@code lastModified} * and {@code length} properties are compared for changes * * @param file the file instance to compare to * @return {@code true} if the file has changed, otherwise {@code false} */ public boolean refresh(final File file) { // cache original values final boolean origExists = exists; final long origLastModified = lastModified; final boolean origDirectory = directory; final long origLength = length; // refresh the values name = file.getName(); exists = Files.exists(file.toPath()); directory = exists && file.isDirectory(); try { lastModified = exists ? FileUtils.lastModified(file) : 0; } catch (final IOException e) { lastModified = 0; } length = exists && !directory ? file.length() : 0; // Return if there are changes return exists != origExists || lastModified != origLastModified || directory != origDirectory || length != origLength; } /** * Create a new child instance. *

* Custom implementations should override this method to return * a new instance of the appropriate type. * * @param file The child file * @return a new child instance */ public FileEntry newChildInstance(final File file) { return new FileEntry(this, file); } /** * Return the parent entry. * * @return the parent entry */ public FileEntry getParent() { return parent; } /** * Return the level * * @return the level */ public int getLevel() { return parent == null ? 0 : parent.getLevel() + 1; } /** * Return the directory's files. * * @return This directory's files or an empty * array if the file is not a directory or the * directory is empty */ public FileEntry[] getChildren() { return children != null ? children : EMPTY_FILE_ENTRY_ARRAY; } /** * Set the directory's files. * * @param children This directory's files, may be null */ public void setChildren(final FileEntry... children) { this.children = children; } /** * Return the file being monitored. * * @return the file being monitored */ public File getFile() { return file; } /** * Return the file name. * * @return the file name */ public String getName() { return name; } /** * Set the file name. * * @param name the file name */ public void setName(final String name) { this.name = name; } /** * Return the last modified time from the last time it * was checked. * * @return the last modified time */ public long getLastModified() { return lastModified; } /** * Return the last modified time from the last time it * was checked. * * @param lastModified The last modified time */ public void setLastModified(final long lastModified) { this.lastModified = lastModified; } /** * Return the length. * * @return the length */ public long getLength() { return length; } /** * Set the length. * * @param length the length */ public void setLength(final long length) { this.length = length; } /** * Indicate whether the file existed the last time it * was checked. * * @return whether the file existed */ public boolean isExists() { return exists; } /** * Set whether the file existed the last time it * was checked. * * @param exists whether the file exists or not */ public void setExists(final boolean exists) { this.exists = exists; } /** * Indicate whether the file is a directory or not. * * @return whether the file is a directory or not */ public boolean isDirectory() { return directory; } /** * Set whether the file is a directory or not. * * @param directory whether the file is a directory or not */ public void setDirectory(final boolean directory) { this.directory = directory; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/monitor/package.html0100644 0000000 0000000 00000001737 13612062727 027513 0ustar00rootroot0000000 0000000

This package provides a component for monitoring file system events (directory and file create, update and delete events).

commons-io-2.11.0-src/src/main/java/org/apache/commons/io/output/AbstractByteArrayOutputStream.java0100644 0000000 0000000 00000034533 13612062727 033731 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import org.apache.commons.io.IOUtils; import org.apache.commons.io.input.ClosedInputStream; import java.io.InputStream; import java.io.IOException; import java.io.OutputStream; import java.io.SequenceInputStream; import java.io.UnsupportedEncodingException; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Collections; import java.util.List; import static org.apache.commons.io.IOUtils.EOF; /** * This is the base class for implementing an output stream in which the data * is written into a byte array. The buffer automatically grows as data * is written to it. *

* The data can be retrieved using {@code toByteArray()} and * {@code toString()}. * Closing an {@code AbstractByteArrayOutputStream} has no effect. The methods in * this class can be called after the stream has been closed without * generating an {@code IOException}. *

*

* This is the base for an alternative implementation of the * {@link java.io.ByteArrayOutputStream} class. The original implementation * only allocates 32 bytes at the beginning. As this class is designed for * heavy duty it starts at {@value #DEFAULT_SIZE} bytes. In contrast to the original it doesn't * reallocate the whole memory block but allocates additional buffers. This * way no buffers need to be garbage collected and the contents don't have * to be copied to the new buffer. This class is designed to behave exactly * like the original. The only exception is the deprecated * {@link java.io.ByteArrayOutputStream#toString(int)} method that has been * ignored. *

* * @since 2.7 */ public abstract class AbstractByteArrayOutputStream extends OutputStream { static final int DEFAULT_SIZE = 1024; /** The list of buffers, which grows and never reduces. */ private final List buffers = new ArrayList<>(); /** The index of the current buffer. */ private int currentBufferIndex; /** The total count of bytes in all the filled buffers. */ private int filledBufferSum; /** The current buffer. */ private byte[] currentBuffer; /** The total count of bytes written. */ protected int count; /** Flag to indicate if the buffers can be reused after reset */ private boolean reuseBuffers = true; /** * Makes a new buffer available either by allocating * a new one or re-cycling an existing one. * * @param newcount the size of the buffer if one is created */ protected void needNewBuffer(final int newcount) { if (currentBufferIndex < buffers.size() - 1) { //Recycling old buffer filledBufferSum += currentBuffer.length; currentBufferIndex++; currentBuffer = buffers.get(currentBufferIndex); } else { //Creating new buffer final int newBufferSize; if (currentBuffer == null) { newBufferSize = newcount; filledBufferSum = 0; } else { newBufferSize = Math.max( currentBuffer.length << 1, newcount - filledBufferSum); filledBufferSum += currentBuffer.length; } currentBufferIndex++; currentBuffer = IOUtils.byteArray(newBufferSize); buffers.add(currentBuffer); } } /** * Writes the bytes to the byte array. * @param b the bytes to write * @param off The start offset * @param len The number of bytes to write */ @Override public abstract void write(final byte[] b, final int off, final int len); /** * Writes the bytes to the byte array. * @param b the bytes to write * @param off The start offset * @param len The number of bytes to write */ protected void writeImpl(final byte[] b, final int off, final int len) { final int newcount = count + len; int remaining = len; int inBufferPos = count - filledBufferSum; while (remaining > 0) { final int part = Math.min(remaining, currentBuffer.length - inBufferPos); System.arraycopy(b, off + len - remaining, currentBuffer, inBufferPos, part); remaining -= part; if (remaining > 0) { needNewBuffer(newcount); inBufferPos = 0; } } count = newcount; } /** * Write a byte to byte array. * @param b the byte to write */ @Override public abstract void write(final int b); /** * Write a byte to byte array. * @param b the byte to write */ protected void writeImpl(final int b) { int inBufferPos = count - filledBufferSum; if (inBufferPos == currentBuffer.length) { needNewBuffer(count + 1); inBufferPos = 0; } currentBuffer[inBufferPos] = (byte) b; count++; } /** * Writes the entire contents of the specified input stream to this * byte stream. Bytes from the input stream are read directly into the * internal buffers of this streams. * * @param in the input stream to read from * @return total number of bytes read from the input stream * (and written to this stream) * @throws IOException if an I/O error occurs while reading the input stream * @since 1.4 */ public abstract int write(final InputStream in) throws IOException; /** * Writes the entire contents of the specified input stream to this * byte stream. Bytes from the input stream are read directly into the * internal buffers of this streams. * * @param in the input stream to read from * @return total number of bytes read from the input stream * (and written to this stream) * @throws IOException if an I/O error occurs while reading the input stream * @since 2.7 */ protected int writeImpl(final InputStream in) throws IOException { int readCount = 0; int inBufferPos = count - filledBufferSum; int n = in.read(currentBuffer, inBufferPos, currentBuffer.length - inBufferPos); while (n != EOF) { readCount += n; inBufferPos += n; count += n; if (inBufferPos == currentBuffer.length) { needNewBuffer(currentBuffer.length); inBufferPos = 0; } n = in.read(currentBuffer, inBufferPos, currentBuffer.length - inBufferPos); } return readCount; } /** * Returns the current size of the byte array. * * @return the current size of the byte array */ public abstract int size(); /** * Closing a {@code ByteArrayOutputStream} has no effect. The methods in * this class can be called after the stream has been closed without * generating an {@code IOException}. * * @throws IOException never (this method should not declare this exception * but it has to now due to backwards compatibility) */ @Override public void close() throws IOException { //nop } /** * @see java.io.ByteArrayOutputStream#reset() */ public abstract void reset(); /** * @see java.io.ByteArrayOutputStream#reset() */ protected void resetImpl() { count = 0; filledBufferSum = 0; currentBufferIndex = 0; if (reuseBuffers) { currentBuffer = buffers.get(currentBufferIndex); } else { //Throw away old buffers currentBuffer = null; final int size = buffers.get(0).length; buffers.clear(); needNewBuffer(size); reuseBuffers = true; } } /** * Writes the entire contents of this byte stream to the * specified output stream. * * @param out the output stream to write to * @throws IOException if an I/O error occurs, such as if the stream is closed * @see java.io.ByteArrayOutputStream#writeTo(OutputStream) */ public abstract void writeTo(final OutputStream out) throws IOException; /** * Writes the entire contents of this byte stream to the * specified output stream. * * @param out the output stream to write to * @throws IOException if an I/O error occurs, such as if the stream is closed * @see java.io.ByteArrayOutputStream#writeTo(OutputStream) */ protected void writeToImpl(final OutputStream out) throws IOException { int remaining = count; for (final byte[] buf : buffers) { final int c = Math.min(buf.length, remaining); out.write(buf, 0, c); remaining -= c; if (remaining == 0) { break; } } } /** * Gets the current contents of this byte stream as a Input Stream. The * returned stream is backed by buffers of {@code this} stream, * avoiding memory allocation and copy, thus saving space and time.
* * @return the current contents of this output stream. * @see java.io.ByteArrayOutputStream#toByteArray() * @see #reset() * @since 2.5 */ public abstract InputStream toInputStream(); /** * Gets the current contents of this byte stream as a Input Stream. The * returned stream is backed by buffers of {@code this} stream, * avoiding memory allocation and copy, thus saving space and time.
* * @param the type of the InputStream which makes up * the {@link SequenceInputStream}. * @param isConstructor A constructor for an InputStream which makes * up the {@link SequenceInputStream}. * * @return the current contents of this output stream. * @see java.io.ByteArrayOutputStream#toByteArray() * @see #reset() * @since 2.7 */ @SuppressWarnings("resource") // The result InputStream MUST be managed by the call site. protected InputStream toInputStream( final InputStreamConstructor isConstructor) { int remaining = count; if (remaining == 0) { return ClosedInputStream.CLOSED_INPUT_STREAM; } final List list = new ArrayList<>(buffers.size()); for (final byte[] buf : buffers) { final int c = Math.min(buf.length, remaining); list.add(isConstructor.construct(buf, 0, c)); remaining -= c; if (remaining == 0) { break; } } reuseBuffers = false; return new SequenceInputStream(Collections.enumeration(list)); } /** * Constructor for an InputStream subclass. * * @param the type of the InputStream. */ @FunctionalInterface protected interface InputStreamConstructor { /** * Construct an InputStream subclass. * * @param buf the buffer * @param offset the offset into the buffer * @param length the length of the buffer * * @return the InputStream subclass. */ T construct(final byte[] buf, final int offset, final int length); } /** * Gets the current contents of this byte stream as a byte array. * The result is independent of this stream. * * @return the current contents of this output stream, as a byte array * @see java.io.ByteArrayOutputStream#toByteArray() */ public abstract byte[] toByteArray(); /** * Gets the current contents of this byte stream as a byte array. * The result is independent of this stream. * * @return the current contents of this output stream, as a byte array * @see java.io.ByteArrayOutputStream#toByteArray() */ protected byte[] toByteArrayImpl() { int remaining = count; if (remaining == 0) { return IOUtils.EMPTY_BYTE_ARRAY; } final byte[] newbuf = IOUtils.byteArray(remaining); int pos = 0; for (final byte[] buf : buffers) { final int c = Math.min(buf.length, remaining); System.arraycopy(buf, 0, newbuf, pos, c); pos += c; remaining -= c; if (remaining == 0) { break; } } return newbuf; } /** * Gets the current contents of this byte stream as a string * using the platform default charset. * @return the contents of the byte array as a String * @see java.io.ByteArrayOutputStream#toString() * @deprecated 2.5 use {@link #toString(String)} instead */ @Override @Deprecated public String toString() { // make explicit the use of the default charset return new String(toByteArray(), Charset.defaultCharset()); } /** * Gets the current contents of this byte stream as a string * using the specified encoding. * * @param enc the name of the character encoding * @return the string converted from the byte array * @throws UnsupportedEncodingException if the encoding is not supported * @see java.io.ByteArrayOutputStream#toString(String) */ public String toString(final String enc) throws UnsupportedEncodingException { return new String(toByteArray(), enc); } /** * Gets the current contents of this byte stream as a string * using the specified encoding. * * @param charset the character encoding * @return the string converted from the byte array * @see java.io.ByteArrayOutputStream#toString(String) * @since 2.5 */ public String toString(final Charset charset) { return new String(toByteArray(), charset); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/output/AppendableOutputStream.java0100644 0000000 0000000 00000004027 13612062727 032371 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import java.io.IOException; import java.io.OutputStream; /** * OutputStream implementation that writes the data to an {@link Appendable} * Object. *

* For example, can be used with any {@link java.io.Writer} or a {@link java.lang.StringBuilder} * or {@link java.lang.StringBuffer}. *

* * @since 2.5 * @see java.lang.Appendable * * @param The type of the {@link Appendable} wrapped by this AppendableOutputStream. */ public class AppendableOutputStream extends OutputStream { private final T appendable; /** * Construct a new instance with the specified appendable. * * @param appendable the appendable to write to */ public AppendableOutputStream(final T appendable) { this.appendable = appendable; } /** * Write a character to the underlying appendable. * * @param b the character to write * @throws IOException upon error */ @Override public void write(final int b) throws IOException { appendable.append((char)b); } /** * Return the target appendable. * * @return the target appendable */ public T getAppendable() { return appendable; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/output/AppendableWriter.java0100644 0000000 0000000 00000011767 13612062727 031202 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import java.io.IOException; import java.io.Writer; import java.util.Objects; /** * Writer implementation that writes the data to an {@link Appendable} * Object. *

* For example, can be used with a {@link java.lang.StringBuilder} * or {@link java.lang.StringBuffer}. *

* * @since 2.7 * @see java.lang.Appendable * * @param The type of the {@link Appendable} wrapped by this AppendableWriter. */ public class AppendableWriter extends Writer { private final T appendable; /** * Constructs a new instance with the specified appendable. * * @param appendable the appendable to write to */ public AppendableWriter(final T appendable) { this.appendable = appendable; } /** * Appends the specified character to the underlying appendable. * * @param c the character to append * @return this writer * @throws IOException upon error */ @Override public Writer append(final char c) throws IOException { appendable.append(c); return this; } /** * Appends the specified character sequence to the underlying appendable. * * @param csq the character sequence to append * @return this writer * @throws IOException upon error */ @Override public Writer append(final CharSequence csq) throws IOException { appendable.append(csq); return this; } /** * Appends a subsequence of the specified character sequence to the underlying appendable. * * @param csq the character sequence from which a subsequence will be appended * @param start the index of the first character in the subsequence * @param end the index of the character following the last character in the subsequence * @return this writer * @throws IOException upon error */ @Override public Writer append(final CharSequence csq, final int start, final int end) throws IOException { appendable.append(csq, start, end); return this; } /** * Closes the stream. This implementation does nothing. * * @throws IOException upon error */ @Override public void close() throws IOException { // noop } /** * Flushes the stream. This implementation does nothing. * * @throws IOException upon error */ @Override public void flush() throws IOException { // noop } /** * Return the target appendable. * * @return the target appendable */ public T getAppendable() { return appendable; } /** * Writes a portion of an array of characters to the underlying appendable. * * @param cbuf an array with the characters to write * @param off offset from which to start writing characters * @param len number of characters to write * @throws IOException upon error */ @Override public void write(final char[] cbuf, final int off, final int len) throws IOException { Objects.requireNonNull(cbuf, "Character array is missing"); if (len < 0 || (off + len) > cbuf.length) { throw new IndexOutOfBoundsException("Array Size=" + cbuf.length + ", offset=" + off + ", length=" + len); } for (int i = 0; i < len; i++) { appendable.append(cbuf[off + i]); } } /** * Writes a character to the underlying appendable. * * @param c the character to write * @throws IOException upon error */ @Override public void write(final int c) throws IOException { appendable.append((char)c); } /** * Writes a portion of a String to the underlying appendable. * * @param str a string * @param off offset from which to start writing characters * @param len number of characters to write * @throws IOException upon error */ @Override public void write(final String str, final int off, final int len) throws IOException { // appendable.append will add "null" for a null String; add an explicit null check Objects.requireNonNull(str, "String is missing"); appendable.append(str, off, off + len); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/output/BrokenOutputStream.java0100644 0000000 0000000 00000004517 13612062727 031562 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import java.io.IOException; import java.io.OutputStream; /** * Broken output stream. This stream always throws an {@link IOException} from * all {@link OutputStream} methods. *

* This class is mostly useful for testing error handling in code that uses an * output stream. *

* * @since 2.0 */ public class BrokenOutputStream extends OutputStream { /** * The exception that is thrown by all methods of this class. */ private final IOException exception; /** * Creates a new stream that always throws the given exception. * * @param exception the exception to be thrown */ public BrokenOutputStream(final IOException exception) { this.exception = exception; } /** * Creates a new stream that always throws an {@link IOException} */ public BrokenOutputStream() { this(new IOException("Broken output stream")); } /** * Throws the configured exception. * * @param b ignored * @throws IOException always thrown */ @Override public void write(final int b) throws IOException { throw exception; } /** * Throws the configured exception. * * @throws IOException always thrown */ @Override public void flush() throws IOException { throw exception; } /** * Throws the configured exception. * * @throws IOException always thrown */ @Override public void close() throws IOException { throw exception; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/output/BrokenWriter.java0100644 0000000 0000000 00000004560 13612062727 030360 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import java.io.IOException; import java.io.Writer; /** * Broken writer. This writer always throws an {@link IOException} from * all {@link Writer} methods. *

* This class is mostly useful for testing error handling in code that uses a * writer. *

* * @since 2.0 */ public class BrokenWriter extends Writer { /** * The exception that is thrown by all methods of this class. */ private final IOException exception; /** * Creates a new writer that always throws the given exception. * * @param exception the exception to be thrown */ public BrokenWriter(final IOException exception) { this.exception = exception; } /** * Creates a new writer that always throws an {@link IOException} */ public BrokenWriter() { this(new IOException("Broken writer")); } /** * Throws the configured exception. * * @param cbuf ignored * @param off ignored * @param len ignored * @throws IOException always thrown */ @Override public void write(final char[] cbuf, final int off, final int len) throws IOException { throw exception; } /** * Throws the configured exception. * * @throws IOException always thrown */ @Override public void flush() throws IOException { throw exception; } /** * Throws the configured exception. * * @throws IOException always thrown */ @Override public void close() throws IOException { throw exception; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/output/ByteArrayOutputStream.java0100644 0000000 0000000 00000012312 13612062727 032234 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; /** * Implements a ThreadSafe version of {@link AbstractByteArrayOutputStream} using instance synchronization. */ //@ThreadSafe public class ByteArrayOutputStream extends AbstractByteArrayOutputStream { /** * Creates a new byte array output stream. The buffer capacity is * initially {@value AbstractByteArrayOutputStream#DEFAULT_SIZE} bytes, though its size increases if necessary. */ public ByteArrayOutputStream() { this(DEFAULT_SIZE); } /** * Creates a new byte array output stream, with a buffer capacity of * the specified size, in bytes. * * @param size the initial size * @throws IllegalArgumentException if size is negative */ public ByteArrayOutputStream(final int size) { if (size < 0) { throw new IllegalArgumentException( "Negative initial size: " + size); } synchronized (this) { needNewBuffer(size); } } @Override public void write(final byte[] b, final int off, final int len) { if ((off < 0) || (off > b.length) || (len < 0) || ((off + len) > b.length) || ((off + len) < 0)) { throw new IndexOutOfBoundsException(); } if (len == 0) { return; } synchronized (this) { writeImpl(b, off, len); } } @Override public synchronized void write(final int b) { writeImpl(b); } @Override public synchronized int write(final InputStream in) throws IOException { return writeImpl(in); } @Override public synchronized int size() { return count; } /** * @see java.io.ByteArrayOutputStream#reset() */ @Override public synchronized void reset() { resetImpl(); } @Override public synchronized void writeTo(final OutputStream out) throws IOException { writeToImpl(out); } /** * Fetches entire contents of an {@code InputStream} and represent * same data as result InputStream. *

* This method is useful where, *

*
    *
  • Source InputStream is slow.
  • *
  • It has network resources associated, so we cannot keep it open for * long time.
  • *
  • It has network timeout associated.
  • *
* It can be used in favor of {@link #toByteArray()}, since it * avoids unnecessary allocation and copy of byte[].
* This method buffers the input internally, so there is no need to use a * {@code BufferedInputStream}. * * @param input Stream to be fully buffered. * @return A fully buffered stream. * @throws IOException if an I/O error occurs. * @since 2.0 */ public static InputStream toBufferedInputStream(final InputStream input) throws IOException { return toBufferedInputStream(input, DEFAULT_SIZE); } /** * Fetches entire contents of an {@code InputStream} and represent * same data as result InputStream. *

* This method is useful where, *

*
    *
  • Source InputStream is slow.
  • *
  • It has network resources associated, so we cannot keep it open for * long time.
  • *
  • It has network timeout associated.
  • *
* It can be used in favor of {@link #toByteArray()}, since it * avoids unnecessary allocation and copy of byte[].
* This method buffers the input internally, so there is no need to use a * {@code BufferedInputStream}. * * @param input Stream to be fully buffered. * @param size the initial buffer size * @return A fully buffered stream. * @throws IOException if an I/O error occurs. * @since 2.5 */ public static InputStream toBufferedInputStream(final InputStream input, final int size) throws IOException { try (final ByteArrayOutputStream output = new ByteArrayOutputStream(size)) { output.write(input); return output.toInputStream(); } } @Override public synchronized InputStream toInputStream() { return toInputStream(java.io.ByteArrayInputStream::new); } @Override public synchronized byte[] toByteArray() { return toByteArrayImpl(); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/output/ChunkedOutputStream.java0100644 0000000 0000000 00000005445 13612062727 031724 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import java.io.FilterOutputStream; import java.io.IOException; import java.io.OutputStream; /** * OutputStream which breaks larger output blocks into chunks. * Native code may need to copy the input array; if the write buffer * is very large this can cause OOME. * * @since 2.5 */ public class ChunkedOutputStream extends FilterOutputStream { /** * The default chunk size to use, i.e. {@value} bytes. */ private static final int DEFAULT_CHUNK_SIZE = 1024 * 4; /** * The maximum chunk size to us when writing data arrays */ private final int chunkSize; /** * Creates a new stream that uses the specified chunk size. * * @param stream the stream to wrap * @param chunkSize the chunk size to use; must be a positive number. * @throws IllegalArgumentException if the chunk size is <= 0 */ public ChunkedOutputStream(final OutputStream stream, final int chunkSize) { super(stream); if (chunkSize <= 0) { throw new IllegalArgumentException(); } this.chunkSize = chunkSize; } /** * Creates a new stream that uses a chunk size of {@link #DEFAULT_CHUNK_SIZE}. * * @param stream the stream to wrap */ public ChunkedOutputStream(final OutputStream stream) { this(stream, DEFAULT_CHUNK_SIZE); } /** * Writes the data buffer in chunks to the underlying stream * * @param data the data to write * @param srcOffset the offset * @param length the length of data to write * * @throws IOException if an I/O error occurs. */ @Override public void write(final byte[] data, final int srcOffset, final int length) throws IOException { int bytes = length; int dstOffset = srcOffset; while(bytes > 0) { final int chunk = Math.min(bytes, chunkSize); out.write(data, dstOffset, chunk); bytes -= chunk; dstOffset += chunk; } } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/output/ChunkedWriter.java0100644 0000000 0000000 00000005313 13612062727 030516 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import java.io.FilterWriter; import java.io.IOException; import java.io.Writer; /** * Writer which breaks larger output blocks into chunks. * Native code may need to copy the input array; if the write buffer * is very large this can cause OOME. * * @since 2.5 */ public class ChunkedWriter extends FilterWriter { /** * The default chunk size to use, i.e. {@value} bytes. */ private static final int DEFAULT_CHUNK_SIZE = 1024 * 4; /** * The maximum chunk size to us when writing data arrays */ private final int chunkSize; /** * Creates a new writer that uses the specified chunk size. * * @param writer the writer to wrap * @param chunkSize the chunk size to use; must be a positive number. * @throws IllegalArgumentException if the chunk size is <= 0 */ public ChunkedWriter(final Writer writer, final int chunkSize) { super(writer); if (chunkSize <= 0) { throw new IllegalArgumentException(); } this.chunkSize = chunkSize; } /** * Creates a new writer that uses a chunk size of {@link #DEFAULT_CHUNK_SIZE} * @param writer the writer to wrap */ public ChunkedWriter(final Writer writer) { this(writer, DEFAULT_CHUNK_SIZE); } /** * writes the data buffer in chunks to the underlying writer * @param data The data * @param srcOffset the offset * @param length the number of bytes to write * * @throws IOException upon error */ @Override public void write(final char[] data, final int srcOffset, final int length) throws IOException { int bytes = length; int dstOffset = srcOffset; while(bytes > 0) { final int chunk = Math.min(bytes, chunkSize); out.write(data, dstOffset, chunk); bytes -= chunk; dstOffset += chunk; } } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/output/CloseShieldOutputStream.java0100644 0000000 0000000 00000004535 13612062727 032540 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import java.io.OutputStream; /** * Proxy stream that prevents the underlying output stream from being closed. *

* This class is typically used in cases where an output stream needs to be * passed to a component that wants to explicitly close the stream even if other * components would still use the stream for output. *

* * @since 1.4 */ public class CloseShieldOutputStream extends ProxyOutputStream { /** * Creates a proxy that shields the given output stream from being closed. * * @param outputStream the output stream to wrap * @return the created proxy * @since 2.9.0 */ public static CloseShieldOutputStream wrap(final OutputStream outputStream) { return new CloseShieldOutputStream(outputStream); } /** * Creates a proxy that shields the given output stream from being closed. * * @param outputStream underlying output stream * @deprecated Using this constructor prevents IDEs from warning if the * underlying output stream is never closed. Use * {@link #wrap(OutputStream)} instead. */ @Deprecated public CloseShieldOutputStream(final OutputStream outputStream) { super(outputStream); } /** * Replaces the underlying output stream with a {@link ClosedOutputStream} * sentinel. The original output stream will remain open, but this proxy will * appear closed. */ @Override public void close() { out = ClosedOutputStream.CLOSED_OUTPUT_STREAM; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/output/CloseShieldWriter.java0100644 0000000 0000000 00000004251 13612062727 031333 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import java.io.Writer; /** * Proxy writer that prevents the underlying writer from being closed. *

* This class is typically used in cases where a writer needs to be passed to a * component that wants to explicitly close the writer even if other components * would still use the writer for output. *

* * @since 2.7 */ public class CloseShieldWriter extends ProxyWriter { /** * Creates a proxy that shields the given writer from being closed. * * @param writer the writer to wrap * @return the created proxy * @since 2.9.0 */ public static CloseShieldWriter wrap(final Writer writer) { return new CloseShieldWriter(writer); } /** * Creates a proxy that shields the given writer from being closed. * * @param writer underlying writer * @deprecated Using this constructor prevents IDEs from warning if the * underlying writer is never closed. Use {@link #wrap(Writer)} * instead. */ @Deprecated public CloseShieldWriter(final Writer writer) { super(writer); } /** * Replaces the underlying writer with a {@link ClosedWriter} sentinel. The * original writer will remain open, but this proxy will appear closed. */ @Override public void close() { out = ClosedWriter.CLOSED_WRITER; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/output/ClosedOutputStream.java0100644 0000000 0000000 00000003647 13612062727 031556 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import java.io.IOException; import java.io.OutputStream; /** * Throws an exception on all attempts to write to the stream. *

* Typically uses of this class include testing for corner cases in methods that accept an output stream and acting as a * sentinel value instead of a {@code null} output stream. *

* * @since 1.4 */ public class ClosedOutputStream extends OutputStream { /** * A singleton. */ public static final ClosedOutputStream CLOSED_OUTPUT_STREAM = new ClosedOutputStream(); /** * Throws an {@link IOException} to indicate that the stream is closed. * * @param b ignored * @throws IOException always thrown */ @Override public void write(final int b) throws IOException { throw new IOException("write(" + b + ") failed: stream is closed"); } /** * Throws an {@link IOException} to indicate that the stream is closed. * * @throws IOException always thrown */ @Override public void flush() throws IOException { throw new IOException("flush() failed: stream is closed"); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/output/ClosedWriter.java0100644 0000000 0000000 00000004147 13612062727 030352 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import java.io.IOException; import java.io.Writer; /** * Throws an exception on all attempts to write with {@link #close()} implemented as a noop. *

* Typically uses of this class include testing for corner cases in methods that accept a writer and acting as a * sentinel value instead of a {@code null} writer. *

* * @since 2.7 */ public class ClosedWriter extends Writer { /** * A singleton. */ public static final ClosedWriter CLOSED_WRITER = new ClosedWriter(); /** * Throws an {@link IOException} to indicate that the writer is closed. * * @param cbuf ignored * @param off ignored * @param len ignored * @throws IOException always thrown */ @Override public void write(final char[] cbuf, final int off, final int len) throws IOException { throw new IOException("write(" + new String(cbuf) + ", " + off + ", " + len + ") failed: stream is closed"); } /** * Throws an {@link IOException} to indicate that the stream is closed. * * @throws IOException always thrown */ @Override public void flush() throws IOException { throw new IOException("flush() failed: stream is closed"); } @Override public void close() throws IOException { // noop } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/output/CountingOutputStream.java0100644 0000000 0000000 00000007627 13612062727 032135 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import java.io.OutputStream; /** * A decorating output stream that counts the number of bytes that have passed * through the stream so far. *

* A typical use case would be during debugging, to ensure that data is being * written as expected. *

* */ public class CountingOutputStream extends ProxyOutputStream { /** The count of bytes that have passed. */ private long count; /** * Constructs a new CountingOutputStream. * * @param out the OutputStream to write to */ public CountingOutputStream( final OutputStream out ) { super(out); } /** * Updates the count with the number of bytes that are being written. * * @param n number of bytes to be written to the stream * @since 2.0 */ @Override protected synchronized void beforeWrite(final int n) { count += n; } /** * The number of bytes that have passed through this stream. *

* NOTE: From v1.3 this method throws an ArithmeticException if the * count is greater than can be expressed by an {@code int}. * See {@link #getByteCount()} for a method using a {@code long}. * * @return the number of bytes accumulated * @throws ArithmeticException if the byte count is too large */ public int getCount() { final long result = getByteCount(); if (result > Integer.MAX_VALUE) { throw new ArithmeticException("The byte count " + result + " is too large to be converted to an int"); } return (int) result; } /** * Set the byte count back to 0. *

* NOTE: From v1.3 this method throws an ArithmeticException if the * count is greater than can be expressed by an {@code int}. * See {@link #resetByteCount()} for a method using a {@code long}. * * @return the count previous to resetting * @throws ArithmeticException if the byte count is too large */ public int resetCount() { final long result = resetByteCount(); if (result > Integer.MAX_VALUE) { throw new ArithmeticException("The byte count " + result + " is too large to be converted to an int"); } return (int) result; } /** * The number of bytes that have passed through this stream. *

* NOTE: This method is an alternative for {@code getCount()}. * It was added because that method returns an integer which will * result in incorrect count for files over 2GB. * * @return the number of bytes accumulated * @since 1.3 */ public synchronized long getByteCount() { return this.count; } /** * Set the byte count back to 0. *

* NOTE: This method is an alternative for {@code resetCount()}. * It was added because that method returns an integer which will * result in incorrect count for files over 2GB. * * @return the count previous to resetting * @since 1.3 */ public synchronized long resetByteCount() { final long tmp = this.count; this.count = 0; return tmp; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/output/DeferredFileOutputStream.java0100644 0000000 0000000 00000027356 13612062727 032670 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.file.Files; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; /** * An output stream which will retain data in memory until a specified threshold is reached, and only then commit it to * disk. If the stream is closed before the threshold is reached, the data will not be written to disk at all. *

* This class originated in FileUpload processing. In this use case, you do not know in advance the size of the file * being uploaded. If the file is small you want to store it in memory (for speed), but if the file is large you want to * store it to file (to avoid memory issues). *

*/ public class DeferredFileOutputStream extends ThresholdingOutputStream { /** * The output stream to which data will be written prior to the threshold being reached. */ private ByteArrayOutputStream memoryOutputStream; /** * The output stream to which data will be written at any given time. This will always be one of * {@code memoryOutputStream} or {@code diskOutputStream}. */ private OutputStream currentOutputStream; /** * The file to which output will be directed if the threshold is exceeded. */ private File outputFile; /** * The temporary file prefix. */ private final String prefix; /** * The temporary file suffix. */ private final String suffix; /** * The directory to use for temporary files. */ private final File directory; /** * True when close() has been called successfully. */ private boolean closed; /** * Constructs an instance of this class which will trigger an event at the specified threshold, and save data to a * file beyond that point. The initial buffer size will default to * {@value AbstractByteArrayOutputStream#DEFAULT_SIZE} bytes which is ByteArrayOutputStream's default buffer size. * * @param threshold The number of bytes at which to trigger an event. * @param outputFile The file to which data is saved beyond the threshold. */ public DeferredFileOutputStream(final int threshold, final File outputFile) { this(threshold, outputFile, null, null, null, AbstractByteArrayOutputStream.DEFAULT_SIZE); } /** * Constructs an instance of this class which will trigger an event at the specified threshold, and save data either * to a file beyond that point. * * @param threshold The number of bytes at which to trigger an event. * @param outputFile The file to which data is saved beyond the threshold. * @param prefix Prefix to use for the temporary file. * @param suffix Suffix to use for the temporary file. * @param directory Temporary file directory. * @param initialBufferSize The initial size of the in memory buffer. */ private DeferredFileOutputStream(final int threshold, final File outputFile, final String prefix, final String suffix, final File directory, final int initialBufferSize) { super(threshold); this.outputFile = outputFile; this.prefix = prefix; this.suffix = suffix; this.directory = directory; memoryOutputStream = new ByteArrayOutputStream(initialBufferSize); currentOutputStream = memoryOutputStream; } /** * Constructs an instance of this class which will trigger an event at the specified threshold, and save data to a * file beyond that point. * * @param threshold The number of bytes at which to trigger an event. * @param initialBufferSize The initial size of the in memory buffer. * @param outputFile The file to which data is saved beyond the threshold. * * @since 2.5 */ public DeferredFileOutputStream(final int threshold, final int initialBufferSize, final File outputFile) { this(threshold, outputFile, null, null, null, initialBufferSize); if (initialBufferSize < 0) { throw new IllegalArgumentException("Initial buffer size must be atleast 0."); } } /** * Constructs an instance of this class which will trigger an event at the specified threshold, and save data to a * temporary file beyond that point. * * @param threshold The number of bytes at which to trigger an event. * @param initialBufferSize The initial size of the in memory buffer. * @param prefix Prefix to use for the temporary file. * @param suffix Suffix to use for the temporary file. * @param directory Temporary file directory. * * @since 2.5 */ public DeferredFileOutputStream(final int threshold, final int initialBufferSize, final String prefix, final String suffix, final File directory) { this(threshold, null, prefix, suffix, directory, initialBufferSize); if (prefix == null) { throw new IllegalArgumentException("Temporary file prefix is missing"); } if (initialBufferSize < 0) { throw new IllegalArgumentException("Initial buffer size must be atleast 0."); } } /** * Constructs an instance of this class which will trigger an event at the specified threshold, and save data to a * temporary file beyond that point. The initial buffer size will default to 32 bytes which is * ByteArrayOutputStream's default buffer size. * * @param threshold The number of bytes at which to trigger an event. * @param prefix Prefix to use for the temporary file. * @param suffix Suffix to use for the temporary file. * @param directory Temporary file directory. * * @since 1.4 */ public DeferredFileOutputStream(final int threshold, final String prefix, final String suffix, final File directory) { this(threshold, null, prefix, suffix, directory, AbstractByteArrayOutputStream.DEFAULT_SIZE); if (prefix == null) { throw new IllegalArgumentException("Temporary file prefix is missing"); } } /** * Closes underlying output stream, and mark this as closed * * @throws IOException if an error occurs. */ @Override public void close() throws IOException { super.close(); closed = true; } /** * Returns the data for this output stream as an array of bytes, assuming that the data has been retained in memory. * If the data was written to disk, this method returns {@code null}. * * @return The data for this output stream, or {@code null} if no such data is available. */ public byte[] getData() { return memoryOutputStream != null ? memoryOutputStream.toByteArray() : null; } /** * Returns either the output file specified in the constructor or the temporary file created or null. *

* If the constructor specifying the file is used then it returns that same output file, even when threshold has not * been reached. *

* If constructor specifying a temporary file prefix/suffix is used then the temporary file created once the * threshold is reached is returned If the threshold was not reached then {@code null} is returned. * * @return The file for this output stream, or {@code null} if no such file exists. */ public File getFile() { return outputFile; } /** * Returns the current output stream. This may be memory based or disk based, depending on the current state with * respect to the threshold. * * @return The underlying output stream. * * @throws IOException if an error occurs. */ @Override protected OutputStream getStream() throws IOException { return currentOutputStream; } /** * Determines whether or not the data for this output stream has been retained in memory. * * @return {@code true} if the data is available in memory; {@code false} otherwise. */ public boolean isInMemory() { return !isThresholdExceeded(); } /** * Switches the underlying output stream from a memory based stream to one that is backed by disk. This is the point * at which we realize that too much data is being written to keep in memory, so we elect to switch to disk-based * storage. * * @throws IOException if an error occurs. */ @Override protected void thresholdReached() throws IOException { if (prefix != null) { outputFile = File.createTempFile(prefix, suffix, directory); } FileUtils.forceMkdirParent(outputFile); final OutputStream fos = Files.newOutputStream(outputFile.toPath()); try { memoryOutputStream.writeTo(fos); } catch (final IOException e) { fos.close(); throw e; } currentOutputStream = fos; memoryOutputStream = null; } /** * Gets the current contents of this byte stream as an {@link InputStream}. * If the data for this output stream has been retained in memory, the * returned stream is backed by buffers of {@code this} stream, * avoiding memory allocation and copy, thus saving space and time.
* Otherwise, the returned stream will be one that is created from the data * that has been committed to disk. * * @return the current contents of this output stream. * @throws IOException if this stream is not yet closed or an error occurs. * @see org.apache.commons.io.output.ByteArrayOutputStream#toInputStream() * * @since 2.9.0 */ public InputStream toInputStream() throws IOException { // we may only need to check if this is closed if we are working with a file // but we should force the habit of closing whether we are working with // a file or memory. if (!closed) { throw new IOException("Stream not closed"); } if (isInMemory()) { return memoryOutputStream.toInputStream(); } return Files.newInputStream(outputFile.toPath()); } /** * Writes the data from this output stream to the specified output stream, after it has been closed. * * @param outputStream output stream to write to. * @throws NullPointerException if the OutputStream is {@code null}. * @throws IOException if this stream is not yet closed or an error occurs. */ public void writeTo(final OutputStream outputStream) throws IOException { // we may only need to check if this is closed if we are working with a file // but we should force the habit of closing whether we are working with // a file or memory. if (!closed) { throw new IOException("Stream not closed"); } if (isInMemory()) { memoryOutputStream.writeTo(outputStream); } else { try (InputStream fis = Files.newInputStream(outputFile.toPath())) { IOUtils.copy(fis, outputStream); } } } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/output/DemuxOutputStream.java0100644 0000000 0000000 00000005324 13612062727 031421 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import java.io.IOException; import java.io.OutputStream; import org.apache.commons.io.IOUtils; /** * Forwards data to a stream that has been associated with this thread. * */ public class DemuxOutputStream extends OutputStream { private final InheritableThreadLocal outputStreamThreadLocal = new InheritableThreadLocal<>(); /** * Binds the specified stream to the current thread. * * @param output * the stream to bind * @return the OutputStream that was previously active */ public OutputStream bindStream(final OutputStream output) { final OutputStream stream = outputStreamThreadLocal.get(); outputStreamThreadLocal.set(output); return stream; } /** * Closes stream associated with current thread. * * @throws IOException * if an error occurs */ @SuppressWarnings("resource") // we actually close the stream here @Override public void close() throws IOException { IOUtils.close(outputStreamThreadLocal.get()); } /** * Flushes stream associated with current thread. * * @throws IOException * if an error occurs */ @Override public void flush() throws IOException { @SuppressWarnings("resource") final OutputStream output = outputStreamThreadLocal.get(); if (null != output) { output.flush(); } } /** * Writes byte to stream associated with current thread. * * @param ch * the byte to write to stream * @throws IOException * if an error occurs */ @Override public void write(final int ch) throws IOException { @SuppressWarnings("resource") final OutputStream output = outputStreamThreadLocal.get(); if (null != output) { output.write(ch); } } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/output/FileWriterWithEncoding.java0100644 0000000 0000000 00000027520 13612062727 032323 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import java.io.File; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Writer; import java.nio.charset.Charset; import java.nio.charset.CharsetEncoder; import java.nio.file.Files; import java.nio.file.StandardOpenOption; import java.util.Objects; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; /** * Writer of files that allows the encoding to be set. *

* This class provides a simple alternative to {@code FileWriter} * that allows an encoding to be set. Unfortunately, it cannot subclass * {@code FileWriter}. *

*

* By default, the file will be overwritten, but this may be changed to append. *

*

* The encoding must be specified using either the name of the {@link Charset}, * the {@link Charset}, or a {@link CharsetEncoder}. If the default encoding * is required then use the {@link java.io.FileWriter} directly, rather than * this implementation. *

* * @since 1.4 */ public class FileWriterWithEncoding extends Writer { // Cannot extend ProxyWriter, as requires writer to be // known when super() is called /** The writer to decorate. */ private final Writer out; /** * Constructs a FileWriterWithEncoding with a file encoding. * * @param fileName the name of the file to write to, not null * @param charsetName the name of the requested charset, not null * @throws NullPointerException if the file name or encoding is null * @throws IOException in case of an I/O error */ public FileWriterWithEncoding(final String fileName, final String charsetName) throws IOException { this(new File(fileName), charsetName, false); } /** * Constructs a FileWriterWithEncoding with a file encoding. * * @param fileName the name of the file to write to, not null * @param charsetName the name of the requested charset, not null * @param append true if content should be appended, false to overwrite * @throws NullPointerException if the file name or encoding is null * @throws IOException in case of an I/O error */ public FileWriterWithEncoding(final String fileName, final String charsetName, final boolean append) throws IOException { this(new File(fileName), charsetName, append); } /** * Constructs a FileWriterWithEncoding with a file encoding. * * @param fileName the name of the file to write to, not null * @param charset the charset to use, not null * @throws NullPointerException if the file name or encoding is null * @throws IOException in case of an I/O error */ public FileWriterWithEncoding(final String fileName, final Charset charset) throws IOException { this(new File(fileName), charset, false); } /** * Constructs a FileWriterWithEncoding with a file encoding. * * @param fileName the name of the file to write to, not null * @param charset the encoding to use, not null * @param append true if content should be appended, false to overwrite * @throws NullPointerException if the file name or encoding is null * @throws IOException in case of an I/O error */ public FileWriterWithEncoding(final String fileName, final Charset charset, final boolean append) throws IOException { this(new File(fileName), charset, append); } /** * Constructs a FileWriterWithEncoding with a file encoding. * * @param fileName the name of the file to write to, not null * @param encoding the encoding to use, not null * @throws NullPointerException if the file name or encoding is null * @throws IOException in case of an I/O error */ public FileWriterWithEncoding(final String fileName, final CharsetEncoder encoding) throws IOException { this(new File(fileName), encoding, false); } /** * Constructs a FileWriterWithEncoding with a file encoding. * * @param fileName the name of the file to write to, not null * @param charsetEncoder the encoding to use, not null * @param append true if content should be appended, false to overwrite * @throws NullPointerException if the file name or encoding is null * @throws IOException in case of an I/O error */ public FileWriterWithEncoding(final String fileName, final CharsetEncoder charsetEncoder, final boolean append) throws IOException { this(new File(fileName), charsetEncoder, append); } /** * Constructs a FileWriterWithEncoding with a file encoding. * * @param file the file to write to, not null * @param charsetName the name of the requested charset, not null * @throws NullPointerException if the file or encoding is null * @throws IOException in case of an I/O error */ public FileWriterWithEncoding(final File file, final String charsetName) throws IOException { this(file, charsetName, false); } /** * Constructs a FileWriterWithEncoding with a file encoding. * * @param file the file to write to, not null * @param charsetName the name of the requested charset, not null * @param append true if content should be appended, false to overwrite * @throws NullPointerException if the file or encoding is null * @throws IOException in case of an I/O error */ public FileWriterWithEncoding(final File file, final String charsetName, final boolean append) throws IOException { this.out = initWriter(file, charsetName, append); } /** * Constructs a FileWriterWithEncoding with a file encoding. * * @param file the file to write to, not null * @param charset the encoding to use, not null * @throws NullPointerException if the file or encoding is null * @throws IOException in case of an I/O error */ public FileWriterWithEncoding(final File file, final Charset charset) throws IOException { this(file, charset, false); } /** * Constructs a FileWriterWithEncoding with a file encoding. * * @param file the file to write to, not null * @param encoding the name of the requested charset, not null * @param append true if content should be appended, false to overwrite * @throws NullPointerException if the file or encoding is null * @throws IOException in case of an I/O error */ public FileWriterWithEncoding(final File file, final Charset encoding, final boolean append) throws IOException { this.out = initWriter(file, encoding, append); } /** * Constructs a FileWriterWithEncoding with a file encoding. * * @param file the file to write to, not null * @param charsetEncoder the encoding to use, not null * @throws NullPointerException if the file or encoding is null * @throws IOException in case of an I/O error */ public FileWriterWithEncoding(final File file, final CharsetEncoder charsetEncoder) throws IOException { this(file, charsetEncoder, false); } /** * Constructs a FileWriterWithEncoding with a file encoding. * * @param file the file to write to, not null * @param charsetEncoder the encoding to use, not null * @param append true if content should be appended, false to overwrite * @throws NullPointerException if the file or encoding is null * @throws IOException in case of an I/O error */ public FileWriterWithEncoding(final File file, final CharsetEncoder charsetEncoder, final boolean append) throws IOException { this.out = initWriter(file, charsetEncoder, append); } /** * Initialize the wrapped file writer. * Ensure that a cleanup occurs if the writer creation fails. * * @param file the file to be accessed * @param encoding the encoding to use - may be Charset, CharsetEncoder or String * @param append true to append * @return the initialized writer * @throws NullPointerException if the file or encoding is null * @throws IOException if an error occurs */ private static Writer initWriter(final File file, final Object encoding, final boolean append) throws IOException { Objects.requireNonNull(file, "file"); Objects.requireNonNull(encoding, "encoding"); OutputStream stream = null; final boolean fileExistedAlready = file.exists(); try { stream = Files.newOutputStream(file.toPath(), append ? StandardOpenOption.APPEND : StandardOpenOption.CREATE); if (encoding instanceof Charset) { return new OutputStreamWriter(stream, (Charset)encoding); } if (encoding instanceof CharsetEncoder) { return new OutputStreamWriter(stream, (CharsetEncoder)encoding); } return new OutputStreamWriter(stream, (String)encoding); } catch (final IOException | RuntimeException ex) { try { IOUtils.close(stream); } catch (final IOException e) { ex.addSuppressed(e); } if (!fileExistedAlready) { FileUtils.deleteQuietly(file); } throw ex; } } /** * Write a character. * @param idx the character to write * @throws IOException if an I/O error occurs. */ @Override public void write(final int idx) throws IOException { out.write(idx); } /** * Write the characters from an array. * @param chr the characters to write * @throws IOException if an I/O error occurs. */ @Override public void write(final char[] chr) throws IOException { out.write(chr); } /** * Write the specified characters from an array. * @param chr the characters to write * @param st The start offset * @param end The number of characters to write * @throws IOException if an I/O error occurs. */ @Override public void write(final char[] chr, final int st, final int end) throws IOException { out.write(chr, st, end); } /** * Write the characters from a string. * @param str the string to write * @throws IOException if an I/O error occurs. */ @Override public void write(final String str) throws IOException { out.write(str); } /** * Write the specified characters from a string. * @param str the string to write * @param st The start offset * @param end The number of characters to write * @throws IOException if an I/O error occurs. */ @Override public void write(final String str, final int st, final int end) throws IOException { out.write(str, st, end); } /** * Flush the stream. * @throws IOException if an I/O error occurs. */ @Override public void flush() throws IOException { out.flush(); } /** * Close the stream. * @throws IOException if an I/O error occurs. */ @Override public void close() throws IOException { out.close(); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/output/FilterCollectionWriter.java0100644 0000000 0000000 00000022767 13612062727 032412 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import java.io.FilterWriter; import java.io.IOException; import java.io.Writer; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; import org.apache.commons.io.IOExceptionList; import org.apache.commons.io.IOIndexedException; /** * Abstract class for writing filtered character streams to a {@link Collection} of writers. This is in contrast to * {@link FilterWriter} which is backed by a single {@link Writer}. *

* This abstract class provides default methods that pass all requests to the contained writers. Subclasses should * likely override some of these methods. *

*

* The class {@link Writer} defines method signatures with {@code throws} {@link IOException}, which in this class are * actually {@link IOExceptionList} containing a list of {@link IOIndexedException}. *

* * @since 2.7 */ public class FilterCollectionWriter extends Writer { /** * Empty and immutable collection of writers. */ protected final Collection EMPTY_WRITERS = Collections.emptyList(); /** * The underlying writers. */ protected final Collection writers; /** * Creates a new filtered collection writer. * * @param writers Writers to provide the underlying targets. */ protected FilterCollectionWriter(final Collection writers) { this.writers = writers == null ? EMPTY_WRITERS : writers; } /** * Creates a new filtered collection writer. * * @param writers Writers to provide the underlying targets. */ protected FilterCollectionWriter(final Writer... writers) { this.writers = writers == null ? EMPTY_WRITERS : Arrays.asList(writers); } /** * Adds an indexed exception to the list. * * @param causeList The target list. * @param i The index. * @param e The cause. * @return the given list or a new list on null input. */ private List add(List causeList, final int i, final IOException e) { if (causeList == null) { causeList = new ArrayList<>(); } causeList.add(new IOIndexedException(i, e)); return causeList; } @Override public Writer append(final char c) throws IOException { List causeList = null; int i = 0; for (final Writer w : writers) { if (w != null) { try { w.append(c); } catch (final IOException e) { causeList = add(causeList, i, e); } } i++; } if (notEmpty(causeList)) { throw new IOExceptionList("append", causeList); } return this; } @Override public Writer append(final CharSequence csq) throws IOException { List causeList = null; int i = 0; for (final Writer w : writers) { if (w != null) { try { w.append(csq); } catch (final IOException e) { causeList = add(causeList, i, e); } } i++; } if (notEmpty(causeList)) { throw new IOExceptionList("append", causeList); } return this; } @Override public Writer append(final CharSequence csq, final int start, final int end) throws IOException { List causeList = null; int i = 0; for (final Writer w : writers) { if (w != null) { try { w.append(csq, start, end); } catch (final IOException e) { causeList = add(causeList, i, e); } } i++; } if (notEmpty(causeList)) { throw new IOExceptionList("append", causeList); } return this; } @Override public void close() throws IOException { List causeList = null; int i = 0; for (final Writer w : writers) { if (w != null) { try { w.close(); } catch (final IOException e) { causeList = add(causeList, i, e); } } i++; } if (notEmpty(causeList)) { throw new IOExceptionList("close", causeList); } } /** * Flushes the stream. * * @exception IOException If an I/O error occurs */ @Override public void flush() throws IOException { List causeList = null; int i = 0; for (final Writer w : writers) { if (w != null) { try { w.flush(); } catch (final IOException e) { causeList = add(causeList, i, e); } } i++; } if (notEmpty(causeList)) { throw new IOExceptionList("flush", causeList); } } /** * Tests if the given list is empty in a null-safe manner. * * @param causeList the list to test. * @return true if empty or null. */ private boolean notEmpty(final List causeList) { return causeList != null && !causeList.isEmpty(); } @Override public void write(final char[] cbuf) throws IOException { List causeList = null; int i = 0; for (final Writer w : writers) { if (w != null) { try { w.write(cbuf); } catch (final IOException e) { causeList = add(causeList, i, e); } } i++; } if (notEmpty(causeList)) { throw new IOExceptionList("write", causeList); } } /** * Writes a portion of an array of characters. * * @param cbuf Buffer of characters to be written * @param off Offset from which to start reading characters * @param len Number of characters to be written * * @exception IOException If an I/O error occurs */ @Override public void write(final char[] cbuf, final int off, final int len) throws IOException { List causeList = null; int i = 0; for (final Writer w : writers) { if (w != null) { try { w.write(cbuf, off, len); } catch (final IOException e) { causeList = add(causeList, i, e); } } i++; } if (notEmpty(causeList)) { throw new IOExceptionList("write", causeList); } } /** * Writes a single character. * * @exception IOException If an I/O error occurs */ @Override public void write(final int c) throws IOException { List causeList = null; int i = 0; for (final Writer w : writers) { if (w != null) { try { w.write(c); } catch (final IOException e) { causeList = add(causeList, i, e); } } i++; } if (notEmpty(causeList)) { throw new IOExceptionList("write", causeList); } } @Override public void write(final String str) throws IOException { List causeList = null; int i = 0; for (final Writer w : writers) { if (w != null) { try { w.write(str); } catch (final IOException e) { causeList = add(causeList, i, e); } } i++; } if (notEmpty(causeList)) { throw new IOExceptionList("write", causeList); } } /** * Writes a portion of a string. * * @param str String to be written * @param off Offset from which to start reading characters * @param len Number of characters to be written * * @exception IOException If an I/O error occurs */ @Override public void write(final String str, final int off, final int len) throws IOException { List causeList = null; int i = 0; for (final Writer w : writers) { if (w != null) { try { w.write(str, off, len); } catch (final IOException e) { causeList = add(causeList, i, e); } } i++; } if (notEmpty(causeList)) { throw new IOExceptionList("write", causeList); } } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/output/LockableFileWriter.java0100644 0000000 0000000 00000030502 13612062727 031447 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.Writer; import java.nio.charset.Charset; import org.apache.commons.io.Charsets; import org.apache.commons.io.FileUtils; /** * FileWriter that will create and honor lock files to allow simple * cross thread file lock handling. *

* This class provides a simple alternative to {@code FileWriter} * that will use a lock file to prevent duplicate writes. *

*

* Note: The lock file is deleted when {@link #close()} is called * - or if the main file cannot be opened initially. * In the (unlikely) event that the lock file cannot be deleted, * an exception is thrown. *

*

* By default, the file will be overwritten, but this may be changed to append. * The lock directory may be specified, but defaults to the system property * {@code java.io.tmpdir}. * The encoding may also be specified, and defaults to the platform default. *

*/ public class LockableFileWriter extends Writer { // Cannot extend ProxyWriter, as requires writer to be // known when super() is called /** The extension for the lock file. */ private static final String LCK = ".lck"; /** The writer to decorate. */ private final Writer out; /** The lock file. */ private final File lockFile; /** * Constructs a LockableFileWriter. * If the file exists, it is overwritten. * * @param fileName the file to write to, not null * @throws NullPointerException if the file is null * @throws IOException in case of an I/O error */ public LockableFileWriter(final String fileName) throws IOException { this(fileName, false, null); } /** * Constructs a LockableFileWriter. * * @param fileName file to write to, not null * @param append true if content should be appended, false to overwrite * @throws NullPointerException if the file is null * @throws IOException in case of an I/O error */ public LockableFileWriter(final String fileName, final boolean append) throws IOException { this(fileName, append, null); } /** * Constructs a LockableFileWriter. * * @param fileName the file to write to, not null * @param append true if content should be appended, false to overwrite * @param lockDir the directory in which the lock file should be held * @throws NullPointerException if the file is null * @throws IOException in case of an I/O error */ public LockableFileWriter(final String fileName, final boolean append, final String lockDir) throws IOException { this(new File(fileName), append, lockDir); } /** * Constructs a LockableFileWriter. * If the file exists, it is overwritten. * * @param file the file to write to, not null * @throws NullPointerException if the file is null * @throws IOException in case of an I/O error */ public LockableFileWriter(final File file) throws IOException { this(file, false, null); } /** * Constructs a LockableFileWriter. * * @param file the file to write to, not null * @param append true if content should be appended, false to overwrite * @throws NullPointerException if the file is null * @throws IOException in case of an I/O error */ public LockableFileWriter(final File file, final boolean append) throws IOException { this(file, append, null); } /** * Constructs a LockableFileWriter. * * @param file the file to write to, not null * @param append true if content should be appended, false to overwrite * @param lockDir the directory in which the lock file should be held * @throws NullPointerException if the file is null * @throws IOException in case of an I/O error * @deprecated 2.5 use {@link #LockableFileWriter(File, Charset, boolean, String)} instead */ @Deprecated public LockableFileWriter(final File file, final boolean append, final String lockDir) throws IOException { this(file, Charset.defaultCharset(), append, lockDir); } /** * Constructs a LockableFileWriter with a file encoding. * * @param file the file to write to, not null * @param charset the charset to use, null means platform default * @throws NullPointerException if the file is null * @throws IOException in case of an I/O error * @since 2.3 */ public LockableFileWriter(final File file, final Charset charset) throws IOException { this(file, charset, false, null); } /** * Constructs a LockableFileWriter with a file encoding. * * @param file the file to write to, not null * @param charsetName the name of the requested charset, null means platform default * @throws NullPointerException if the file is null * @throws IOException in case of an I/O error * @throws java.nio.charset.UnsupportedCharsetException * thrown instead of {@link java.io.UnsupportedEncodingException} in version 2.2 if the encoding is not * supported. */ public LockableFileWriter(final File file, final String charsetName) throws IOException { this(file, charsetName, false, null); } /** * Constructs a LockableFileWriter with a file encoding. * * @param file the file to write to, not null * @param charset the name of the requested charset, null means platform default * @param append true if content should be appended, false to overwrite * @param lockDir the directory in which the lock file should be held * @throws NullPointerException if the file is null * @throws IOException in case of an I/O error * @since 2.3 */ public LockableFileWriter(File file, final Charset charset, final boolean append, String lockDir) throws IOException { // init file to create/append file = file.getAbsoluteFile(); if (file.getParentFile() != null) { FileUtils.forceMkdir(file.getParentFile()); } if (file.isDirectory()) { throw new IOException("File specified is a directory"); } // init lock file if (lockDir == null) { lockDir = System.getProperty("java.io.tmpdir"); } final File lockDirFile = new File(lockDir); FileUtils.forceMkdir(lockDirFile); testLockDir(lockDirFile); lockFile = new File(lockDirFile, file.getName() + LCK); // check if locked createLock(); // init wrapped writer out = initWriter(file, charset, append); } /** * Constructs a LockableFileWriter with a file encoding. * * @param file the file to write to, not null * @param charsetName the encoding to use, null means platform default * @param append true if content should be appended, false to overwrite * @param lockDir the directory in which the lock file should be held * @throws NullPointerException if the file is null * @throws IOException in case of an I/O error * @throws java.nio.charset.UnsupportedCharsetException * thrown instead of {@link java.io.UnsupportedEncodingException} in version 2.2 if the encoding is not * supported. */ public LockableFileWriter(final File file, final String charsetName, final boolean append, final String lockDir) throws IOException { this(file, Charsets.toCharset(charsetName), append, lockDir); } /** * Tests that we can write to the lock directory. * * @param lockDir the File representing the lock directory * @throws IOException if we cannot write to the lock directory * @throws IOException if we cannot find the lock file */ private void testLockDir(final File lockDir) throws IOException { if (!lockDir.exists()) { throw new IOException( "Could not find lockDir: " + lockDir.getAbsolutePath()); } if (!lockDir.canWrite()) { throw new IOException( "Could not write to lockDir: " + lockDir.getAbsolutePath()); } } /** * Creates the lock file. * * @throws IOException if we cannot create the file */ private void createLock() throws IOException { synchronized (LockableFileWriter.class) { if (!lockFile.createNewFile()) { throw new IOException("Can't write file, lock " + lockFile.getAbsolutePath() + " exists"); } lockFile.deleteOnExit(); } } /** * Initializes the wrapped file writer. * Ensure that a cleanup occurs if the writer creation fails. * * @param file the file to be accessed * @param charset the charset to use * @param append true to append * @return The initialized writer * @throws IOException if an error occurs */ private Writer initWriter(final File file, final Charset charset, final boolean append) throws IOException { final boolean fileExistedAlready = file.exists(); try { return new OutputStreamWriter(new FileOutputStream(file.getAbsolutePath(), append), Charsets.toCharset(charset)); } catch (final IOException | RuntimeException ex) { FileUtils.deleteQuietly(lockFile); if (!fileExistedAlready) { FileUtils.deleteQuietly(file); } throw ex; } } /** * Closes the file writer and deletes the lock file. * * @throws IOException if an I/O error occurs. */ @Override public void close() throws IOException { try { out.close(); } finally { FileUtils.delete(lockFile); } } /** * Writes a character. * @param c the character to write * @throws IOException if an I/O error occurs. */ @Override public void write(final int c) throws IOException { out.write(c); } /** * Writes the characters from an array. * @param cbuf the characters to write * @throws IOException if an I/O error occurs. */ @Override public void write(final char[] cbuf) throws IOException { out.write(cbuf); } /** * Writes the specified characters from an array. * @param cbuf the characters to write * @param off The start offset * @param len The number of characters to write * @throws IOException if an I/O error occurs. */ @Override public void write(final char[] cbuf, final int off, final int len) throws IOException { out.write(cbuf, off, len); } /** * Writes the characters from a string. * @param str the string to write * @throws IOException if an I/O error occurs. */ @Override public void write(final String str) throws IOException { out.write(str); } /** * Writes the specified characters from a string. * @param str the string to write * @param off The start offset * @param len The number of characters to write * @throws IOException if an I/O error occurs. */ @Override public void write(final String str, final int off, final int len) throws IOException { out.write(str, off, len); } /** * Flushes the stream. * @throws IOException if an I/O error occurs. */ @Override public void flush() throws IOException { out.flush(); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/output/NullAppendable.java0100644 0000000 0000000 00000003251 13612062727 030625 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import java.io.IOException; /** * Appends all data to the famous /dev/null. *

* This Appendable has no destination (file/socket etc.) and all characters written to it are ignored and lost. *

* * @since 2.8.0 */ public class NullAppendable implements Appendable { /** * A singleton. */ public static final NullAppendable INSTANCE = new NullAppendable(); /** Use the singleton. */ private NullAppendable() { // no instances. } @Override public Appendable append(final char c) throws IOException { return this; } @Override public Appendable append(final CharSequence csq) throws IOException { return this; } @Override public Appendable append(final CharSequence csq, final int start, final int end) throws IOException { return this; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/output/NullOutputStream.java0100644 0000000 0000000 00000004300 13612062727 031242 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import java.io.IOException; import java.io.OutputStream; /** * Writes all data to the famous /dev/null. *

* This output stream has no destination (file/socket etc.) and all bytes written to it are ignored and lost. *

*/ public class NullOutputStream extends OutputStream { /** * Deprecated in favor of {@link #NULL_OUTPUT_STREAM}. * * TODO: Will be private in 3.0. * * @deprecated Use {@link #NULL_OUTPUT_STREAM}. */ @Deprecated public NullOutputStream() { } /** * The singleton. */ public static final NullOutputStream NULL_OUTPUT_STREAM = new NullOutputStream(); /** * Does nothing - output to {@code /dev/null}. * * @param b The bytes to write * @param off The start offset * @param len The number of bytes to write */ @Override public void write(final byte[] b, final int off, final int len) { // To /dev/null } /** * Does nothing - output to {@code /dev/null}. * * @param b The byte to write */ @Override public void write(final int b) { // To /dev/null } /** * Does nothing - output to {@code /dev/null}. * * @param b The bytes to write * @throws IOException never */ @Override public void write(final byte[] b) throws IOException { // To /dev/null } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/output/NullPrintStream.java0100644 0000000 0000000 00000002712 13612062727 031043 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import java.io.PrintStream; /** * Writes all data to the famous /dev/null. *

* This print stream has no destination (file/socket etc.) and all bytes written to it are ignored and lost. *

* * @since 2.7 */ public class NullPrintStream extends PrintStream { /** * The singleton instance. */ public static final NullPrintStream NULL_PRINT_STREAM = new NullPrintStream(); /** * Constructs an instance. */ public NullPrintStream() { // Relies on the default charset which is OK since we are not actually writing. super(NullOutputStream.NULL_OUTPUT_STREAM); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/output/NullWriter.java0100644 0000000 0000000 00000007140 13612062727 030047 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import java.io.Writer; /** * Writes all data to the famous /dev/null. *

* This {@code Writer} has no destination (file/socket etc.) and all characters written to it are ignored and lost. *

*/ public class NullWriter extends Writer { /** * A singleton. */ public static final NullWriter NULL_WRITER = new NullWriter(); /** * Constructs a new NullWriter. */ public NullWriter() { } /** * Does nothing - output to {@code /dev/null}. * @param c The character to write * @return this writer * @since 2.0 */ @Override public Writer append(final char c) { //to /dev/null return this; } /** * Does nothing - output to {@code /dev/null}. * @param csq The character sequence to write * @param start The index of the first character to write * @param end The index of the first character to write (exclusive) * @return this writer * @since 2.0 */ @Override public Writer append(final CharSequence csq, final int start, final int end) { //to /dev/null return this; } /** * Does nothing - output to {@code /dev/null}. * @param csq The character sequence to write * @return this writer * @since 2.0 */ @Override public Writer append(final CharSequence csq) { //to /dev/null return this; } /** * Does nothing - output to {@code /dev/null}. * @param idx The character to write */ @Override public void write(final int idx) { //to /dev/null } /** * Does nothing - output to {@code /dev/null}. * @param chr The characters to write */ @Override public void write(final char[] chr) { //to /dev/null } /** * Does nothing - output to {@code /dev/null}. * @param chr The characters to write * @param st The start offset * @param end The number of characters to write */ @Override public void write(final char[] chr, final int st, final int end) { //to /dev/null } /** * Does nothing - output to {@code /dev/null}. * @param str The string to write */ @Override public void write(final String str) { //to /dev/null } /** * Does nothing - output to {@code /dev/null}. * @param str The string to write * @param st The start offset * @param end The number of characters to write */ @Override public void write(final String str, final int st, final int end) { //to /dev/null } /** @see java.io.Writer#flush() */ @Override public void flush() { //to /dev/null } /** @see java.io.Writer#close() */ @Override public void close() { //to /dev/null } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/output/ProxyCollectionWriter.java0100644 0000000 0000000 00000021373 13612062727 032276 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import java.io.FilterWriter; import java.io.IOException; import java.io.Writer; import java.util.Collection; import org.apache.commons.io.IOUtils; /** * A Proxy stream collection which acts as expected, that is it passes the method calls on to the proxied streams and * doesn't change which methods are being called. It is an alternative base class to {@link FilterWriter} and * {@link FilterCollectionWriter} to increase reusability, because FilterWriter changes the methods being called, such * as {@code write(char[])} to {@code write(char[], int, int)} and {@code write(String)} to * {@code write(String, int, int)}. This is in contrast to {@link ProxyWriter} which is backed by a single * {@link Writer}. * * @since 2.7 */ public class ProxyCollectionWriter extends FilterCollectionWriter { /** * Creates a new proxy collection writer. * * @param writers Writers object to provide the underlying targets. */ public ProxyCollectionWriter(final Collection writers) { super(writers); } /** * Creates a new proxy collection writer. * * @param writers Writers to provide the underlying targets. */ public ProxyCollectionWriter(final Writer... writers) { super(writers); } /** * Invoked by the write methods after the proxied call has returned successfully. The number of chars written (1 for * the {@link #write(int)} method, buffer length for {@link #write(char[])}, etc.) is given as an argument. *

* Subclasses can override this method to add common post-processing functionality without having to override all * the write methods. The default implementation does nothing. *

* * @param n number of chars written * @throws IOException if the post-processing fails */ @SuppressWarnings("unused") // Possibly thrown from subclasses. protected void afterWrite(final int n) throws IOException { // noop } /** * Invokes the delegates' {@code append(char)} methods. * * @param c The character to write * @return this writer * @throws IOException if an I/O error occurs. * @since 2.0 */ @Override public Writer append(final char c) throws IOException { try { beforeWrite(1); super.append(c); afterWrite(1); } catch (final IOException e) { handleIOException(e); } return this; } /** * Invokes the delegates' {@code append(CharSequence)} methods. * * @param csq The character sequence to write * @return this writer * @throws IOException if an I/O error occurs. */ @Override public Writer append(final CharSequence csq) throws IOException { try { final int len = IOUtils.length(csq); beforeWrite(len); super.append(csq); afterWrite(len); } catch (final IOException e) { handleIOException(e); } return this; } /** * Invokes the delegates' {@code append(CharSequence, int, int)} methods. * * @param csq The character sequence to write * @param start The index of the first character to write * @param end The index of the first character to write (exclusive) * @return this writer * @throws IOException if an I/O error occurs. */ @Override public Writer append(final CharSequence csq, final int start, final int end) throws IOException { try { beforeWrite(end - start); super.append(csq, start, end); afterWrite(end - start); } catch (final IOException e) { handleIOException(e); } return this; } /** * Invoked by the write methods before the call is proxied. The number of chars to be written (1 for the * {@link #write(int)} method, buffer length for {@link #write(char[])}, etc.) is given as an argument. *

* Subclasses can override this method to add common pre-processing functionality without having to override all the * write methods. The default implementation does nothing. *

* * @param n number of chars to be written * @throws IOException if the pre-processing fails */ @SuppressWarnings("unused") // Possibly thrown from subclasses. protected void beforeWrite(final int n) throws IOException { // noop } /** * Invokes the delegate's {@code close()} method. * * @throws IOException if an I/O error occurs. */ @Override public void close() throws IOException { try { super.close(); } catch (final IOException e) { handleIOException(e); } } /** * Invokes the delegate's {@code flush()} method. * * @throws IOException if an I/O error occurs. */ @Override public void flush() throws IOException { try { super.flush(); } catch (final IOException e) { handleIOException(e); } } /** * Handle any IOExceptions thrown. *

* This method provides a point to implement custom exception handling. The default behavior is to re-throw the * exception. *

* * @param e The IOException thrown * @throws IOException if an I/O error occurs. */ protected void handleIOException(final IOException e) throws IOException { throw e; } /** * Invokes the delegate's {@code write(char[])} method. * * @param cbuf the characters to write * @throws IOException if an I/O error occurs. */ @Override public void write(final char[] cbuf) throws IOException { try { final int len = IOUtils.length(cbuf); beforeWrite(len); super.write(cbuf); afterWrite(len); } catch (final IOException e) { handleIOException(e); } } /** * Invokes the delegate's {@code write(char[], int, int)} method. * * @param cbuf the characters to write * @param off The start offset * @param len The number of characters to write * @throws IOException if an I/O error occurs. */ @Override public void write(final char[] cbuf, final int off, final int len) throws IOException { try { beforeWrite(len); super.write(cbuf, off, len); afterWrite(len); } catch (final IOException e) { handleIOException(e); } } /** * Invokes the delegate's {@code write(int)} method. * * @param c the character to write * @throws IOException if an I/O error occurs. */ @Override public void write(final int c) throws IOException { try { beforeWrite(1); super.write(c); afterWrite(1); } catch (final IOException e) { handleIOException(e); } } /** * Invokes the delegate's {@code write(String)} method. * * @param str the string to write * @throws IOException if an I/O error occurs. */ @Override public void write(final String str) throws IOException { try { final int len = IOUtils.length(str); beforeWrite(len); super.write(str); afterWrite(len); } catch (final IOException e) { handleIOException(e); } } /** * Invokes the delegate's {@code write(String)} method. * * @param str the string to write * @param off The start offset * @param len The number of characters to write * @throws IOException if an I/O error occurs. */ @Override public void write(final String str, final int off, final int len) throws IOException { try { beforeWrite(len); super.write(str, off, len); afterWrite(len); } catch (final IOException e) { handleIOException(e); } } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/output/ProxyOutputStream.java0100644 0000000 0000000 00000012755 13612062727 031466 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import java.io.FilterOutputStream; import java.io.IOException; import java.io.OutputStream; import org.apache.commons.io.IOUtils; /** * A Proxy stream which acts as expected, that is it passes the method * calls on to the proxied stream and doesn't change which methods are * being called. It is an alternative base class to FilterOutputStream * to increase reusability. *

* See the protected methods for ways in which a subclass can easily decorate * a stream with custom pre-, post- or error processing functionality. *

* */ public class ProxyOutputStream extends FilterOutputStream { /** * Constructs a new ProxyOutputStream. * * @param proxy the OutputStream to delegate to */ public ProxyOutputStream(final OutputStream proxy) { super(proxy); // the proxy is stored in a protected superclass variable named 'out' } /** * Invokes the delegate's {@code write(int)} method. * @param idx the byte to write * @throws IOException if an I/O error occurs. */ @Override public void write(final int idx) throws IOException { try { beforeWrite(1); out.write(idx); afterWrite(1); } catch (final IOException e) { handleIOException(e); } } /** * Invokes the delegate's {@code write(byte[])} method. * @param bts the bytes to write * @throws IOException if an I/O error occurs. */ @Override public void write(final byte[] bts) throws IOException { try { final int len = IOUtils.length(bts); beforeWrite(len); out.write(bts); afterWrite(len); } catch (final IOException e) { handleIOException(e); } } /** * Invokes the delegate's {@code write(byte[])} method. * @param bts the bytes to write * @param st The start offset * @param end The number of bytes to write * @throws IOException if an I/O error occurs. */ @Override public void write(final byte[] bts, final int st, final int end) throws IOException { try { beforeWrite(end); out.write(bts, st, end); afterWrite(end); } catch (final IOException e) { handleIOException(e); } } /** * Invokes the delegate's {@code flush()} method. * @throws IOException if an I/O error occurs. */ @Override public void flush() throws IOException { try { out.flush(); } catch (final IOException e) { handleIOException(e); } } /** * Invokes the delegate's {@code close()} method. * @throws IOException if an I/O error occurs. */ @Override public void close() throws IOException { IOUtils.close(out, this::handleIOException); } /** * Invoked by the write methods before the call is proxied. The number * of bytes to be written (1 for the {@link #write(int)} method, buffer * length for {@link #write(byte[])}, etc.) is given as an argument. *

* Subclasses can override this method to add common pre-processing * functionality without having to override all the write methods. * The default implementation does nothing. * * @since 2.0 * @param n number of bytes to be written * @throws IOException if the pre-processing fails */ @SuppressWarnings("unused") // Possibly thrown from subclasses. protected void beforeWrite(final int n) throws IOException { // noop } /** * Invoked by the write methods after the proxied call has returned * successfully. The number of bytes written (1 for the * {@link #write(int)} method, buffer length for {@link #write(byte[])}, * etc.) is given as an argument. *

* Subclasses can override this method to add common post-processing * functionality without having to override all the write methods. * The default implementation does nothing. * * @since 2.0 * @param n number of bytes written * @throws IOException if the post-processing fails */ @SuppressWarnings("unused") // Possibly thrown from subclasses. protected void afterWrite(final int n) throws IOException { // noop } /** * Handle any IOExceptions thrown. *

* This method provides a point to implement custom exception * handling. The default behavior is to re-throw the exception. * @param e The IOException thrown * @throws IOException if an I/O error occurs. * @since 2.0 */ protected void handleIOException(final IOException e) throws IOException { throw e; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/output/ProxyWriter.java0100644 0000000 0000000 00000020433 13612062727 030256 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import java.io.FilterWriter; import java.io.IOException; import java.io.Writer; import org.apache.commons.io.IOUtils; /** * A Proxy stream which acts as expected, that is it passes the method calls on to the proxied stream and doesn't * change which methods are being called. It is an alternative base class to FilterWriter to increase reusability, * because FilterWriter changes the methods being called, such as {@code write(char[]) to write(char[], int, int)} * and {@code write(String) to write(String, int, int)}. */ public class ProxyWriter extends FilterWriter { /** * Constructs a new ProxyWriter. * * @param proxy the Writer to delegate to */ public ProxyWriter(final Writer proxy) { super(proxy); // the proxy is stored in a protected superclass variable named 'out' } /** * Invokes the delegate's {@code append(char)} method. * @param c The character to write * @return this writer * @throws IOException if an I/O error occurs. * @since 2.0 */ @Override public Writer append(final char c) throws IOException { try { beforeWrite(1); out.append(c); afterWrite(1); } catch (final IOException e) { handleIOException(e); } return this; } /** * Invokes the delegate's {@code append(CharSequence, int, int)} method. * @param csq The character sequence to write * @param start The index of the first character to write * @param end The index of the first character to write (exclusive) * @return this writer * @throws IOException if an I/O error occurs. * @since 2.0 */ @Override public Writer append(final CharSequence csq, final int start, final int end) throws IOException { try { beforeWrite(end - start); out.append(csq, start, end); afterWrite(end - start); } catch (final IOException e) { handleIOException(e); } return this; } /** * Invokes the delegate's {@code append(CharSequence)} method. * @param csq The character sequence to write * @return this writer * @throws IOException if an I/O error occurs. * @since 2.0 */ @Override public Writer append(final CharSequence csq) throws IOException { try { final int len = IOUtils.length(csq); beforeWrite(len); out.append(csq); afterWrite(len); } catch (final IOException e) { handleIOException(e); } return this; } /** * Invokes the delegate's {@code write(int)} method. * @param c the character to write * @throws IOException if an I/O error occurs. */ @Override public void write(final int c) throws IOException { try { beforeWrite(1); out.write(c); afterWrite(1); } catch (final IOException e) { handleIOException(e); } } /** * Invokes the delegate's {@code write(char[])} method. * @param cbuf the characters to write * @throws IOException if an I/O error occurs. */ @Override public void write(final char[] cbuf) throws IOException { try { final int len = IOUtils.length(cbuf); beforeWrite(len); out.write(cbuf); afterWrite(len); } catch (final IOException e) { handleIOException(e); } } /** * Invokes the delegate's {@code write(char[], int, int)} method. * @param cbuf the characters to write * @param off The start offset * @param len The number of characters to write * @throws IOException if an I/O error occurs. */ @Override public void write(final char[] cbuf, final int off, final int len) throws IOException { try { beforeWrite(len); out.write(cbuf, off, len); afterWrite(len); } catch (final IOException e) { handleIOException(e); } } /** * Invokes the delegate's {@code write(String)} method. * @param str the string to write * @throws IOException if an I/O error occurs. */ @Override public void write(final String str) throws IOException { try { final int len = IOUtils.length(str); beforeWrite(len); out.write(str); afterWrite(len); } catch (final IOException e) { handleIOException(e); } } /** * Invokes the delegate's {@code write(String)} method. * @param str the string to write * @param off The start offset * @param len The number of characters to write * @throws IOException if an I/O error occurs. */ @Override public void write(final String str, final int off, final int len) throws IOException { try { beforeWrite(len); out.write(str, off, len); afterWrite(len); } catch (final IOException e) { handleIOException(e); } } /** * Invokes the delegate's {@code flush()} method. * @throws IOException if an I/O error occurs. */ @Override public void flush() throws IOException { try { out.flush(); } catch (final IOException e) { handleIOException(e); } } /** * Invokes the delegate's {@code close()} method. * @throws IOException if an I/O error occurs. */ @Override public void close() throws IOException { IOUtils.close(out, this::handleIOException); } /** * Invoked by the write methods before the call is proxied. The number * of chars to be written (1 for the {@link #write(int)} method, buffer * length for {@link #write(char[])}, etc.) is given as an argument. *

* Subclasses can override this method to add common pre-processing * functionality without having to override all the write methods. * The default implementation does nothing. *

* * @since 2.0 * @param n number of chars to be written * @throws IOException if the pre-processing fails */ @SuppressWarnings("unused") // Possibly thrown from subclasses. protected void beforeWrite(final int n) throws IOException { // noop } /** * Invoked by the write methods after the proxied call has returned * successfully. The number of chars written (1 for the * {@link #write(int)} method, buffer length for {@link #write(char[])}, * etc.) is given as an argument. *

* Subclasses can override this method to add common post-processing * functionality without having to override all the write methods. * The default implementation does nothing. *

* * @since 2.0 * @param n number of chars written * @throws IOException if the post-processing fails */ @SuppressWarnings("unused") // Possibly thrown from subclasses. protected void afterWrite(final int n) throws IOException { // noop } /** * Handle any IOExceptions thrown. *

* This method provides a point to implement custom exception * handling. The default behavior is to re-throw the exception. *

* * @param e The IOException thrown * @throws IOException if an I/O error occurs. * @since 2.0 */ protected void handleIOException(final IOException e) throws IOException { throw e; } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/output/QueueOutputStream.java0100644 0000000 0000000 00000007015 13612062727 031422 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import org.apache.commons.io.input.QueueInputStream; import java.io.InterruptedIOException; import java.io.OutputStream; import java.io.PipedInputStream; import java.io.PipedOutputStream; import java.util.Objects; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; /** * Simple alternative to JDK {@link java.io.PipedOutputStream}; queue input stream provides what's written in queue * output stream. *

* Example usage: *

* *
 * QueueOutputStream outputStream = new QueueOutputStream();
 * QueueInputStream inputStream = outputStream.newPipeInputStream();
 *
 * outputStream.write("hello world".getBytes(UTF_8));
 * inputStream.read();
 * 
* * Unlike JDK {@link PipedInputStream} and {@link PipedOutputStream}, queue input/output streams may be used safely in a * single thread or multiple threads. Also, unlike JDK classes, no special meaning is attached to initial or current * thread. Instances can be used longer after initial threads exited. *

* Closing a {@code QueueOutputStream} has no effect. The methods in this class can be called after the stream has been * closed without generating an {@code IOException}. *

* * @see QueueInputStream * @since 2.9.0 */ public class QueueOutputStream extends OutputStream { private final BlockingQueue blockingQueue; /** * Constructs a new instance with no limit to internal buffer size. */ public QueueOutputStream() { this(new LinkedBlockingQueue<>()); } /** * Constructs a new instance with given buffer. * * @param blockingQueue backing queue for the stream */ public QueueOutputStream(final BlockingQueue blockingQueue) { this.blockingQueue = Objects.requireNonNull(blockingQueue, "blockingQueue"); } /** * Creates a new QueueInputStream instance connected to this. Writes to this output stream will be visible to the * input stream. * * @return QueueInputStream connected to this stream */ public QueueInputStream newQueueInputStream() { return new QueueInputStream(blockingQueue); } /** * Writes a single byte. * * @throws InterruptedIOException if the thread is interrupted while writing to the queue. */ @Override public void write(final int b) throws InterruptedIOException { try { blockingQueue.put(0xFF & b); } catch (final InterruptedException e) { Thread.currentThread().interrupt(); final InterruptedIOException interruptedIoException = new InterruptedIOException(); interruptedIoException.initCause(e); throw interruptedIoException; } } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/output/StringBuilderWriter.java0100644 0000000 0000000 00000011157 13612062727 031715 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import java.io.Serializable; import java.io.Writer; /** * {@link Writer} implementation that outputs to a {@link StringBuilder}. *

* NOTE: This implementation, as an alternative to * {@code java.io.StringWriter}, provides an un-synchronized * (i.e. for use in a single thread) implementation for better performance. * For safe usage with multiple {@link Thread}s then * {@code java.io.StringWriter} should be used. *

* * @since 2.0 */ public class StringBuilderWriter extends Writer implements Serializable { private static final long serialVersionUID = -146927496096066153L; private final StringBuilder builder; /** * Constructs a new {@link StringBuilder} instance with default capacity. */ public StringBuilderWriter() { this.builder = new StringBuilder(); } /** * Constructs a new {@link StringBuilder} instance with the specified capacity. * * @param capacity The initial capacity of the underlying {@link StringBuilder} */ public StringBuilderWriter(final int capacity) { this.builder = new StringBuilder(capacity); } /** * Constructs a new instance with the specified {@link StringBuilder}. * *

If {@code builder} is null a new instance with default capacity will be created.

* * @param builder The String builder. May be null. */ public StringBuilderWriter(final StringBuilder builder) { this.builder = builder != null ? builder : new StringBuilder(); } /** * Appends a single character to this Writer. * * @param value The character to append * @return This writer instance */ @Override public Writer append(final char value) { builder.append(value); return this; } /** * Appends a character sequence to this Writer. * * @param value The character to append * @return This writer instance */ @Override public Writer append(final CharSequence value) { builder.append(value); return this; } /** * Appends a portion of a character sequence to the {@link StringBuilder}. * * @param value The character to append * @param start The index of the first character * @param end The index of the last character + 1 * @return This writer instance */ @Override public Writer append(final CharSequence value, final int start, final int end) { builder.append(value, start, end); return this; } /** * Closing this writer has no effect. */ @Override public void close() { // no-op } /** * Flushing this writer has no effect. */ @Override public void flush() { // no-op } /** * Writes a String to the {@link StringBuilder}. * * @param value The value to write */ @Override public void write(final String value) { if (value != null) { builder.append(value); } } /** * Writes a portion of a character array to the {@link StringBuilder}. * * @param value The value to write * @param offset The index of the first character * @param length The number of characters to write */ @Override public void write(final char[] value, final int offset, final int length) { if (value != null) { builder.append(value, offset, length); } } /** * Returns the underlying builder. * * @return The underlying builder */ public StringBuilder getBuilder() { return builder; } /** * Returns {@link StringBuilder#toString()}. * * @return The contents of the String builder. */ @Override public String toString() { return builder.toString(); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/output/TaggedOutputStream.java0100644 0000000 0000000 00000010005 13612062727 031522 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import java.io.IOException; import java.io.OutputStream; import java.io.Serializable; import java.util.UUID; import org.apache.commons.io.TaggedIOException; /** * An output stream decorator that tags potential exceptions so that the * stream that caused the exception can easily be identified. This is * done by using the {@link TaggedIOException} class to wrap all thrown * {@link IOException}s. See below for an example of using this class. *
 * TaggedOutputStream stream = new TaggedOutputStream(...);
 * try {
 *     // Processing that may throw an IOException either from this stream
 *     // or from some other IO activity like temporary files, etc.
 *     writeToStream(stream);
 * } catch (IOException e) {
 *     if (stream.isCauseOf(e)) {
 *         // The exception was caused by this stream.
 *         // Use e.getCause() to get the original exception.
 *     } else {
 *         // The exception was caused by something else.
 *     }
 * }
 * 
*

* Alternatively, the {@link #throwIfCauseOf(Exception)} method can be * used to let higher levels of code handle the exception caused by this * stream while other processing errors are being taken care of at this * lower level. *

*
 * TaggedOutputStream stream = new TaggedOutputStream(...);
 * try {
 *     writeToStream(stream);
 * } catch (IOException e) {
 *     stream.throwIfCauseOf(e);
 *     // ... or process the exception that was caused by something else
 * }
 * 
* * @see TaggedIOException * @since 2.0 */ public class TaggedOutputStream extends ProxyOutputStream { /** * The unique tag associated with exceptions from stream. */ private final Serializable tag = UUID.randomUUID(); /** * Creates a tagging decorator for the given output stream. * * @param proxy output stream to be decorated */ public TaggedOutputStream(final OutputStream proxy) { super(proxy); } /** * Tests if the given exception was caused by this stream. * * @param exception an exception * @return {@code true} if the exception was thrown by this stream, * {@code false} otherwise */ public boolean isCauseOf(final Exception exception) { return TaggedIOException.isTaggedWith(exception, tag); } /** * Re-throws the original exception thrown by this stream. This method * first checks whether the given exception is a {@link TaggedIOException} * wrapper created by this decorator, and then unwraps and throws the * original wrapped exception. Returns normally if the exception was * not thrown by this stream. * * @param exception an exception * @throws IOException original exception, if any, thrown by this stream */ public void throwIfCauseOf(final Exception exception) throws IOException { TaggedIOException.throwCauseIfTaggedWith(exception, tag); } /** * Tags any IOExceptions thrown, wrapping and re-throwing. * * @param e The IOException thrown * @throws IOException if an I/O error occurs. */ @Override protected void handleIOException(final IOException e) throws IOException { throw new TaggedIOException(e, tag); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/output/TaggedWriter.java0100644 0000000 0000000 00000007671 13612062727 030341 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import java.io.IOException; import java.io.Serializable; import java.io.Writer; import java.util.UUID; import org.apache.commons.io.TaggedIOException; /** * A writer decorator that tags potential exceptions so that the * reader that caused the exception can easily be identified. This is * done by using the {@link TaggedIOException} class to wrap all thrown * {@link IOException}s. See below for an example of using this class. *
 * TaggedReader reader = new TaggedReader(...);
 * try {
 *     // Processing that may throw an IOException either from this reader
 *     // or from some other IO activity like temporary files, etc.
 *     writeToWriter(writer);
 * } catch (IOException e) {
 *     if (writer.isCauseOf(e)) {
 *         // The exception was caused by this writer.
 *         // Use e.getCause() to get the original exception.
 *     } else {
 *         // The exception was caused by something else.
 *     }
 * }
 * 
*

* Alternatively, the {@link #throwIfCauseOf(Exception)} method can be * used to let higher levels of code handle the exception caused by this * writer while other processing errors are being taken care of at this * lower level. *

*
 * TaggedWriter writer = new TaggedWriter(...);
 * try {
 *     writeToWriter(writer);
 * } catch (IOException e) {
 *     writer.throwIfCauseOf(e);
 *     // ... or process the exception that was caused by something else
 * }
 * 
* * @see TaggedIOException * @since 2.0 */ public class TaggedWriter extends ProxyWriter { /** * The unique tag associated with exceptions from writer. */ private final Serializable tag = UUID.randomUUID(); /** * Creates a tagging decorator for the given writer. * * @param proxy writer to be decorated */ public TaggedWriter(final Writer proxy) { super(proxy); } /** * Tests if the given exception was caused by this writer. * * @param exception an exception * @return {@code true} if the exception was thrown by this writer, * {@code false} otherwise */ public boolean isCauseOf(final Exception exception) { return TaggedIOException.isTaggedWith(exception, tag); } /** * Re-throws the original exception thrown by this writer. This method * first checks whether the given exception is a {@link TaggedIOException} * wrapper created by this decorator, and then unwraps and throws the * original wrapped exception. Returns normally if the exception was * not thrown by this writer. * * @param exception an exception * @throws IOException original exception, if any, thrown by this writer */ public void throwIfCauseOf(final Exception exception) throws IOException { TaggedIOException.throwCauseIfTaggedWith(exception, tag); } /** * Tags any IOExceptions thrown, wrapping and re-throwing. * * @param e The IOException thrown * @throws IOException if an I/O error occurs. */ @Override protected void handleIOException(final IOException e) throws IOException { throw new TaggedIOException(e, tag); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/output/TeeOutputStream.java0100644 0000000 0000000 00000006522 13612062727 031055 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import java.io.IOException; import java.io.OutputStream; /** * Classic splitter of {@link OutputStream}. Named after the Unix 'tee' command. It allows a stream to be branched off * so there are now two streams. */ public class TeeOutputStream extends ProxyOutputStream { /** * The second OutputStream to write to. * * TODO Make private and final in 3.0. */ protected OutputStream branch; /** * Constructs a TeeOutputStream. * * @param out the main OutputStream * @param branch the second OutputStream */ public TeeOutputStream(final OutputStream out, final OutputStream branch) { super(out); this.branch = branch; } /** * Writes the bytes to both streams. * * @param b the bytes to write * @throws IOException if an I/O error occurs. */ @Override public synchronized void write(final byte[] b) throws IOException { super.write(b); this.branch.write(b); } /** * Writes the specified bytes to both streams. * * @param b the bytes to write * @param off The start offset * @param len The number of bytes to write * @throws IOException if an I/O error occurs. */ @Override public synchronized void write(final byte[] b, final int off, final int len) throws IOException { super.write(b, off, len); this.branch.write(b, off, len); } /** * Writes a byte to both streams. * * @param b the byte to write * @throws IOException if an I/O error occurs. */ @Override public synchronized void write(final int b) throws IOException { super.write(b); this.branch.write(b); } /** * Flushes both streams. * * @throws IOException if an I/O error occurs. */ @Override public void flush() throws IOException { super.flush(); this.branch.flush(); } /** * Closes both output streams. *

* If closing the main output stream throws an exception, attempt to close the branch output stream. *

* *

* If closing the main and branch output streams both throw exceptions, which exceptions is thrown by this method is * currently unspecified and subject to change. *

* * @throws IOException if an I/O error occurs. */ @Override public void close() throws IOException { try { super.close(); } finally { this.branch.close(); } } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/output/TeeWriter.java0100644 0000000 0000000 00000003171 13612062727 027652 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import java.io.Writer; import java.util.Collection; /** * Classic splitter of {@link Writer}. Named after the Unix 'tee' command. It allows a stream to be branched off so * there are now two streams. *

* This currently a only convenience class with the proper name "TeeWriter". *

* * @since 2.7 */ public class TeeWriter extends ProxyCollectionWriter { /** * Creates a new filtered collection writer. * * @param writers Writers to provide the underlying targets. */ public TeeWriter(final Collection writers) { super(writers); } /** * Creates a new filtered collection writer. * * @param writers Writers to provide the underlying targets. */ public TeeWriter(final Writer... writers) { super(writers); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/output/ThresholdingOutputStream.java0100644 0000000 0000000 00000020623 13612062727 032770 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import java.io.IOException; import java.io.OutputStream; import org.apache.commons.io.function.IOConsumer; import org.apache.commons.io.function.IOFunction; /** * An output stream which triggers an event when a specified number of bytes of data have been written to it. The event * can be used, for example, to throw an exception if a maximum has been reached, or to switch the underlying stream * type when the threshold is exceeded. *

* This class overrides all {@code OutputStream} methods. However, these overrides ultimately call the corresponding * methods in the underlying output stream implementation. *

*

* NOTE: This implementation may trigger the event before the threshold is actually reached, since it triggers * when a pending write operation would cause the threshold to be exceeded. *

*/ public class ThresholdingOutputStream extends OutputStream { /** * Noop output stream getter function. */ private static final IOFunction NOOP_OS_GETTER = os -> NullOutputStream.NULL_OUTPUT_STREAM; /** * The threshold at which the event will be triggered. */ private final int threshold; /** * Accepts reaching the threshold. */ private final IOConsumer thresholdConsumer; /** * Gets the output stream. */ private final IOFunction outputStreamGetter; /** * The number of bytes written to the output stream. */ private long written; /** * Whether or not the configured threshold has been exceeded. */ private boolean thresholdExceeded; /** * Constructs an instance of this class which will trigger an event at the specified threshold. * * @param threshold The number of bytes at which to trigger an event. */ public ThresholdingOutputStream(final int threshold) { this(threshold, IOConsumer.noop(), NOOP_OS_GETTER); } /** * Constructs an instance of this class which will trigger an event at the specified threshold. * * @param threshold The number of bytes at which to trigger an event. * @param thresholdConsumer Accepts reaching the threshold. * @param outputStreamGetter Gets the output stream. * @since 2.9.0 */ public ThresholdingOutputStream(final int threshold, final IOConsumer thresholdConsumer, final IOFunction outputStreamGetter) { this.threshold = threshold; this.thresholdConsumer = thresholdConsumer == null ? IOConsumer.noop() : thresholdConsumer; this.outputStreamGetter = outputStreamGetter == null ? NOOP_OS_GETTER : outputStreamGetter; } /** * Checks to see if writing the specified number of bytes would cause the configured threshold to be exceeded. If * so, triggers an event to allow a concrete implementation to take action on this. * * @param count The number of bytes about to be written to the underlying output stream. * * @throws IOException if an error occurs. */ protected void checkThreshold(final int count) throws IOException { if (!thresholdExceeded && written + count > threshold) { thresholdExceeded = true; thresholdReached(); } } /** * Closes this output stream and releases any system resources associated with this stream. * * @throws IOException if an error occurs. */ @Override public void close() throws IOException { try { flush(); } catch (final IOException ignored) { // ignore } getStream().close(); } /** * Flushes this output stream and forces any buffered output bytes to be written out. * * @throws IOException if an error occurs. */ @SuppressWarnings("resource") // the underlying stream is managed by a subclass. @Override public void flush() throws IOException { getStream().flush(); } /** * Returns the number of bytes that have been written to this output stream. * * @return The number of bytes written. */ public long getByteCount() { return written; } /** * Returns the underlying output stream, to which the corresponding {@code OutputStream} methods in this class will * ultimately delegate. * * @return The underlying output stream. * * @throws IOException if an error occurs. */ protected OutputStream getStream() throws IOException { return outputStreamGetter.apply(this); } /** * Returns the threshold, in bytes, at which an event will be triggered. * * @return The threshold point, in bytes. */ public int getThreshold() { return threshold; } /** * Determines whether or not the configured threshold has been exceeded for this output stream. * * @return {@code true} if the threshold has been reached; {@code false} otherwise. */ public boolean isThresholdExceeded() { return written > threshold; } /** * Resets the byteCount to zero. You can call this from {@link #thresholdReached()} if you want the event to be * triggered again. */ protected void resetByteCount() { this.thresholdExceeded = false; this.written = 0; } /** * Sets the byteCount to count. Useful for re-opening an output stream that has previously been written to. * * @param count The number of bytes that have already been written to the output stream * * @since 2.5 */ protected void setByteCount(final long count) { this.written = count; } /** * Indicates that the configured threshold has been reached, and that a subclass should take whatever action * necessary on this event. This may include changing the underlying output stream. * * @throws IOException if an error occurs. */ protected void thresholdReached() throws IOException { thresholdConsumer.accept(this); } /** * Writes {@code b.length} bytes from the specified byte array to this output stream. * * @param b The array of bytes to be written. * * @throws IOException if an error occurs. */ @SuppressWarnings("resource") // the underlying stream is managed by a subclass. @Override public void write(final byte[] b) throws IOException { checkThreshold(b.length); getStream().write(b); written += b.length; } /** * Writes {@code len} bytes from the specified byte array starting at offset {@code off} to this output stream. * * @param b The byte array from which the data will be written. * @param off The start offset in the byte array. * @param len The number of bytes to write. * * @throws IOException if an error occurs. */ @SuppressWarnings("resource") // the underlying stream is managed by a subclass. @Override public void write(final byte[] b, final int off, final int len) throws IOException { checkThreshold(len); getStream().write(b, off, len); written += len; } /** * Writes the specified byte to this output stream. * * @param b The byte to be written. * * @throws IOException if an error occurs. */ @SuppressWarnings("resource") // the underlying stream is managed by a subclass. @Override public void write(final int b) throws IOException { checkThreshold(1); getStream().write(b); written++; } } ././@LongLink0100644 0000000 0000000 00000000152 13612062727 011637 Lustar 0000000 0000000 commons-io-2.11.0-src/src/main/java/org/apache/commons/io/output/UnsynchronizedByteArrayOutputStream.javacommons-io-2.11.0-src/src/main/java/org/apache/commons/io/output/UnsynchronizedByteArrayOutputStream0100644 0000000 0000000 00000012214 13612062727 034260 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; /** * Implements a version of {@link AbstractByteArrayOutputStream} without any concurrent thread safety. * * @since 2.7 */ //@NotThreadSafe public final class UnsynchronizedByteArrayOutputStream extends AbstractByteArrayOutputStream { /** * Creates a new byte array output stream. The buffer capacity is initially * {@value AbstractByteArrayOutputStream#DEFAULT_SIZE} bytes, though its size increases if necessary. */ public UnsynchronizedByteArrayOutputStream() { this(DEFAULT_SIZE); } /** * Creates a new byte array output stream, with a buffer capacity of the specified size, in bytes. * * @param size the initial size * @throws IllegalArgumentException if size is negative */ public UnsynchronizedByteArrayOutputStream(final int size) { if (size < 0) { throw new IllegalArgumentException("Negative initial size: " + size); } needNewBuffer(size); } @Override public void write(final byte[] b, final int off, final int len) { if ((off < 0) || (off > b.length) || (len < 0) || ((off + len) > b.length) || ((off + len) < 0)) { throw new IndexOutOfBoundsException(String.format("offset=%,d, length=%,d", off, len)); } if (len == 0) { return; } writeImpl(b, off, len); } @Override public void write(final int b) { writeImpl(b); } @Override public int write(final InputStream in) throws IOException { return writeImpl(in); } @Override public int size() { return count; } /** * @see java.io.ByteArrayOutputStream#reset() */ @Override public void reset() { resetImpl(); } @Override public void writeTo(final OutputStream out) throws IOException { writeToImpl(out); } /** * Fetches entire contents of an {@code InputStream} and represent same data as result InputStream. *

* This method is useful where, *

*
    *
  • Source InputStream is slow.
  • *
  • It has network resources associated, so we cannot keep it open for long time.
  • *
  • It has network timeout associated.
  • *
* It can be used in favor of {@link #toByteArray()}, since it avoids unnecessary allocation and copy of byte[].
* This method buffers the input internally, so there is no need to use a {@code BufferedInputStream}. * * @param input Stream to be fully buffered. * @return A fully buffered stream. * @throws IOException if an I/O error occurs. */ public static InputStream toBufferedInputStream(final InputStream input) throws IOException { return toBufferedInputStream(input, DEFAULT_SIZE); } /** * Fetches entire contents of an {@code InputStream} and represent same data as result InputStream. *

* This method is useful where, *

*
    *
  • Source InputStream is slow.
  • *
  • It has network resources associated, so we cannot keep it open for long time.
  • *
  • It has network timeout associated.
  • *
* It can be used in favor of {@link #toByteArray()}, since it avoids unnecessary allocation and copy of byte[].
* This method buffers the input internally, so there is no need to use a {@code BufferedInputStream}. * * @param input Stream to be fully buffered. * @param size the initial buffer size * @return A fully buffered stream. * @throws IOException if an I/O error occurs. */ public static InputStream toBufferedInputStream(final InputStream input, final int size) throws IOException { // It does not matter if a ByteArrayOutputStream is not closed as close() is a no-op try (final UnsynchronizedByteArrayOutputStream output = new UnsynchronizedByteArrayOutputStream(size)) { output.write(input); return output.toInputStream(); } } @Override public InputStream toInputStream() { return toInputStream(UnsynchronizedByteArrayInputStream::new); } @Override public byte[] toByteArray() { return toByteArrayImpl(); } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/output/WriterOutputStream.java0100644 0000000 0000000 00000034327 13612062727 031620 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import java.io.IOException; import java.io.OutputStream; import java.io.Writer; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.nio.charset.CoderResult; import java.nio.charset.CodingErrorAction; /** * {@link OutputStream} implementation that transforms a byte stream to a * character stream using a specified charset encoding and writes the resulting * stream to a {@link Writer}. The stream is transformed using a * {@link CharsetDecoder} object, guaranteeing that all charset * encodings supported by the JRE are handled correctly. *

* The output of the {@link CharsetDecoder} is buffered using a fixed size buffer. * This implies that the data is written to the underlying {@link Writer} in chunks * that are no larger than the size of this buffer. By default, the buffer is * flushed only when it overflows or when {@link #flush()} or {@link #close()} * is called. In general there is therefore no need to wrap the underlying {@link Writer} * in a {@link java.io.BufferedWriter}. {@link WriterOutputStream} can also * be instructed to flush the buffer after each write operation. In this case, all * available data is written immediately to the underlying {@link Writer}, implying that * the current position of the {@link Writer} is correlated to the current position * of the {@link WriterOutputStream}. *

* {@link WriterOutputStream} implements the inverse transformation of {@link java.io.OutputStreamWriter}; * in the following example, writing to {@code out2} would have the same result as writing to * {@code out} directly (provided that the byte sequence is legal with respect to the * charset encoding): *

 * OutputStream out = ...
 * Charset cs = ...
 * OutputStreamWriter writer = new OutputStreamWriter(out, cs);
 * WriterOutputStream out2 = new WriterOutputStream(writer, cs);
* {@link WriterOutputStream} implements the same transformation as {@link java.io.InputStreamReader}, * except that the control flow is reversed: both classes transform a byte stream * into a character stream, but {@link java.io.InputStreamReader} pulls data from the underlying stream, * while {@link WriterOutputStream} pushes it to the underlying stream. *

* Note that while there are use cases where there is no alternative to using * this class, very often the need to use this class is an indication of a flaw * in the design of the code. This class is typically used in situations where an existing * API only accepts an {@link OutputStream} object, but where the stream is known to represent * character data that must be decoded for further use. *

*

* Instances of {@link WriterOutputStream} are not thread safe. *

* * @see org.apache.commons.io.input.ReaderInputStream * @since 2.0 */ public class WriterOutputStream extends OutputStream { private static final int BUFFER_SIZE = 1024; private final Writer writer; private final CharsetDecoder decoder; private final boolean writeImmediately; /** * ByteBuffer used as input for the decoder. This buffer can be small * as it is used only to transfer the received data to the * decoder. */ private final ByteBuffer decoderIn = ByteBuffer.allocate(128); /** * CharBuffer used as output for the decoder. It should be * somewhat larger as we write from this buffer to the * underlying Writer. */ private final CharBuffer decoderOut; /** * Constructs a new {@link WriterOutputStream} with a default output buffer size of {@value #BUFFER_SIZE} * characters. The output buffer will only be flushed when it overflows or when {@link #flush()} or {@link #close()} * is called. * * @param writer the target {@link Writer} * @param decoder the charset decoder * @since 2.1 */ public WriterOutputStream(final Writer writer, final CharsetDecoder decoder) { this(writer, decoder, BUFFER_SIZE, false); } /** * Constructs a new {@link WriterOutputStream}. * * @param writer the target {@link Writer} * @param decoder the charset decoder * @param bufferSize the size of the output buffer in number of characters * @param writeImmediately If {@code true} the output buffer will be flushed after each * write operation, i.e. all available data will be written to the * underlying {@link Writer} immediately. If {@code false}, the * output buffer will only be flushed when it overflows or when * {@link #flush()} or {@link #close()} is called. * @since 2.1 */ public WriterOutputStream(final Writer writer, final CharsetDecoder decoder, final int bufferSize, final boolean writeImmediately) { checkIbmJdkWithBrokenUTF16( decoder.charset()); this.writer = writer; this.decoder = decoder; this.writeImmediately = writeImmediately; decoderOut = CharBuffer.allocate(bufferSize); } /** * Constructs a new {@link WriterOutputStream}. * * @param writer the target {@link Writer} * @param charset the charset encoding * @param bufferSize the size of the output buffer in number of characters * @param writeImmediately If {@code true} the output buffer will be flushed after each * write operation, i.e. all available data will be written to the * underlying {@link Writer} immediately. If {@code false}, the * output buffer will only be flushed when it overflows or when * {@link #flush()} or {@link #close()} is called. */ public WriterOutputStream(final Writer writer, final Charset charset, final int bufferSize, final boolean writeImmediately) { this(writer, charset.newDecoder() .onMalformedInput(CodingErrorAction.REPLACE) .onUnmappableCharacter(CodingErrorAction.REPLACE) .replaceWith("?"), bufferSize, writeImmediately); } /** * Constructs a new {@link WriterOutputStream} with a default output buffer size of {@value #BUFFER_SIZE} * characters. The output buffer will only be flushed when it overflows or when {@link #flush()} or {@link #close()} * is called. * * @param writer the target {@link Writer} * @param charset the charset encoding */ public WriterOutputStream(final Writer writer, final Charset charset) { this(writer, charset, BUFFER_SIZE, false); } /** * Constructs a new {@link WriterOutputStream}. * * @param writer the target {@link Writer} * @param charsetName the name of the charset encoding * @param bufferSize the size of the output buffer in number of characters * @param writeImmediately If {@code true} the output buffer will be flushed after each * write operation, i.e. all available data will be written to the * underlying {@link Writer} immediately. If {@code false}, the * output buffer will only be flushed when it overflows or when * {@link #flush()} or {@link #close()} is called. */ public WriterOutputStream(final Writer writer, final String charsetName, final int bufferSize, final boolean writeImmediately) { this(writer, Charset.forName(charsetName), bufferSize, writeImmediately); } /** * Constructs a new {@link WriterOutputStream} with a default output buffer size of {@value #BUFFER_SIZE} * characters. The output buffer will only be flushed when it overflows or when {@link #flush()} or {@link #close()} * is called. * * @param writer the target {@link Writer} * @param charsetName the name of the charset encoding */ public WriterOutputStream(final Writer writer, final String charsetName) { this(writer, charsetName, BUFFER_SIZE, false); } /** * Constructs a new {@link WriterOutputStream} that uses the default character encoding and with a default output * buffer size of {@value #BUFFER_SIZE} characters. The output buffer will only be flushed when it overflows or when * {@link #flush()} or {@link #close()} is called. * * @param writer the target {@link Writer} * @deprecated 2.5 use {@link #WriterOutputStream(Writer, Charset)} instead */ @Deprecated public WriterOutputStream(final Writer writer) { this(writer, Charset.defaultCharset(), BUFFER_SIZE, false); } /** * Write bytes from the specified byte array to the stream. * * @param b the byte array containing the bytes to write * @param off the start offset in the byte array * @param len the number of bytes to write * @throws IOException if an I/O error occurs. */ @Override public void write(final byte[] b, int off, int len) throws IOException { while (len > 0) { final int c = Math.min(len, decoderIn.remaining()); decoderIn.put(b, off, c); processInput(false); len -= c; off += c; } if (writeImmediately) { flushOutput(); } } /** * Write bytes from the specified byte array to the stream. * * @param b the byte array containing the bytes to write * @throws IOException if an I/O error occurs. */ @Override public void write(final byte[] b) throws IOException { write(b, 0, b.length); } /** * Write a single byte to the stream. * * @param b the byte to write * @throws IOException if an I/O error occurs. */ @Override public void write(final int b) throws IOException { write(new byte[] {(byte) b}, 0, 1); } /** * Flush the stream. Any remaining content accumulated in the output buffer * will be written to the underlying {@link Writer}. After that * {@link Writer#flush()} will be called. * @throws IOException if an I/O error occurs. */ @Override public void flush() throws IOException { flushOutput(); writer.flush(); } /** * Close the stream. Any remaining content accumulated in the output buffer * will be written to the underlying {@link Writer}. After that * {@link Writer#close()} will be called. * @throws IOException if an I/O error occurs. */ @Override public void close() throws IOException { processInput(true); flushOutput(); writer.close(); } /** * Decode the contents of the input ByteBuffer into a CharBuffer. * * @param endOfInput indicates end of input * @throws IOException if an I/O error occurs. */ private void processInput(final boolean endOfInput) throws IOException { // Prepare decoderIn for reading decoderIn.flip(); CoderResult coderResult; while (true) { coderResult = decoder.decode(decoderIn, decoderOut, endOfInput); if (coderResult.isOverflow()) { flushOutput(); } else if (coderResult.isUnderflow()) { break; } else { // The decoder is configured to replace malformed input and unmappable characters, // so we should not get here. throw new IOException("Unexpected coder result"); } } // Discard the bytes that have been read decoderIn.compact(); } /** * Flush the output. * * @throws IOException if an I/O error occurs. */ private void flushOutput() throws IOException { if (decoderOut.position() > 0) { writer.write(decoderOut.array(), 0, decoderOut.position()); decoderOut.rewind(); } } /** * Check if the JDK in use properly supports the given charset. * * @param charset the charset to check the support for */ private static void checkIbmJdkWithBrokenUTF16(final Charset charset){ if (!"UTF-16".equals(charset.name())) { return; } final String TEST_STRING_2 = "v\u00e9s"; final byte[] bytes = TEST_STRING_2.getBytes(charset); final CharsetDecoder charsetDecoder2 = charset.newDecoder(); final ByteBuffer bb2 = ByteBuffer.allocate(16); final CharBuffer cb2 = CharBuffer.allocate(TEST_STRING_2.length()); final int len = bytes.length; for (int i = 0; i < len; i++) { bb2.put(bytes[i]); bb2.flip(); try { charsetDecoder2.decode(bb2, cb2, i == (len - 1)); } catch ( final IllegalArgumentException e){ throw new UnsupportedOperationException("UTF-16 requested when running on an IBM JDK with broken UTF-16 support. " + "Please find a JDK that supports UTF-16 if you intend to use UF-16 with WriterOutputStream"); } bb2.compact(); } cb2.rewind(); if (!TEST_STRING_2.equals(cb2.toString())){ throw new UnsupportedOperationException("UTF-16 requested when running on an IBM JDK with broken UTF-16 support. " + "Please find a JDK that supports UTF-16 if you intend to use UF-16 with WriterOutputStream"); } } } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/output/XmlStreamWriter.java0100644 0000000 0000000 00000016411 13612062727 031052 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; 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.StringWriter; import java.io.Writer; import java.util.Locale; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.commons.io.IOUtils; import org.apache.commons.io.input.XmlStreamReader; /** * Character stream that handles all the necessary Voodoo to figure out the * charset encoding of the XML document written to the stream. * * @see XmlStreamReader * @since 2.0 */ public class XmlStreamWriter extends Writer { private static final int BUFFER_SIZE = IOUtils.DEFAULT_BUFFER_SIZE; private final OutputStream out; private final String defaultEncoding; private StringWriter xmlPrologWriter = new StringWriter(BUFFER_SIZE); private Writer writer; private String encoding; /** * Constructs a new XML stream writer for the specified output stream * with a default encoding of UTF-8. * * @param out The output stream */ public XmlStreamWriter(final OutputStream out) { this(out, null); } /** * Constructs a new XML stream writer for the specified output stream * with the specified default encoding. * * @param out The output stream * @param defaultEncoding The default encoding if not encoding could be detected */ public XmlStreamWriter(final OutputStream out, final String defaultEncoding) { this.out = out; this.defaultEncoding = defaultEncoding != null ? defaultEncoding : "UTF-8"; } /** * Constructs a new XML stream writer for the specified file * with a default encoding of UTF-8. * * @param file The file to write to * @throws FileNotFoundException if there is an error creating or * opening the file */ public XmlStreamWriter(final File file) throws FileNotFoundException { this(file, null); } /** * Constructs a new XML stream writer for the specified file * with the specified default encoding. * * @param file The file to write to * @param defaultEncoding The default encoding if not encoding could be detected * @throws FileNotFoundException if there is an error creating or * opening the file */ @SuppressWarnings("resource") public XmlStreamWriter(final File file, final String defaultEncoding) throws FileNotFoundException { this(new FileOutputStream(file), defaultEncoding); } /** * Returns the detected encoding. * * @return the detected encoding */ public String getEncoding() { return encoding; } /** * Returns the default encoding. * * @return the default encoding */ public String getDefaultEncoding() { return defaultEncoding; } /** * Closes the underlying writer. * * @throws IOException if an error occurs closing the underlying writer */ @Override public void close() throws IOException { if (writer == null) { encoding = defaultEncoding; writer = new OutputStreamWriter(out, encoding); writer.write(xmlPrologWriter.toString()); } writer.close(); } /** * Flushes the underlying writer. * * @throws IOException if an error occurs flushing the underlying writer */ @Override public void flush() throws IOException { if (writer != null) { writer.flush(); } } /** * Detects the encoding. * * @param cbuf the buffer to write the characters from * @param off The start offset * @param len The number of characters to write * @throws IOException if an error occurs detecting the encoding */ private void detectEncoding(final char[] cbuf, final int off, final int len) throws IOException { int size = len; final StringBuffer xmlProlog = xmlPrologWriter.getBuffer(); if (xmlProlog.length() + len > BUFFER_SIZE) { size = BUFFER_SIZE - xmlProlog.length(); } xmlPrologWriter.write(cbuf, off, size); // try to determine encoding if (xmlProlog.length() >= 5) { if (xmlProlog.substring(0, 5).equals(""); if (xmlPrologEnd > 0) { // ok, full XML prolog written: let's extract encoding final Matcher m = ENCODING_PATTERN.matcher(xmlProlog.substring(0, xmlPrologEnd)); if (m.find()) { encoding = m.group(1).toUpperCase(Locale.ROOT); encoding = encoding.substring(1, encoding.length() - 1); } else { // no encoding found in XML prolog: using default // encoding encoding = defaultEncoding; } } else if (xmlProlog.length() >= BUFFER_SIZE) { // no encoding found in first characters: using default // encoding encoding = defaultEncoding; } } else { // no XML prolog: using default encoding encoding = defaultEncoding; } if (encoding != null) { // encoding has been chosen: let's do it xmlPrologWriter = null; writer = new OutputStreamWriter(out, encoding); writer.write(xmlProlog.toString()); if (len > size) { writer.write(cbuf, off + size, len - size); } } } } /** * Writes the characters to the underlying writer, detecting encoding. * * @param cbuf the buffer to write the characters from * @param off The start offset * @param len The number of characters to write * @throws IOException if an error occurs detecting the encoding */ @Override public void write(final char[] cbuf, final int off, final int len) throws IOException { if (xmlPrologWriter != null) { detectEncoding(cbuf, off, len); } else { writer.write(cbuf, off, len); } } static final Pattern ENCODING_PATTERN = XmlStreamReader.ENCODING_PATTERN; } commons-io-2.11.0-src/src/main/java/org/apache/commons/io/output/package.html0100644 0000000 0000000 00000001730 13612062727 027355 0ustar00rootroot0000000 0000000

This package provides implementations of output classes, such as OutputStream and Writer.

commons-io-2.11.0-src/src/main/java/org/apache/commons/io/overview.html0100644 0000000 0000000 00000002352 13612062727 026271 0ustar00rootroot0000000 0000000

The commons-io component contains utility classes, filters, streams, readers and writers.

These classes aim to add to the standard JDK IO classes. The utilities provide convenience wrappers around the JDK, simplifying various operations into pre-tested units of code. The filters and streams provide useful implementations that perhaps should be in the JDK itself.

commons-io-2.11.0-src/src/main/java/org/apache/commons/io/package.html0100644 0000000 0000000 00000003451 13612062727 026017 0ustar00rootroot0000000 0000000

This package defines utility classes for working with streams, readers, writers and files. The most commonly used classes are described here:

IOUtils is the most frequently used class. It provides operations to read, write, copy and close streams.

FileUtils provides operations based around the JDK File class. These include reading, writing, copying, comparing and deleting.

FilenameUtils provides utilities based on filenames. This utility class manipulates filenames without using File objects. It aims to simplify the transition between Windows and Unix. Before using this class however, you should consider whether you should be using File objects.

FileSystemUtils allows access to the filing system in ways the JDK does not support. At present this allows you to get the free space on a drive.

EndianUtils swaps data between Big-Endian and Little-Endian formats.

commons-io-2.11.0-src/src/main/java/org/apache/commons/io/serialization/ClassNameMatcher.java0100644 0000000 0000000 00000002322 13612062727 032424 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.commons.io.serialization; /** * An object that matches a Class name to a condition. */ public interface ClassNameMatcher { /** * Returns {@code true} if the supplied class name matches this object's condition. * * @param className fully qualified class name * @return {@code true} if the class name matches this object's condition */ boolean matches(String className); }commons-io-2.11.0-src/src/main/java/org/apache/commons/io/serialization/FullClassNameMatcher.java0100644 0000000 0000000 00000003104 13612062727 033246 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.commons.io.serialization; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Set; /** * A {@link ClassNameMatcher} that matches on full class names. *

* This object is immutable and thread-safe. *

*/ final class FullClassNameMatcher implements ClassNameMatcher { private final Set classesSet; /** * Constructs an object based on the specified class names. * * @param classes a list of class names */ public FullClassNameMatcher(final String... classes) { classesSet = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(classes))); } @Override public boolean matches(final String className) { return classesSet.contains(className); } }commons-io-2.11.0-src/src/main/java/org/apache/commons/io/serialization/RegexpClassNameMatcher.java0100644 0000000 0000000 00000003656 13612062727 033612 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.commons.io.serialization; import java.util.regex.Pattern; /** * A {@link ClassNameMatcher} that uses regular expressions. *

* This object is immutable and thread-safe. *

*/ final class RegexpClassNameMatcher implements ClassNameMatcher { private final Pattern pattern; // Class is thread-safe /** * Constructs an object based on the specified regular expression. * * @param regex a regular expression for evaluating acceptable class names */ public RegexpClassNameMatcher(final String regex) { this(Pattern.compile(regex)); } /** * Constructs an object based on the specified pattern. * * @param pattern a pattern for evaluating acceptable class names * @throws IllegalArgumentException if {@code pattern} is null */ public RegexpClassNameMatcher(final Pattern pattern) { if (pattern == null) { throw new IllegalArgumentException("Null pattern"); } this.pattern = pattern; } @Override public boolean matches(final String className) { return pattern.matcher(className).matches(); } }././@LongLink0100644 0000000 0000000 00000000151 13612062727 011636 Lustar 0000000 0000000 commons-io-2.11.0-src/src/main/java/org/apache/commons/io/serialization/ValidatingObjectInputStream.javacommons-io-2.11.0-src/src/main/java/org/apache/commons/io/serialization/ValidatingObjectInputStream.0100644 0000000 0000000 00000015660 13612062727 034026 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.commons.io.serialization; import java.io.IOException; import java.io.InputStream; import java.io.InvalidClassException; import java.io.ObjectInputStream; import java.io.ObjectStreamClass; import java.util.ArrayList; import java.util.List; import java.util.regex.Pattern; /** * An {@code ObjectInputStream} that's restricted to deserialize * a limited set of classes. * *

* Various accept/reject methods allow for specifying which classes * can be deserialized. *

* *

* Design inspired by IBM * DeveloperWorks Article. *

*/ public class ValidatingObjectInputStream extends ObjectInputStream { private final List acceptMatchers = new ArrayList<>(); private final List rejectMatchers = new ArrayList<>(); /** * Constructs an object to deserialize the specified input stream. * At least one accept method needs to be called to specify which * classes can be deserialized, as by default no classes are * accepted. * * @param input an input stream * @throws IOException if an I/O error occurs while reading stream header */ public ValidatingObjectInputStream(final InputStream input) throws IOException { super(input); } /** Check that the classname conforms to requirements. * @param name The class name * @throws InvalidClassException when a non-accepted class is encountered */ private void validateClassName(final String name) throws InvalidClassException { // Reject has precedence over accept for (final ClassNameMatcher m : rejectMatchers) { if (m.matches(name)) { invalidClassNameFound(name); } } boolean ok = false; for (final ClassNameMatcher m : acceptMatchers) { if (m.matches(name)) { ok = true; break; } } if (!ok) { invalidClassNameFound(name); } } /** * Called to throw {@code InvalidClassException} if an invalid * class name is found during deserialization. Can be overridden, for example * to log those class names. * * @param className name of the invalid class * @throws InvalidClassException if the specified class is not allowed */ protected void invalidClassNameFound(final String className) throws InvalidClassException { throw new InvalidClassException("Class name not accepted: " + className); } @Override protected Class resolveClass(final ObjectStreamClass osc) throws IOException, ClassNotFoundException { validateClassName(osc.getName()); return super.resolveClass(osc); } /** * Accept the specified classes for deserialization, unless they * are otherwise rejected. * * @param classes Classes to accept * @return this object */ public ValidatingObjectInputStream accept(final Class... classes) { for (final Class c : classes) { acceptMatchers.add(new FullClassNameMatcher(c.getName())); } return this; } /** * Reject the specified classes for deserialization, even if they * are otherwise accepted. * * @param classes Classes to reject * @return this object */ public ValidatingObjectInputStream reject(final Class... classes) { for (final Class c : classes) { rejectMatchers.add(new FullClassNameMatcher(c.getName())); } return this; } /** * Accept the wildcard specified classes for deserialization, * unless they are otherwise rejected. * * @param patterns Wildcard file name patterns as defined by * {@link org.apache.commons.io.FilenameUtils#wildcardMatch(String, String) FilenameUtils.wildcardMatch} * @return this object */ public ValidatingObjectInputStream accept(final String... patterns) { for (final String pattern : patterns) { acceptMatchers.add(new WildcardClassNameMatcher(pattern)); } return this; } /** * Reject the wildcard specified classes for deserialization, * even if they are otherwise accepted. * * @param patterns Wildcard file name patterns as defined by * {@link org.apache.commons.io.FilenameUtils#wildcardMatch(String, String) FilenameUtils.wildcardMatch} * @return this object */ public ValidatingObjectInputStream reject(final String... patterns) { for (final String pattern : patterns) { rejectMatchers.add(new WildcardClassNameMatcher(pattern)); } return this; } /** * Accept class names that match the supplied pattern for * deserialization, unless they are otherwise rejected. * * @param pattern standard Java regexp * @return this object */ public ValidatingObjectInputStream accept(final Pattern pattern) { acceptMatchers.add(new RegexpClassNameMatcher(pattern)); return this; } /** * Reject class names that match the supplied pattern for * deserialization, even if they are otherwise accepted. * * @param pattern standard Java regexp * @return this object */ public ValidatingObjectInputStream reject(final Pattern pattern) { rejectMatchers.add(new RegexpClassNameMatcher(pattern)); return this; } /** * Accept class names where the supplied ClassNameMatcher matches for * deserialization, unless they are otherwise rejected. * * @param m the matcher to use * @return this object */ public ValidatingObjectInputStream accept(final ClassNameMatcher m) { acceptMatchers.add(m); return this; } /** * Reject class names where the supplied ClassNameMatcher matches for * deserialization, even if they are otherwise accepted. * * @param m the matcher to use * @return this object */ public ValidatingObjectInputStream reject(final ClassNameMatcher m) { rejectMatchers.add(m); return this; } }././@LongLink0100644 0000000 0000000 00000000146 13612062727 011642 Lustar 0000000 0000000 commons-io-2.11.0-src/src/main/java/org/apache/commons/io/serialization/WildcardClassNameMatcher.javacommons-io-2.11.0-src/src/main/java/org/apache/commons/io/serialization/WildcardClassNameMatcher.jav0100644 0000000 0000000 00000003206 13612062727 033737 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.commons.io.serialization; import org.apache.commons.io.FilenameUtils; /** * A {@link ClassNameMatcher} that uses simplified regular expressions * provided by {@link org.apache.commons.io.FilenameUtils#wildcardMatch(String, String) FilenameUtils.wildcardMatch} *

* This object is immutable and thread-safe. *

*/ final class WildcardClassNameMatcher implements ClassNameMatcher { private final String pattern; /** * Constructs an object based on the specified simplified regular expression. * * @param pattern a {@link FilenameUtils#wildcardMatch} pattern. */ public WildcardClassNameMatcher(final String pattern) { this.pattern = pattern; } @Override public boolean matches(final String className) { return FilenameUtils.wildcardMatch(className, pattern); } }commons-io-2.11.0-src/src/main/java/org/apache/commons/io/serialization/package.html0100644 0000000 0000000 00000001666 13612062727 030702 0ustar00rootroot0000000 0000000

This package provides a framework for controlling the deserialization of classes.

commons-io-2.11.0-src/src/media/io-logo-white.xcf0100644 0000000 0000000 00000047413 13612062727 022051 0ustar00rootroot0000000 0000000 gimp xcf fileZBBLK gimp-commentCreated with The GIMPgimp-image-grid(style solid) (fgcolor (color-rgba 0.000000 0.000000 0.000000 1.000000)) (bgcolor (color-rgba 1.000000 1.000000 1.000000 1.000000)) (xspacing 10.000000) (yspacing 10.000000) (spacing-unit inches) (xoffset 0.000000) (yoffset 0.000000) (offset-unit inches) 0<$M( TM     HL8gimp-text-layer(text "TM") (font "Sans") (font-size 8.000000) (font-size-unit pixels) (hinting yes) (antialias yes) (language "en-us") (base-direction ltr) (color (color-rgb 0.000000 0.000000 0.000000)) (justify left) (box-mode fixed) (box-width 12.000000) (box-height 11.000000) (box-unit pixels)   #ɰ->8x88w8P8?8+ Text Layer     -J++   U U8 qqUqqU8qUU q8q8U UU UUUq8 8U8 UU qU8qU88UUqUUUUUUUUUUUUUUUUqUUUUU8UU qUq U8 UUU U  qq8 q8U88 q8!U I<Drop-Shadow#2     &KI<I< P                    !#$#"   #'*++)&#  !!"!   $).1220-*&"  "$%&&%$%%&''&%"  #)/48::850,(%$#$%')*++*)(''()+,,+)&"  &-4:>@@>;62.+))*,-/010/.,*)(()*,.01210-)$  !)19?DFFD@<84100134676530-+)((*-0357763/*$  #+4<;<>@ABA?<73.*&%$%(,16:>AA@<71*"  %.8AHNQRPMIEBAABDFGGFB>82-($""#&*06>?ADEFEC?;50+'%$%'*/48;989;=?AA@=951-)'&'),/379;;961+$  "*2:@EHHFB>96323479:;;9740-*)((*,/146653/+%  '/6<@BB@<840-,,-/2456531/-+)()*+-/011/-)$  $+16:<<:73.+(&&')+-/00/.-+)(()*+,,+)&#   &,045530,(%" !"$&()**)('&&'&%#   !%),--,)&"!#$%%$##"#"!  #%&&$"                       Nt               $commons     ##"c8qU8Uq8q8q q UU88UU8qUqUUUqUUUqUUq8U8 UU 8q8U8 q   8U 8U UU UU UU 8UU U 8 88 U q 8888 q8 q8qUUUUUqU UUUU U 8qUq q8UqUU8qU 8q8U8 8UqU8qqq88qqUUqUUUqƪUqUUUU8Uqq q8UUU 88UUqq UUUU UUUU UUUU UUUU UUUU UUUU UUUU UUUU UUUU UUUU UUUU UUUU UUUU UUUU UUUU qUq qUqU8qU88qU8UƍUUUU8q qq q8  8qUU88qU 88 8UU UUUU8U8UUUUUUUUU8q 8UqUUU UUUUU 8UUUU UUUUU UUUU UUUU UUUUUU UUUUUU UUUUU UUUUUU UUUUU8 UUUU qUUUUq UUUUq8UUUUUUUUqUqU88UUqqU8q8qUU 8Uq8 q 8VVV UU ⪪88888Uqqq88  q 8 qU  qU qq8qƪq888UUk 58 Drop-Shadow     9$8$MM8$/59DU                    !#$%%$# !"##$%%$"   "$&')*+,,+*'%"!#$&'())*+,,*(&#! !$&(*+-.01221.,)&#! !#$'(*+,--./0234431.,)  #'),-/01346787642/,)(''(*,./11223568:;;9752 !&*-/12334679:;<;9742/..0245677665668:=?ABCB@=: "',02456678:<=>>=;97544579;<==<:9878:>=;:99:<>ABCCB@=;988:=@EIMOPONK &-38;==<:8655679;<=>==>@BEGIIHFC?;9779<@FKPSUVTR $+29=@AA>;853223579:;<==?ADGKMOOMJE@;7556:?EKQVZ[ZX  (08>CEED@<830..024689;=@CGLPSTSQLGA;63237=CKRX\__] $,5=CGJIGB=72.+))*,.1369<@EJOTWXWTOHA:40/04:AJRY^aba '09AHLNMID>71+(%%'),/26:@FLRW[\[WQIA93.,-17?HQY_cdd  )3=ELPRPLF?70*%"!!"$'*.38?FMTZ^_^YSJA92-*+/5=FOX_dfe ",6@HOTUSOIA81*$!!#'+06>ENU\`a`[TKB91,))-3;DNW^cff #-8BKSWYWRLC;2+% !$(.55-'" #'-471,)&%&'*.3:AJRZ_bc`ZSJA93/-/28@HOUY[[ !+6ALV]bdd`[TME>83/,*)*+.38?GOV\`a_ZTLC<610149@FMRUWW (3>IS[aeec_ZSLE?:52/--/27=DKRX\]\YSME>94336:?EJOQRR %/:EOX_ceeb^XRLFA<741/./149?FMSWYYWSMF@;7557;?CGKLML !+5@JS[`dec`\WQLFA<741/./15:@FLQTUSPLGB=9778;>ADFGGF &0:DMU\`bba]YTOID?:51.-,.04:?EJMOOMJFA=:88:<>@AA@? !*3=FNUZ]_^\YUPJE?:50-*))+.27=AEHIHFC@=:87789:;;:98 $-5>FMRVYYXVRNIC>83.*'%$%(+059=@BBA?=:8755421 &-5=DINPRQPMID?:4/*%" !$(,048:;;:875321100/.,+* %,3:?CFHIHEB>94/*%! $(,/13310/.-,+*('%$# $*059<>?><:62.)$  #&)+,,+*)('&%#"  !&+.134431.*&"!#$%%$$#"!  !$')**)'%"                    "                              !!"#$$%%$#"!  !"##! !!"#$%!$&'))*+,-.//.-,*))()*+,,*(%!"$&())**+,-. #&*-/123345789987642112345531-*&" #'*-012334567'%%&(+/369;<==<<=>@ACCDCB@><::;=>>=:62.)&$$%'+/37:;<=<<=>@/--.037<@CEFFEDDFGIKMMKIGECAABCDFGFEC?:51-+*,.27<@CEFFEDDEFH86558;@DILNOOMLKJJLNPSUVVTROMJHGGIJLMNMKGB=841125:?DILNONMKJJKLN@>==?CHLQTVWVTRPOOPRUX[\]\YVSPMLLMOQSTTRNID?:778;@FKPTVVUSQOOQSHEDDFJNSX[]][YVSRQRUX\_aba_\XTQONOQTVXXWTPJE@=<=@EKQWZ\\ZXUSQQSVOLKJLOTY]`ba_\XUSRSUY^adfec_[VRPOPRUX[\[YUOJEA@ADJPV[_``^ZWTRRTWUSQPQTY]adedb^YURQRUY^bfhgea\WSONOQUY\^^\XSNHECDHMSY_bcb`\WTQQSV[XUU;X\`dggfc^YTPOPSW]bfhhfb\WRNLMPTX\_`_[VQLHFGJOU\aded`[WRPOQT_\YXY[^bfhhfb]WRNLMPU[`ehhfb\VPLJKNRW\_a`]YSNJHHKPW]befd`[UPMLNRb_\[[]`dgiifb\UPKIJMRY_dggea[TNJHHKPU[_ba_ZUPKIJLQW]beec_YSNJIKOca^\\^adgiheaZTMIGGJPV]befd`YSLHEFINTZ_ab`\VQLJJMRX]beeb^WQKHGHLda_]]^adghhe`YRKGDEHMT[`dec^XQKFCDGLRY^ab`\WQMJJMRW]bdda\VOIFDFJda_]]^adghgd^XPJEBCFLRY_cdb]WPIDBBEKQX^aba]XRNKKMRW]adc`[UNHDBDHc`^\\^`cfgfc^WOICAAEJQX^bca\VOHCAADJPW]aba]XSNKKMRW]acc`ZTMFBABG`^\[[]_cegfc]VNHC@@DJQX^aba\UNHB@@DIPW]aba^YSOLLNRW]acc_ZSLFB@BF][YXY[^befeb\UNGB?@CIPW]ab`\UNGB@@CIPW]aba^YSOLLNRW\`cb_YRKEA@AEZXVVWY]`deea\UNGB?@CIPW]ab`[UNGB@@CIOW]aba^YTOLLNRW\`bb_YRKEA?AEUTRRTW[_bdda[UMGB?@CIPW\`a`[UNGB@@CIOV\`ba^YTOMLNRW\`ba^YRKEA?AEPONNPTX]acb_[TMFB?@CHOV\_`_ZTMGB@@CHOV\`a`]YTPMMNRW\_a`]XQJEA?AEJIIJLPUZ^``^YSLFA??CHNU[^_^YTMGB@@CHNU[_`_\XSOMLNRV[^`_\WQJD@?ADD2EHMRW[^^\WQKEA>?BGMSY\]\XRLFA??BGMSY]^][WRNLLMQUY]^]ZUOIC@>@D>=>@CHMSWZZXTNHC?==@EKQVYZXUOJD@>>AEKQVY[ZXTPLJIKNRVY[ZWRLFA>=>B778:>CHNRUUTPKE@=;;>BHMRUVTQLGB><<>CHMRUWVTPLIGGHKOSUVVSOID?<;CHLOPNKGB>:88;>CHLOPPNKHECCDFJMOPPMID?;878;))+.27BFHIHEA=96446:>BFHJIGEB?>>?ADGIIGC?:64347"#$'+059=?@?<952/..037;>@A@>:731//147;>@AA@=;9878:=?AA?<841/./1!$(-146641.+)((*,/2578752/,*))*-035788753100134688630-*)()+!%(+-.-+)'$#""#%(*-./.,*(%$##$&(+-.//.-+*))+,.//-+)&$""$!#$%$#!  #$%&%$" !#$&&%$#"!!"#$%&&%#!                         9 ,                     %%$#"!  !""##"    !"#//.,+*)(()*+,,+)&# !"#$%%$#!"$')+,,89987532112245542/+'" "$%&'()*+,--,+*(&#"!!"$'*.13566BCDCCA?=;::;<=>><84/*&" "%')*+,-./01234420.,*))*-037;=?@@JLMMLKIFDBAABCEFGFDA=83.)&%%&(*,.0112234689;<<;975321358=AEGIJJQSUVUTQNLIHGHIKMNNLJE@;61.,,-/24567665679<>ABCCB@><::;>AFJNQSSVY[\\[XUROMLLMORSTSQMHC>964468:;==<;9889;>BEHJKJIGECBCFINRVY[[ZZ]`bba^ZVRPNNPRUWYYWTOJEA><=>@ACCB@>;9889;?CHLOQQPOMKJKMQUY]`aa_[_cefeb^YUQOOQSWZ\]\ZVQLHFDEFGIIGD@=9778;?DIOSVWWVTRQRTW[_cefebZ_dghgd`ZUQONPSV[^``^[WSOMLLMOPONKGB=86458=CIPUZ\]\ZYWWY\_cghigdY^cghhe`ZUPMLNQUZ^acb_\XUSRSTUVURNIC=74236;AIPW\`aa`^\\]`cfikjhdW]bfhhe`ZTOKJLOTY_bdec`][YXYZ[[ZVQJC<61/028?GOW^bdedb``acehklkhcT[`eggd_XRMIHIMRX^cfgfda_^^=`a`^ZTLD<50--055.*(*.5>HQZaeggfeddegijjhc]LSZ_bb_ZSLFA@AFLS[bgijjhggijkkid]TJ@70+)+/5>GPX_ceedcbbdfhiigb\LSY_bb_YSLEA@AELS[afijihffhijjid^ULB92-+,/5=FNV\`bba``bdghhfb\KRY^aa^YRKEA?AEKSZafhihfeddeghigd^VMD<50-.16=EMTY]^^]]^`ceggea[KRY^aa^YRKEA@AEKSZ`eghfdbaabdefeb^WOF>830037=DKQVXZYYXYZ]`cefd`ZKQX]``]XRKEA@AEKRY_dffdb_^]^_abb`\WPHA:63358>CINRTTUWZ]addc_ZJQW\__\WQKEA@AEJQX^bcca^[YXYZ\]^]ZUOIC=86569=BGJMNONNPRVZ^aba^XIOUZ]]ZVPJDA?@DIPV[_``]ZWTSRSUWXXVSNIC>:878:=@DFHIHHJMRV[^_^[WGMRWYYWSMHB?>?BGMSX[\[XUQNLLNPQRQOLGC?;9889;>@ABBABDHLQVY[ZXSDJOSUUSOJE@=<=@DJOSVWVSOKHEDEFHIKKJGDA>;97789:;<<;::<>BGLPTVVSO@EIMOOMJE@<989<@EIMPPOLHD@><<=?ABCCB@>;976556543357;@EJMOOMJ;?CGHIGD@;85457;?CFHIGDA=9654568:;<;:9754221100/.-,+,.049>BFHHFC48?@><-14677641.+*))+.13677530,)&%$$%'(*+,,+*)('&%$"!  "&*.256764&)+-./.,)'%##$&)+-..,*(%" "#$%%$#"! #&),-.-+!#$%%#" !#$%%$" !#$%$#                        !   *                  #$$%$"  -.-,)&"  678753/+'"!#$%&&%$#! @?@AA@?<84/*%" !#%(*,--,+*(&# IHGGHIIGEA<71,)&%&'*-/1344321/-*'# QPNNOPPOMJE?94/-,,.1479:;::8641.*&! WUSRRSTUVVTQLF@;632247;>@AA?=;851-(# \YVUUWYZ[ZWRMGA<978:=ADFHHGEB?<840*% _[XVUVX[]^^\XRLFA><=?BFJLNNMKHD@<72,'! _[WUTUX[^`a_\VPJEB@ACGKNQSSRPMID@:5/(" _ZVSRSVZ^aba^YTMHDCCFINRUWXWURNID>81*$ ^XSPOQTX]acc`\VPJFDEGKPTXZ\[YWSNHB<4-& \VQNMNRV\`cca]WQKGEEGKPUY\^^][WSMG@91)" ZTNKJKOTZ_bcb^XRLGEDFJOTY]`aa_\XSLE=5-% YRLIGIMSY^bcb^XRLGDCDHMRW\_bcb`\XRKC:1)  WPJGFGLQX^bcb^XRKFBABEJOUZ^acdc`\WPH?6-$ VOIEDFJPW]acb^XQKEA?@BFKQV[_bddc`[UMD;1( UNHDCEJPV]acb^XQJD@==?CGMRW\`bdcb^XQH?5+" UNHDCEIPV\acb^XQJD?<;;:;=@EINSX\_aa_[UMD:0& TMGDCEIOV\`bb^XQJD>;99;>AEJNSW[]^]ZUNE;1( SMGDCEIOU[`ba^XQJD>;98:<>BFJNRVYZZXSMD;1( RLGCCDINUZ_a`]WQJD>;989::8789:@CFIJJIE@:2*" JEA?>?CHMRUWVSOJD?;75445678:<>@BCCB?:4-& EA=;:BFHJIGC?;630/../0123455430,'" 95311247;>@AA?<840.+*))*+,--..-+)%! 1.,**+-025787630-*'%$$%&'&%$! )'%$$&(*-./.-+(&#!  ! !"$%&%$#!                    z=,d Background     M,dMNNN,dN#NANQNaNqNNNNN:        &>>Q            00002K% commons-io-2.11.0-src/src/media/logo.gif0100644 0000000 0000000 00000010471 13612062727 020305 0ustar00rootroot0000000 0000000 GIF89ag  !!!"""###$$$%%%'''((())),,,...000111222333444555777888:::;;;<<<===>>>???@@@AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffhhhjjjkkklllmmmnnnoooppprrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~! ,g N@%Zz@!A0SË)r4^4PF%  1 h9DN8ف!=)ULL8[t'S`F#mKϽS`S喖[Ea,l` )F9,F5YH!FT2b jTApA(CRpfA[lE KUrbP:nTK9H-\BRoBITMQn cbY[GAJD[z0 ,TفA¡sfC + ɠCDTf:R,b!' NN9 4\rpA GZp,G(4H )@R`7T%-I@ }wa :|p%J5A `2dP :0P dh%J=1'8{B :0pb(u9J T[u*{6M= X8%FM'cN#j}U(@͠ 'F+(%ARh@;AFûO䨠+|4 >XP r"{20\Ё?vM X (YstMSaʫ΅RHB&(RA Aㅐ 4PJBX +Hp[2Ĉ|jX'B dGIBv<'!:P,?!v2=isP~1 EhC3*5#7*% RDL[:G D1$*8d$"4 Y0c(YF.*A)]h^!!xt(p5@pR("$8e(ՀE0)tJ>xF '*`Pz6$B_ }35␎{ E]УhvcrLyEl''1yL:`6 pygs !LG ,+mѵK¥6[cC70gYp-l@_6 fa fp‚V`eP*2858W8;KPf`@aev`mIKȄ?POH_ *_v1geH11eh8heIrE rHa)_6{`Pf& Fr(x2_Ua`T^ F6 @fT1EPf3f)dU#FJ(i@Pf7feH~f 慝v;Ve3fPf v }e8zNV(i KaY e` hhx+-h e` PfͰyF *y~eJ'd8Pfl6 '+wep o^ eP Qcc0lf(`PfsВW& 0Y4'edgSfMM >#7qHP^ 9i`SfՆ_ @8eRfpben^ #9_qȌ~_ƒpd0ͳC_hm=Ae,id^wyeMG_ F Bgm |YW_f J|wWfYaQeidp|WdY}CAl faxf{0&zuЛe 9HabgZ5 łדҙqlFU ay 2x'J2h_ z7G pС9  fS 9 tD# zv@xmurcs<rӈ*c i@5Ѕ:1zqE: l4hgO (@s-JIi W5G ׳Ir"_Y iQkְ[U9وai,U7n =^얟aꨒV;Yy`]uYqWeFRjSze:*`ۑN B@F lG1Ъ k2JeZyZi 樷Z)bHqmx'= P|]l \CaC sPj_YG1@t0 @ t -p{"&`:k_89@;;commons-io-2.11.0-src/src/site/resources/download_io.cgi0100644 0000000 0000000 00000000235 13612062727 023534 0ustar00rootroot0000000 0000000 #!/bin/sh # Just call the standard mirrors.cgi script. It will use download.html # as the input template. exec /www/www.apache.org/dyn/mirrors/mirrors.cgi $*commons-io-2.11.0-src/src/site/resources/images/io-logo-white.png0100644 0000000 0000000 00000024631 13612062727 025216 0ustar00rootroot0000000 0000000 PNG  IHDRZb*sRGBbKGD pHYs  tIME +!H!iTXtCommentCreated with The GIMPm IDATx}ipVU?K' FtQYIHơ`tfH X.(E@D [%,фa`6n !*$vo喙ssNקR@_O|)uճ_Jnhwt=|1skƃ媫\˃LGÿ|> M˃߆AA^^cŦueݺu{nꫯLu t@yy9̞=[{yy9}AIIe=yؽ{inVV+zu<"mYYYF?Nzc-M#\Gb())qώ|A9G`Zmr(/R`'OvU8VHDEQT,SgvGVV*--Mh4֬YJJJ֬YѨD"*]v\m߹ĉ… 瞳붵굵6ݑHD}gj*//hiEz_x>'Ol… jɶuhҵ裏Lt;Ν;U{{?i=qUUU674*--UVYE8)S())Q%%%طo >a֭&}/|z N ~?\qIƂXt86,ӧOEY7j(X`iNkz6m}#Ho M6ksҥpwZh02? ,QF{w޽{ddd/KJk^αc 'SOkf3??-Zd |ڹYd xӾ}@ߴiW_BXr%|> b󟡢-6 ী뮻~aX 8b1FF!@$4ׯerrr H$O<{<&}"aS_HĘ(ZC8vhoo7bp8-Zd|n׻wo3givQ`}X,fOèQLrZLBc=Æ i4T>p8 ]O|p]N >y1EHs3}t1b88ݻCzz޽{ŵuϞ=X(plh!(I \q!b9sZF0q &x޼yjYݻw$2J->8XYNNe1`…F?y~/fzz\{- lAmRw2{[[P"D$pp )))1sS={ԭt.\Тt@9R]?Jc4|?55՘Dӧ-ߡ#`a޼y&ޤq`%Y?ADom"z&DsJzHOOD"Y#7 kh\dl2 Ï7dЇx&ڗt- 3xbfTҋ4Sz}>X7B[[ܐQHR7Ew߅w{p0>|t=ovXd×_~ih8JDc4vc^u㥽bjFݧz 8/1t+kV>frP)uuu\3("jQP(hb#xH:to6 08`Z4Npl8N:`a"1.&A04:zuDN<:`bH/~2,\tֳgϞOzVܠ63 °ag5}ڴiPQQO>$Kc= ֗2~fL\Zs tMMM"Sfm $ `߾}p 7XNNcOާ`1S~wҘT!RBǸX3/j\.999ri-~ .Lڏ1ZҵkWaʕ>=z4^|EB1JN@ `,Aݻw[:ejKV^?#j Lq tҠީSkԳӘ'G:@@d tZUp-Xႄ2! ]]t><(D~iiiN>m֚<ʁ뚜.?^ZZ O͛7[߿ ƍcB(z۹D[P)e>Q`JΌܭ\vt%[O*`^?eztKjd4]WҘs+ P7* $[]] RA;J?իE+ZΔڒFEWʙ3gBZZZJo7o0f&in:ڳgEcr= ?eb\+Hf.ŸPO%_2sINRmLn~}:z%TZt7L8ѕD`Нz뭢ɦ[LI!Y|,1D 7X:+{tGcZn,HN(霗J)5k[ζT:u*<㖶w)ZNNCc7KKKԩSH{!a„ pB 0i5m#)9"z뭢3j ;p>0:Ftk&<*ɉ1Fk %% 63[ZnBhLJA} >|Xl?CBVL4ix/BCCvo*'L\Ɓ@}}v3M-?BFFb:rnLY-nQ%FsK$t&џ~;|ʑO83t{,B)5zk.G+**:$_Q7L4IԚ[ljkkf<e˖AII 444k&~?kAN^C)/##{1-0,[3DG7\NN؍iԨQm~kk+TTTDyhܹsEPv$۹qj\\skF‘t@gўL4 ƍر*++a۶m0gCFFVu ,1c.˗F8vI:x?n5dsӟ);eICKKx>O6s޼yЧO(ՕCfSSl(8Ϝ9c7x`wάB$& aZFhii7̙3aƌ0m4Xf7g>|Yȑ#ᥗ^2}v5kS>P^^"f^q_Q466:tP---":w h辗3gδ'V BP;+#Grt-M;pzСLJW^yŢ5QS"07l`ԹM{Nɒs L7ݔP(>,%0Ç+WUU?***LZYY wo.*]Eg c_Ŭt԰k׮A"kr-O+++-umfˀDmBJJ ̚5  d2i'L+Wcǎky!(++QFAcc#CYY1B J 6mhرCx|IƏ&z0W_5R2q's"^x!>''|bKpqq13 99sK~C ðb Xfٳ'<Я_?CZ@%H$[l&عs'|b{W^y%\wu0x`ĉp1裏ȑ#Zznf馛k׮pWѣGPUU olڵ+\~pQ8z(|G޽;\wumI?:~8ڵK;P ِ W\qNرcu{C+~__n ѣtRv{L/8p<ׯ͕W^ lC@‰'?*--ݻw!C|>xB~iiiƥklٲ~;=z&=JJJdLŏ@&p|w^غuRRR ;; `hK.TZ/Á~nի\uU&c\}ՖoNkSS!hh=z􀜜۷i-Qkzj8tGyRpqxwq||8/!==ufzahnnZ' 7s>W.]ҥI n]Jp:( ш~С 6N0Ҋߕu$ 1cAixJ< ֕i,*4 iuqNjJiu؈G3YJ'j|8iQ;äB9B!@c~8_seC*Co̠DAS_l/R0SVAfQ!#.bZ8n%̊'KL TW繕BDhrێVleyIc!3qJa(&n|in ۔"ua]'bJdL%FH8|1[ Y)9@וRFygTp+CBIzs3+YMgڢV$ ]kʫv׌|-7‡Zvrk̤$1PF$6/zSH%Rv tNXL|`z v@N_v}SFl7qյiM ;zk7TNt+;NvMݬ743$4NH7LnA$u,pnDo"uus4vsZͩmEG-lfJGna'4]P7mKWt39غNt0!Z&2/]xly&t'DNL -TS.&%fb5:b]f"q̋N":DSO+DLx7&u[(U?iz1%QMf꠺ڕi,umAyy9@MM ö +EV뢀*̺:x- EBffLFp/ s<()),{n0yd[:9yW5We <jjjL&`~t;NPx%S?<*ծ1uڒ&ҽJwkM)!զR0rIiQH bZy}80iIK)3M9x+%)xhZI)3cU U0rITw!c 4,~nG/=F\dK 2Ycca(3:]6o]TRp;ExךR9xϴEʮ{{^77N<`zS0ZN(^:)S{־oFiLl:tP߇AC=vtrĈ\uz<镟I;dHMM5oW}I?۳g{Frm^;e镟M=zuiF[ϟ?[nvZ)YLy9r9N)oÆ FtS2.^YINj2i.\hV27'0B~~#^iNwv B0o<G3gھ |IC[O?m.Sb` z0) f³؁4 pڵ f͚%  0c Xt( ;: i^O@SPVVfp HKKS2;/~ 뮻テÇ×_~ ~4a۶m~z8q";wK,Sϴǯ~e`0ɐIIIg8\/W:C^zbZJQ5xz=zN466[o;vf- #Fh%>H $HNN. t]t1@ !@LtMɣhh66)+QkQIo`x<;v0@ү_?ʂdHNN6LQzw\ĎR`b{Lykz0jL6l`0IIIh?~<( RRR.{f̘̓_~;w.[Π:~Pz*hA):%՚X_B4ڱX̤q.\hJJJ b߿aÆ 0~xH$b)kvk_RϘE=x<j@cgcrSR;Ґ paΆ/ٙI (Ӑ)SzK{XZ\e@ cAEElݺ$((,y^ډKN?LZH!55viJ LlW: XT?ԔS2IzRע<K.pM7A04MjKqW:C5ܒ1u{BHi VҜ\S!Ey+JSr5졟I%<ҁ3u!yR ^T!5G(egRwT#xtz՚p$ME(qK5 R0t7W:Ac0,=nѽ\6`JKhsx:t{B]v\crpJf>䒆1ҩ@N/@aP'|sRx+Rkr)]:\t0`G@"LXUIENDB`commons-io-2.11.0-src/src/site/resources/profile.jacoco0100644 0000000 0000000 00000000000 13612062727 023360 0ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/site/site.xml0100644 0000000 0000000 00000004120 13612062727 020223 0ustar00rootroot0000000 0000000 Commons IO /images/io-logo-white.png /index.html commons-io-2.11.0-src/src/site/xdoc/bestpractices.xml0100644 0000000 0000000 00000012325 13612062727 023055 0ustar00rootroot0000000 0000000 Best practices Commons Documentation Team

This document presents a number of 'best practices' in the IO area.

Often, you have to deal with files and filenames. There are many things that can go wrong:

  • A class works in Unix but doesn't on Windows (or vice versa)
  • Invalid filenames due to double or missing path separators
  • UNC filenames (on Windows) don't work with my home-grown filename utility function
  • etc. etc.

These are good reasons not to work with filenames as Strings. Using java.io.File instead handles many of the above cases nicely. Thus, our best practice recommendation is to use java.io.File instead of String for filenames to avoid platform dependencies.

Version 1.1 of commons-io now includes a dedicated filename handling class - FilenameUtils. This does handle many of these filename issues, however we still recommend, wherever possible, that you use java.io.File objects.

Let's look at an example.

public static String getExtension(String filename) { int index = filename.lastIndexOf('.'); if (index == -1) { return ""; } else { return filename.substring(index + 1); } }

Easy enough? Right, but what happens if someone passes in a full path instead of only a filename? Consider the following, perfectly legal path: "C:\Temp\documentation.new\README". The method as defined above would return "new\README" - definitely not what you wanted.

Please use java.io.File for filenames instead of Strings. The functionality that the class provides is well tested. In FileUtils you will find other useful utility functions around java.io.File.

Instead of:

String tmpdir = "/var/tmp"; String tmpfile = tmpdir + System.getProperty("file.separator") + "test.tmp"; InputStream in = new java.io.FileInputStream(tmpfile);

...write:

File tmpdir = new File("/var/tmp"); File tmpfile = new File(tmpdir, "test.tmp"); InputStream in = new java.io.FileInputStream(tmpfile);

IO performance depends a lot from the buffering strategy. Usually, it's quite fast to read packets with the size of 512 or 1024 bytes because these sizes match well with the packet sizes used on harddisks in file systems or file system caches. But as soon as you have to read only a few bytes and that many times performance drops significantly.

Make sure you're properly buffering streams when reading or writing streams, especially when working with files. Just decorate your FileInputStream with a BufferedInputStream:

InputStream in = new java.io.FileInputStream(myfile); try { in = new java.io.BufferedInputStream(in); in.read(..... } finally { IOUtils.closeQuietly(in); }

Pay attention that you're not buffering an already buffered stream. Some components like XML parsers may do their own buffering so decorating the InputStream you pass to the XML parser does nothing but slowing down your code. If you use our CopyUtils or IOUtils you don't need to additionally buffer the streams you use as the code in there already buffers the copy process. Always check the Javadocs for information. Another case where buffering is unnecessary is when you write to a ByteArrayOutputStream since you're writing to memory only.

commons-io-2.11.0-src/src/site/xdoc/building.xml0100644 0000000 0000000 00000004227 13612062727 022021 0ustar00rootroot0000000 0000000 Building Commons Documentation Team

Commons IO uses Maven its build system.

Commons IO requires a minimum of JDK 8 to build.

You may also be interested in the upgrade notes:
Upgrade from 2.0 to 2.0.1
Upgrade from 1.4 to 2.0
Upgrade from 1.3.2 to 1.4
Upgrade from 1.3, or 1.3.1 to 1.3.2
Upgrade from 1.3 to 1.3.1
Upgrade from 1.2 to 1.3
Upgrade from 1.1 to 1.2
Upgrade from 1.0 to 1.1

The following Maven commands can be used to build io:

  • mvn clean - clean up
  • mvn test - compile and run the unit tests
  • mvn site - create io documentation
  • mvn package - build the jar
commons-io-2.11.0-src/src/site/xdoc/description.xml0100644 0000000 0000000 00000023622 13612062727 022547 0ustar00rootroot0000000 0000000 User guide Commons Documentation Team

Commons-IO contains utility classes, endian classes, line iterator, file filters, file comparators and stream implementations.

For a more detailed descriptions, take a look at the Javadocs.

IOUtils contains utility methods dealing with reading, writing and copying. The methods work on InputStream, OutputStream, Reader and Writer.

As an example, consider the task of reading bytes from a URL, and printing them. This would typically done like this:

InputStream in = new URL( "https://commons.apache.org" ).openStream(); try { InputStreamReader inR = new InputStreamReader( in ); BufferedReader buf = new BufferedReader( inR ); String line; while ( ( line = buf.readLine() ) != null ) { System.out.println( line ); } } finally { in.close(); }

With the IOUtils class, that could be done with:

InputStream in = new URL( "https://commons.apache.org" ).openStream(); try { System.out.println( IOUtils.toString( in ) ); } finally { IOUtils.closeQuietly(in); }

In certain application domains, such IO operations are common, and this class can save a great deal of time. And you can rely on well-tested code.

For utility code such as this, flexibility and speed are of primary importance. However you should also understand the limitations of this approach. Using the above technique to read a 1GB file would result in an attempt to create a 1GB String object!

The FileUtils class contains utility methods for working with File objects. These include reading, writing, copying and comparing files.

For example to read an entire file line by line you could use:

File file = new File("/commons/io/project.properties"); List lines = FileUtils.readLines(file, "UTF-8");

The FilenameUtils class contains utility methods for working with filenames without using File objects. The class aims to be consistent between Unix and Windows, to aid transitions between these environments (such as moving from development to production).

For example to normalize a filename removing double dot segments:

String filename = "C:/commons/io/../lang/project.xml"; String normalized = FilenameUtils.normalize(filename); // result is "C:/commons/lang/project.xml"

The FileSystemUtils class contains utility methods for working with the file system to access functionality not supported by the JDK. Currently, the only method is to get the free space on a drive. Note that this uses the command line, not native code.

For example to find the free space on a drive:

long freeSpace = FileSystemUtils.freeSpace("C:/");

Different computer architectures adopt different conventions for byte ordering. In so-called "Little Endian" architectures (eg Intel), the low-order byte is stored in memory at the lowest address, and subsequent bytes at higher addresses. For "Big Endian" architectures (eg Motorola), the situation is reversed.

There are two classes in this package of relevance:

  • The EndianUtils class contains static methods for swapping the Endian-ness of Java primitives and streams.
  • The SwappedDataInputStream class is an implementation of the DataInput interface. With this, one can read data from files of non-native Endian-ness.

For more information, see http://www.cs.umass.edu/~verts/cs32/endian.html

The org.apache.commons.io.LineIterator class provides a flexible way for working with a line-based file. An instance can be created directly, or via factory methods on FileUtils or IOUtils. The recommended usage pattern is:

LineIterator it = FileUtils.lineIterator(file, "UTF-8"); try { while (it.hasNext()) { String line = it.nextLine(); /// do something with line } } finally { LineIterator.closeQuietly(iterator); }

The org.apache.commons.io.filefilter package defines an interface (IOFileFilter) that combines both java.io.FileFilter and java.io.FilenameFilter. Besides that the package offers a series of ready-to-use implementations of the IOFileFilter interface including implementation that allow you to combine other such filters. These filters can be used to list files or in FileDialog, for example.

See the filefilter package javadoc for more details.

The org.apache.commons.io.comparator package provides a number of java.util.Comparator implementations for java.io.File. These comparators can be used to sort lists and arrays of files, for example.

See the comparator package javadoc for more details.

The org.apache.commons.io.input and org.apache.commons.io.output packages contain various useful implementations of streams. These include:

  • Null output stream - that silently absorbs all data sent to it
  • Tee output stream - that sends output data to two streams instead of one
  • Byte array output stream - that is a faster version of the JDK class
  • Counting streams - that count the number of bytes passed
  • Proxy streams - that delegate to the correct method in the proxy
  • Lockable writer - that provides synchronization of writes using a lock file

See the input or output package javadoc for more details.

commons-io-2.11.0-src/src/site/xdoc/download_io.xml0100644 0000000 0000000 00000020060 13612062727 022513 0ustar00rootroot0000000 0000000 Download Apache Commons IO Apache Commons Documentation Team

We recommend you use a mirror to download our release builds, but you must verify the integrity of the downloaded files using signatures downloaded from our main distribution directories. Recent releases (48 hours) may not yet be available from all the mirrors.

You are currently using [preferred]. If you encounter a problem with this mirror, please select another mirror. If all mirrors are failing, there are backup mirrors (at the end of the mirrors list) that should be available.

[if-any logo][end]

Other mirrors:

It is essential that you verify the integrity of downloaded files, preferably using the PGP signature (*.asc files); failing that using the SHA512 hash (*.sha512 checksum files).

The KEYS file contains the public PGP keys used by Apache Commons developers to sign releases.

commons-io-2.11.0-bin.tar.gz sha512 pgp
commons-io-2.11.0-bin.zip sha512 pgp
commons-io-2.11.0-src.tar.gz sha512 pgp
commons-io-2.11.0-src.zip sha512 pgp

Older releases can be obtained from the archives.

commons-io-2.11.0-src/src/site/xdoc/index.xml0100644 0000000 0000000 00000021004 13612062727 021323 0ustar00rootroot0000000 0000000 Commons IO Overview Commons Documentation Team

Apache Commons IO is a library of utilities to assist with developing IO functionality.

There are six main areas included:

  • io - This package defines utility classes for working with streams, readers, writers and files.
  • comparator - This package provides various Comparator implementations for Files.
  • file - This package provides extensions in the realm of java.nio.file.
  • filefilter - This package defines an interface (IOFileFilter) that combines both FileFilter and FilenameFilter.
  • function - This package defines IO-only related functional interfaces for lambda expressions and method references.
  • input - This package provides implementations of input classes, such as InputStream and Reader.
  • input.buffer - This package provides implementations of buffered input classes, such as CircularBufferInputStream and PeekableInputStream.
  • monitor - This package provides a component for monitoring file system events (directory and file create, update and delete events).
  • output - This package provides implementations of output classes, such as OutputStream and Writer.
  • serialization - This package provides a framework for controlling the deserialization of classes.

Commons IO 2.11.0 requires a minimum of Java 8 - Download now!

View the Release Notes and Javadoc API documents

Commons IO 2.10.0 requires a minimum of Java 8 - Download now!

View the Release Notes and Javadoc API documents

Commons IO 2.9.0 requires a minimum of Java 8 - Download now!

View the Release Notes and Javadoc API documents

Commons IO 2.8.0 requires a minimum of Java 8 - Download now!

View the Release Notes and Javadoc API documents

Commons IO 2.7 requires a minimum of Java 8 - Download now!

View the Release Notes and Javadoc API documents

Commons IO 2.6 requires a minimum of Java 7 - Download now!

View the Release Notes and Javadoc API documents

Commons IO 2.5 requires a minimum of Java 6 - Download now!

View the Release Notes and Javadoc API documents

Commons IO 2.4 requires a minimum of JDK 1.6 - Download now!

View the Release Notes and Javadoc API documents

Commons IO 2.3 requires a minimum of JDK 1.6 - Download now!

View the Release Notes and Javadoc API documents

Commons IO 2.2 requires a minimum of JDK 1.5 - Download now!

View the Release Notes and Javadoc API documents

For previous releases, see the Apache Archive and Javadoc Archive

The commons mailing lists act as the main support forum. The user list is suitable for most library usage queries. The dev list is intended for the development discussion. Please remember that the lists are shared between all commons components, so prefix your email by [io].

Issues may be reported via ASF JIRA. Please read the instructions carefully to submit a useful bug report or enhancement request.

commons-io-2.11.0-src/src/site/xdoc/issue-tracking.xml0100644 0000000 0000000 00000013316 13612062727 023153 0ustar00rootroot0000000 0000000 Apache Commons IO Issue tracking Apache Commons Documentation Team

Apache Commons IO uses ASF JIRA for tracking issues. See the Apache Commons IO JIRA project page.

To use JIRA you may need to create an account (if you have previously created/updated Commons issues using Bugzilla an account will have been automatically created and you can use the Forgot Password page to get a new password).

If you would like to report a bug, or raise an enhancement request with Apache Commons IO please do the following:

  1. Search existing open bugs. If you find your issue listed then please add a comment with your details.
  2. Search the mailing list archive(s). You may find your issue or idea has already been discussed.
  3. Decide if your issue is a bug or an enhancement.
  4. Submit either a bug report or enhancement request.

Please also remember these points:

  • the more information you provide, the better we can help you
  • test cases are vital, particularly for any proposed enhancements
  • the developers of Apache Commons IO are all unpaid volunteers

For more information on subversion and creating patches see the Apache Contributors Guide.

You may also find these links useful:

commons-io-2.11.0-src/src/site/xdoc/mail-lists.xml0100644 0000000 0000000 00000023663 13612062727 022307 0ustar00rootroot0000000 0000000 Apache Commons IO Mailing Lists Apache Commons Documentation Team

Apache Commons IO shares mailing lists with all the other Commons Components. To make it easier for people to only read messages related to components they are interested in, the convention in Commons is to prefix the subject line of messages with the component's name, for example:

  • [io] Problem with the ...

Questions related to the usage of Apache Commons IO should be posted to the User List.
The Developer List is for questions and discussion related to the development of Apache Commons IO.
Please do not cross-post; developers are also subscribed to the user list.
You must be subscribed to post to the mailing lists. Follow the Subscribe links below to subscribe.

Note: please don't send patches or attachments to any of the mailing lists. Patches are best handled via the Issue Tracking system. Otherwise, please upload the file to a public server and include the URL in the mail.

Please prefix the subject line of any messages for Apache Commons IO with [io] - thanks!

Name Subscribe Unsubscribe Post Archive Other Archives
Commons User List

Questions on using Apache Commons IO.

Subscribe Unsubscribe Post mail-archives.apache.org
lists.apache.org
markmail.org
www.mail-archive.com
news.gmane.org
Commons Developer List

Discussion of development of Apache Commons IO.

Subscribe Unsubscribe Post mail-archives.apache.org
lists.apache.org
markmail.org
www.mail-archive.com
news.gmane.org
Commons Issues List

Only for e-mails automatically generated by the issue tracking system.

Subscribe Unsubscribe read only mail-archives.apache.org
lists.apache.org
markmail.org
www.mail-archive.com
Commons Commits List

Only for e-mails automatically generated by the source control sytem.

Subscribe Unsubscribe read only mail-archives.apache.org
lists.apache.org
markmail.org
www.mail-archive.com

Other mailing lists which you may find useful include:

Name Subscribe Unsubscribe Post Archive Other Archives
Apache Announce List

General announcements of Apache project releases.

Subscribe Unsubscribe read only mail-archives.apache.org
lists.apache.org
markmail.org
old.nabble.com
www.mail-archive.com
news.gmane.org
commons-io-2.11.0-src/src/site/xdoc/proposal.xml0100644 0000000 0000000 00000006230 13612062727 022057 0ustar00rootroot0000000 0000000 Proposal Commons Documentation Team

Many software projects have a need to perform I/O in various ways, and the JDK class libraries provide a lot of functionality, but sometimes you need just a little bit more. The io package seeks to encapsulate some of the most popular i/o base classes into one easy to use package.

This proposal is to create a package of Java utility classes for various types of i/o related activity.

IO relies only on standard JDK 1.2 (or later) APIs for production deployment. It utilizes the JUnit unit testing framework for developing and executing unit tests, but this is of interest only to developers of the component. IO will be a dependency for several existing components in the open source world.

No external configuration files are utilized.

The original Java classes are splashed around various Apache subprojects. We intend to seek them out and integrate them.

The proposed package name for the new component is org.apache.commons.io.

  • CVS Repository - New directory io in the jakarta-commons CVS repository.
  • Mailing List - Discussions will take place on the general dev@commons.apache.org mailing list. To help list subscribers identify messages of interest, it is suggested that the message subject of messages about this component be prefixed with [IO].
  • Bugzilla - New component "IO" under the "Commons" product category, with appropriate version identifiers as needed.
  • Jyve FAQ - New category "commons-io" (when available).

The initial committers on the IO component shall be Scott Sanders and Nicola Ken Barozzi and Henri Yandell

commons-io-2.11.0-src/src/site/xdoc/tasks.xml0100644 0000000 0000000 00000003447 13612062727 021354 0ustar00rootroot0000000 0000000 Tasks Commons Documentation Team

The following are some of the proposed ideas and tasks for commons-io:

  • A proper user guide
  • A URLUtils class that has many of the FileUtils operations, but for a URL
  • FilePoller for telling when a file changes. Look in Tomcat, or GenJava[bayard] (One implemented in bugzilla awaiting investigation)
  • A "hot folder" handler which triggers an action when a new file has been uploaded to an FTP directory, for example.
  • JoinReader/ConcatReader. One in GenJava, one submitted to Bayard
  • FormattedWriter, when it writes out values it uses Format objects to output them.
  • FixedWidthReader. Reads in files with a known width, ie) mainframe like.
commons-io-2.11.0-src/src/site/xdoc/upgradeto1_1.xml0100644 0000000 0000000 00000015455 13612062727 022524 0ustar00rootroot0000000 0000000 Upgrade from 1.0 to 1.1 Commons Documentation Team

These are the release notes and advice for upgrading Commons-IO from version 1.0 to version 1.1. Commons IO is a package of Java utility classes for java.io's hierarchy. Classes in this package are considered to be so standard and of such high reuse as to justify existence in java.io. Commons IO contains utility classes, stream implementations, file filters, and endian transformation classes. Incompatible changes from 1.0 ----------------------------- Binary compatible - Yes Source compatible - Yes Semantic compatible - Yes, except: - FileUtils.writeStringToFile() A null encoding previously used 'ISO-8859-1', now it uses the platform default Generally this will make no difference - LockableFileWriter Improved validation and now create directories if necesssary plus these bug fixes may affect you semantically: - FileUtils.touch() (Bug fix 29821) Now creates the file if it did not previously exist - FileUtils.toFile(URL) (Bug fix 32575) Now handles escape syntax such as %20 - FileUtils.sizeOfDirectory() (Bug fix 36801) May now return a size of 0 if the directory is security restricted Deprecations from 1.0 --------------------- - CopyUtils has been deprecated. Its methods have been moved to IOUtils. The new IOUtils methods handle nulls better, and have clearer names. - IOUtils.toByteArray(String) - Use {@link String#getBytes()} - IOUtils.toString(byte[]) - Use {@link String#String(byte[])} - IOUtils.toString(byte[],String) - Use {@link String#String(byte[],String)} Bug fixes from 1.0 ------------------ - FileUtils - touch() [29821] Now creates the file if it did not previously exist - FileUtils - toFile(URL) [32575] Now handles escape syntax such as %20 - FileFilterUtils - makeCVSAware(IOFileFilter) [33023] Fixed bug that caused method to be completely broken - CountingInputStream [33336] Fixed bug that caused the count to reduce by one at the end of the stream - CountingInputStream - skip(long) [34311] Bytes from calls to this method were not previously counted - NullOutputStream [33481] Remove unnecessary synchronization - AbstractFileFilter - accept(File, String) [30992] Fixed broken implementation - FileUtils [36801] Previously threw NPE when listing files in a security restricted directory Now throw IOException with a better message - FileUtils - writeStringToFile() Null encoding now correctly uses the platform default Enhancements from 1.0 --------------------- - FilenameUtils - new class [33303,29351] A static utility class for working with filenames Seeks to ease the pain of developing on Windows and deploying on Unix - FileSystemUtils - new class [32982,36325] A static utility class for working with file systems Provides one method at present, to get the free space on the filing system - IOUtils - new public constants Constants for directory and line separators on Windows and Unix - IOUtils - toByteArray(Reader,encoding) Handles encodings when reading to a byte array - IOUtils - toCharArray(InputStream) [28979] - toCharArray(InputStream,encoding) - toCharArray(Reader) Reads a stream/reader into a charatcter array - IOUtils - readLines(InputStream) [36214] - readLines(InputStream,encoding) - readLines(Reader) Reads a stream/reader line by line into a List of Strings - IOUtils - toInputStream(String) [32958] - toInputStream(String,encoding) Creates an input stream that uses the string as a source of data - IOUtils - writeLines(Collection,lineEnding,OutputStream) [36214] - writeLines(Collection,lineEnding,OutputStream,encoding) - writeLines(Collection,lineEnding,Writer) Writes a collection to a stream/writer line by line - IOUtils - write(...) Write data to a stream/writer (moved from CopyUtils with better null handling) - IOUtils - copy(...) Copy data between streams (moved from CopyUtils with better null handling) - IOUtils - contentEquals(Reader,Reader) Method to compare the contents of two readers - FileUtils - toFiles(URL[]) Converts an array of URLs to an array of Files - FileUtils - copyDirectory() [32944] New methods to copy a directory - FileUtils - readFileToByteArray(File) Reads an entire file into a byte array - FileUtils - writeByteArrayToFile(File,byte[]) Writes a byte array to a file - FileUtils - readLines(File,encoding) [36214] Reads a file line by line into a List of Strings - FileUtils - writeLines(File,encoding,List) writeLines(File,encoding,List,lineEnding) Writes a collection to a file line by line - FileUtils - EMPTY_FILE_ARRAY Constant for an empty array of File objects - ConditionalFileFilter - new interface [30705] Defines the behavior of list based filters - AndFileFilter, OrFileFilter [30705] Now support a list of filters to and/or - WildcardFilter [31115] New filter that can match using wildcard file names - FileFilterUtils - makeSVNAware(IOFileFilter) New method, like makeCVSAware, that ignores Subversion source control directories - ClassLoaderObjectInputStream An ObjectInputStream that supports a ClassLoader - CountingInputStream,CountingOutputStream - resetCount() [28976] Adds the ability to reset the count part way through reading/writing the stream - DeferredFileOutputStream - writeTo(OutputStream) [34173] New method to allow current contents to be written to a stream - DeferredFileOutputStream [34142] Performance optimizations avoiding double buffering - LockableFileWriter - encoding support [36825] Add support for character encodings to LockableFileWriter Improve the validation Create directories if necesssary - IOUtils and EndianUtils are no longer final [28978] Allows developers to have subclasses if desired

commons-io-2.11.0-src/src/site/xdoc/upgradeto1_2.xml0100644 0000000 0000000 00000005150 13612062727 022514 0ustar00rootroot0000000 0000000 Upgrade from 1.1 to 1.2 Commons Documentation Team

These are the release notes and advice for upgrading Commons-IO from version 1.1 to version 1.2. Commons IO is a package of Java utility classes for java.io's hierarchy. Classes in this package are considered to be so standard and of such high reuse as to justify existence in java.io. Commons IO contains utility classes, stream implementations, file filters, and endian transformation classes. Compatibility with 1.1 ---------------------- Binary compatible - Yes Source compatible - Yes Semantic compatible - Yes Deprecations from 1.1 --------------------- Bug fixes from 1.1 ------------------ - FileSystemUtils.freeSpace(drive) Fix to allow Windows based command to function in French locale - FileUtils.read* Increase certainty that files are closed in case of error - LockableFileWriter Locking mechanism was broken and only provided limited protection [38942] File deletion and locking in case of constructor error was broken Enhancements from 1.1 --------------------- - AgeFileFilter/SizeFileFilter New file filters that compares against the age and size of the file - FileSystemUtils.freeSpaceKb(drive) New method that unifies result to be in kilobytes [38574] - FileUtils.contentEquals(File,File) Performance improved by adding length and file location checking - FileUtils.iterateFiles Two new method to provide direct access to iterators over files - FileUtils.lineIterator IOUtils.lineIterator New methods to provide an iterator over the lines in a file [38083] - FileUtils.copyDirectoryToDirectory New method to copy a directory to within another directory [36315]

commons-io-2.11.0-src/src/site/xdoc/upgradeto1_3.xml0100644 0000000 0000000 00000017704 13612062727 022525 0ustar00rootroot0000000 0000000 Upgrade from 1.2 to 1.3 Commons Documentation Team

These are the release notes and advice for upgrading Commons-IO from version 1.2 to version 1.3. Commons IO is a package of Java utility classes for java.io's hierarchy. Classes in this package are considered to be so standard and of such high reuse as to justify existence in java.io. Commons IO contains utility classes, stream implementations, file filters, and endian transformation classes. Compatibility with 1.2 ---------------------- Binary compatible - Yes Source compatible - Yes Semantic compatible - Yes Check the bug fixes section for semantic bug fixes Deprecations from 1.2 --------------------- - WildcardFilter deprecated, replaced by WildcardFileFilter - old class only accepted files, thus had a confusing dual purpose - FileSystemUtils.freeSpace deprecated, replaced by freeSpaceKb - freeSpace returns a result that varies by operating system and thus isn't that useful - freeSpaceKb returns much better and more consistent results - freeSpaceKb existed in v1.2, so this is a gentle cutover Bug fixes from 1.2 ------------------ - LineIterator now implements Iterator - It was always supposed to... - FileSystemUtils.freeSpace/freeSpaceKb [IO-83] - These should now work on AIX and HP-UX - FileSystemUtils.freeSpace/freeSpaceKb [IO-90] - Avoid infinite looping in Windows - Catch more errors with nice messages - FileSystemUtils.freeSpace [IO-91] - This is now documented not to work on SunOS 5 - FileSystemUtils [IO-93] - Fixed resource leak leading to 'Too many open files' error - Previously did not destroy Process instances (as JDK Javadoc is so poor) - http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4801027 - FileUtils.touch [IO-100] - The touch method previously gave no indication when the file could not be touched successfully (such as due to access restrictions) - it now throws an IOException if the last modified date cannot be changed - FileCleaner - This now handles the situation where an error occurs when deleting the file - IOUtils.copy [IO-84] - Copy methods could return inaccurate byte/char count for large streams - The copy(InputStream, OutputStream) method now returns -1 if the count is greater than an int - The copy(Reader, Writer) method now throws now returns -1 if the count is greater than an int - Added a new copyLarge(InputStream, OutputStream) method that returns a long - Added a new copyLarge(Reader, Writer) method that returns a long - CountingInputStream/CountingOutputStream [IO-84] - Methods were declared as int thus the count was innacurate for large streams - new long based methods getByteCount()/resetByteCount() added - existing methods changed to throw an exception if the count is greater than an int - FileBasedTestCase - Fixed bug in compare content methods identified by GNU classpath - EndianUtils.writeSwappedLong(byte[], int) [IO-101] - An int overrun in the bit shifting when it should have been a long - EndianUtils.writeSwappedLong(InputStream) [IO-102] - The return of input.read(byte[]) was not being checked to ensure all 8 bytes were read Enhancements from 1.2 --------------------- - DirectoryWalker [IO-86] - New class designed for subclassing to walk through a set of files. DirectoryWalker provides the walk of the directories, filtering of directories and files, and cancellation support. The subclass must provide the specific behavior, such as text searching or image processing. - IOCase - New class/enumeration for case-sensitivity control - FilenameUtils - New methods to handle case-sensitivity - wildcardMatch - new method that has IOCase as a parameter - equals - new method that has IOCase as a parameter - FileUtils [IO-108] - new default encoding methods for: - readFileToString(File) - readLines(File) - lineIterator(File) - writeStringToFile(File, String) - writeLines(File, Collection) - writeLines(File, Collection, String) - FileUtils.openOutputStream [IO-107] - new method to open a FileOutputStream, creating parent directories if required - FileUtils.touch - FileUtils.copyURLToFile - FileUtils.writeStringToFile - FileUtils.writeByteArrayToFile - FileUtils.writeLines - enhanced to create parent directories if required - FileUtils.openInputStream [IO-107] - new method to open a FileInputStream, providing better error messages than the JDK - FileUtils.isFileOlder - new methods to check if a file is older (i.e. isFileOlder()) - counterparts to the existing isFileNewer() methods. - FileUtils.checksum, FileUtils.checksumCRC32 - new methods to create a checksum of a file - FileUtils.copyFileToDirectory [IO-104] - new variant that optionally retains the file date - FileDeleteStrategy - FileCleaner [IO-56,IO-70] - FileDeleteStrategy is a strategy for handling file deletion - This can be used as a calback in FileCleaner - Together these allow FileCleaner to do a forceDelete to kill directories - FileCleaner.exitWhenFinished [IO-99] - A new method that allows the internal cleaner thread to be cleanly terminated - WildcardFileFilter - Replacement for WildcardFilter - Accepts both files and directories - Ability to control case-sensitivity - NameFileFilter - Ability to control case-sensitivity - FileFileFilter - New IOFileFilter implementation - Accepts files where File.isFile() is true - In other words it filters out directories - Singleton instance provided (FILE) - CanReadFileFilter - New IOFileFilter implementation - Accepts files where File.canRead() is true - Singleton instances provided (CAN_READ/CANNOT_READ/READ_ONLY) - CanWriteFileFilter - New IOFileFilter implementation - Accepts files where File.canWrite() is true - Singleton instances provided (CAN_WRITE/CANNOT_WRITE) - HiddenFileFilter - New IOFileFilter implementation - Accepts files where File.isHidden() is true - Singleton instances provided (HIDDEN/VISIBLE) - EmptyFileFilter - New IOFileFilter implementation - Accepts files or directories that are empty - Singleton instances provided (EMPTY/NOT_EMPTY) - TrueFileFilter/FalseFileFilter/DirectoryFileFilter - New singleton instance constants (TRUE/FALSE/DIRECTORY) - The new constants are more JDK 1.5 friendly with regards to static imports (whereas if everything uses INSTANCE, then they just clash) - The old INSTANCE constants are still present and have not been deprecated - FileFilterUtils.sizeRangeFileFilter - new sizeRangeFileFilter(long minimumSize, long maximumSize) method which creates a filter that accepts files within the specified size range. - FileFilterUtils.makeDirectoryOnly/makeFileOnly - two new methods that decorate a file filter to make it apply to directories only or files only - NullWriter - New writer that acts as a sink for all data, as per /dev/null - NullInputStream - New input stream that emulates a stream of a specified size - NullReader - New reader that emulates a reader of a specified size - ByteArrayOutputStream [IO-97] - Performance enhancements

commons-io-2.11.0-src/src/site/xdoc/upgradeto1_3_1.xml0100644 0000000 0000000 00000003355 13612062727 022742 0ustar00rootroot0000000 0000000 Upgrade from 1.3 to 1.3.1 Commons Documentation Team

These are the release notes and advice for upgrading Commons-IO from version 1.3 to version 1.3.1. Commons IO is a package of Java utility classes for java.io's hierarchy. Classes in this package are considered to be so standard and of such high reuse as to justify existence in java.io. Commons IO contains utility classes, stream implementations, file filters, and endian transformation classes. Compatibility with 1.3 ---------------------- Binary compatible - No See [IO-113] Source compatible - No See [IO-113] Semantic compatible - Yes Bug fixes from 1.3 ------------------ - FileUtils - NPE in openOutputStream(File) when file has no parent in path [IO-112] - readFileToString(File) is not static [IO-113]

commons-io-2.11.0-src/src/site/xdoc/upgradeto1_3_2.xml0100644 0000000 0000000 00000004663 13612062727 022746 0ustar00rootroot0000000 0000000 Upgrade from 1.3, or 1.3.1, to 1.3.2 Commons Documentation Team

These are the release notes and advice for upgrading Commons-IO from version 1.3, or 1.3.1, to version 1.3.2. Commons IO is a package of Java utility classes for java.io's hierarchy. Classes in this package are considered to be so standard and of such high reuse as to justify existence in java.io. Commons IO contains utility classes, stream implementations, file filters, and endian transformation classes. Compatibility with 1.3.1 ------------------------ Binary compatible - Yes Source compatible - Yes Semantic compatible - Yes Check the bug fixes section for semantic bug fixes Compatibility with 1.3 ---------------------- Binary compatible - No See [IO-113] Source compatible - No See [IO-113] Semantic compatible - Yes Enhancements since 1.3.1 ------------------------ - Created the FileCleaningTracker, basically a non-static version of the FileCleaner, which can be controlled by the user. [IO-116] - The FileCleaner is deprecated. (For reasons of compatibility, the deprecation warnings are hidden within the 1.3 branch. They'll be visible, as of version 1.4.) Bug fixes from 1.3.1 -------------------- - Some tests, which are implicitly assuming a Unix-like file system, are now skipped on Windows. [IO-115] Bug fixes from 1.3 ------------------ - FileUtils - NPE in openOutputStream(File) when file has no parent in path [IO-112] - readFileToString(File) is not static [IO-113]

commons-io-2.11.0-src/src/site/xdoc/upgradeto1_4.xml0100644 0000000 0000000 00000011640 13612062727 022517 0ustar00rootroot0000000 0000000 Upgrade from 1.3.2 to 1.4 Commons Documentation Team

These are the release notes and advice for upgrading Commons-IO from version 1.3.2 to version 1.4. Commons IO is a package of Java utility classes for java.io's hierarchy. Classes in this package are considered to be so standard and of such high reuse as to justify existence in java.io. Commons IO contains utility classes, stream implementations, file filters, file comparators and endian transformation classes. Compatibility with 1.3.2 ------------------------ Binary compatible - Yes Source compatible - Yes Semantic compatible - Yes Check the bug fixes section for semantic bug fixes Commons IO 1.4 introduces four new implementations which depend on JDK 1.4 features (CharSequenceReader, FileWriterWithEncoding, IOExceptionWithCause and RegexFileFilter). It has been built with the JDK source and target options set to JDK 1.3 and, except for those implementations, can be used with JDK 1.3 (see IO IO-127). Deprecations from 1.3.2 ----------------------- - FileCleaner deprecated in favour of FileCleaningTracker [see IO-116] Bug fixes from 1.3.2 -------------------- - FileUtils - forceDelete of orphaned Softlinks does not work [IO-147] - Infinite loop on FileUtils.copyDirectory when the destination directory is within the source directory [IO-141] - HexDump - HexDump's use of static StringBuffers isn't thread-safe [IO-136] Enhancements from 1.3.2 ----------------------- - FileUtils - Add a deleteQuietly method [IO-135] - Add a copyDirectory() method that makes use of FileFilter [IO-105] - Add moveDirectory() and moveFile() methods [IO-77] - FilenameUtils - Add file name extension separator constants[IO-149] - IOExceptionWithCause [IO-148] - Add a new IOException implementation with constructors which take a cause - TeeInputStream [IO-129] - Add new Tee input stream implementation - FileWriterWithEncoding [IO-153] - Add new File Writer implementation that accepts an encoding - CharSequenceReader [IO-138] - Add new Reader implementation that handles any CharSequence (String, StringBuffer, StringBuilder or CharBuffer) - ThesholdingOuputStream [IO-121] - Add a reset() method which sets the count of the bytes written back to zero. - DeferredFileOutputStream [IO-130] - Add support for temporary files - ByteArrayOutputStream - Add a new write(InputStream) method [IO-152] - New Closed Input/Output stream implementations [IO-122] - AutoCloseInputStream - automatically closes and discards the underlying input stream - ClosedInputStream - returns -1 for any read attempts - ClosedOutputStream - throws an IOException for any write attempts - CloseShieldInputStream - prevents the underlying input stream from being closed. - CloseShieldOutputStream - prevents the underlying output stream from being closed. - Add Singleton Constants to several stream classes [IO-143] - PrefixFileFilter [IO-126] - Add faciltiy to specify case sensitivity on prefix matching - SuffixFileFilter [IO-126] - Add faciltiy to specify case sensitivity on suffix matching - RegexFileFilter [IO-74] - Add new regular expression file filter implementation - Make IOFileFilter implementations Serializable [IO-131] - Improve IOFileFilter toString() methods [IO-120] - Make fields final so classes are immutable/threadsafe [IO-133] - changes to Age, Delegate, Name, Not, Prefix, Regex, Size, Suffix and Wildcard IOFileFilter implementations. - IOCase - Add a compare method to IOCase [IO-144] - Add a package of java.util.Comparator implementations for files [IO-145] - DefaultFileComparator - compare files using the default File.compareTo(File) method. - ExtensionFileComparator - compares files using file name extensions. - LastModifiedFileComparator - compares files using the last modified date/time. - NameFileComparator - compares files using file names. - PathFileComparator - compares files using file paths. - SizeFileComparator - compares files using file sizes.

commons-io-2.11.0-src/src/site/xdoc/upgradeto2_0.xml0100644 0000000 0000000 00000017742 13612062727 022525 0ustar00rootroot0000000 0000000 Upgrade from 1.4 to 2.0 Commons Documentation Team

These are the release notes and advice for upgrading Commons-IO from version 1.4 to version 2.0. Commons IO is a package of Java utility classes for java.io's hierarchy. Classes in this package are considered to be so standard and of such high reuse as to justify existence in java.io. Commons IO contains utility classes, stream implementations, file filters, file comparators and endian transformation classes. Compatibility with 1.4 ---------------------- Binary compatible - Yes Source compatible - Yes Semantic compatible - Yes Check the bug fixes section for semantic bug fixes Commons IO 2.0 requires a minimum of JDK 1.5 (Commons IO 1.4 had a minimum of JDK 1.3) Deprecations from 1.4 --------------------- - IOUtils - write(StringBuffer, Writer) in favour of write(CharSequence, Writer) - write(StringBuffer, OutputStream) in favour of write(CharSequence, OutputStream) - write(StringBuffer, OutputStream, String) in favour of write(CharSequence, OutputStream, String) - FileFilterUtils - andFileFilter(IOFileFilter, IOFileFilter) in favour of and(IOFileFilter...) - orFileFilter(IOFileFilter, IOFileFilter) in favour of or(IOFileFilter...) Enhancements from 1.4 --------------------- * [IO-140] Move minimum Java requirement from JDK 1.3 to JDK 1.5 - use Generics - add new CharSequence write() flavour methods to IOUtils and FileUtils - replace StringBuffer with StringBuilder, where appropriate - add new Reader/Writer methods to ProxyReader and ProxyWriter - Annotate with @Override and @Deprecated * [IO-178] New BOMInputStream and ByteOrderMark implementations - to detect and optionally exclude an initial Byte Order mark (BOM) * [IO-197] New BoundedInputStream (copied from from Apache JackRabbit) * [IO-193] New Broken Input and Output streams * [IO-132] New File Listener/Monitor facility * [IO-158] New ReaderInputStream and WriterOutputStream implementations * [IO-139] New StringBuilder Writer implementation * [IO-192] New Tagged Input and Output streams * [IO-177] New Tailer class - simple implementation of the Unix "tail -f" functionality * [IO-162] New XML Stream Reader/Writer implementations (from ROME via plexus-utils) * [IO-142] Comparators - add facility to sort file lists/arrays * [IO-186] Comparators - new Composite and Directory File Comparator implementations * [IO-176] DirectoryWalker - add filterDirectoryContents() callback method for filtering directory contents * [IO-210] FileFilter - new Magic Number FileFilter * [IO-221] FileFilterUtils - add methods for suffix and prefix filters which take an IOCase object * [IO-232] FileFilterUtils - add method for name filters which take an IOCase object * [IO-229] FileFilterUtils - add varargs and() and or() methods * [IO-198] FileFilterUtils - add ability to apply file filters to collections and arrays * [IO-156] FilenameUtils - add normalize() and normalizeNoEndSeparator() methods which allow the separator character to be specified * [IO-194] FileSystemUtils - add freeSpaceKb() method with no input arguments * [IO-185] FileSystemUtils - add freeSpaceKb() methods that take a timeout parameter - fixes freeSpaceWindows() blocks * [IO-155] FileUtils - use NIO to copy files * [IO-168] FileUtils - add new isSymlink() method * [IO-219] FileUtils - throw FileExistsException when moving a file or directory if the destination already exists * [IO-234] FileUtils - add Methods for retrieving System User/Temp directories/paths * [IO-208] FileUtils - add timeout (connection and read) support for copyURLToFile() method * [IO-238] FileUtils - add sizeOf(File) method * [IO-181] LineIterator now implements Iterable * [IO-224] IOUtils - add closeQuietly(Closeable) and closeQuietly(Socket) methods * [IO-203] IOUtils - add skipFully() method for InputStreams * [IO-137] IOUtils and ByteArrayOutputStream - add toBufferedInputStream() method to avoid unnecessary array allocation/copy * [IO-195] Proxy streams/Reader/Writer - provide exception handling methods * [IO-211] Proxy Input/Output streams - add pre/post processing support * [IO-242] Proxy Reader/Writer - add pre/post processing support Bug fixes from 1.4 ------------------ * [IO-214] ByteArrayOutputStream - fix inconsistent synchronization of fields * [IO-201] Counting Input/Output streams - fix inconsistent synchronization * [IO-159] FileCleaningTracker - fix remove() never returns null * [IO-220] FileCleaningTracker - fix Vector performs badly under load * [IO-167] FilenameUtils - fix case-insensitive string handling in FilenameUtils and FilesystemUtils * [IO-179] FilenameUtils - fix StringIndexOutOfBounds exception in getPathNoEndSeparator() * [IO-248] FilenameUtils - fix getFullPathNoEndSeparator() returns empty while path is a one level directory * [IO-246] FilenameUtils - fix wildcardMatch gives incorrect results * [IO-187] FileSystemUtils - fix freeSpaceKb() doesn't work with relative paths on Linux * [IO-160] FileSystemUtils - fix freeSpace() fails on solaris * [IO-209] FileSystemUtils - fix freeSpaceKb() fails to return correct size for a windows mount point * [IO-163] FileUtils - fix toURLs() using deprecated method of conversion to URL * [IO-168] FileUtils - fix Symbolic links followed when deleting directory * [IO-231] FileUtils - fix wrong exception message generated in isFileNewer() method * [IO-207] FileUtils - fix race condition in forceMkdir() method * [IO-217] FileUtils - fix copyDirectoryToDirectory() makes infinite loops * [IO-166] FileUtils - fix URL decoding in toFile(URL) * [IO-190] FileUtils - fix copyDirectory not preserving lastmodified date on sub-directories * [IO-240] FileFilterUtils - ensure cvsFilter and svnFilter are only created once. * [IO-175] IOUtils - fix copyFile() issues with very large files * [IO-191] Improvements from static analysis * [IO-216] LockableFileWriter - delete files quietly when an exception is thrown during initialization * [IO-243] SwappedDataInputStream - fix readBoolean is inverted * [IO-235] Tests - remove unused YellOnFlushAndCloseOutputStream from CopyUtilsTest * [IO-161] Tests - fix FileCleaningTrackerTestCase hanging Documentation changes from 1.4 ------------------------------ * [IO-183 FilenameUtils.getExtension() method documentation improvements * [IO-226 FileUtils.byteCountToDisplaySize() documentation corrections * [IO-205 FileUtils.forceMkdir() documentation improvements * [IO-215 FileUtils copy file/directory improve documentation regarding preserving the last modified date * [IO-189 HexDump.dump() method documentation improvements * [IO-171 IOCase document that it assumes there are only two OSes: Windows and Unix * [IO-223 IOUtils.copy() documentation corrections * [IO-247 IOUtils.closeQuietly() improve documentation with examples * [IO-202 NotFileFilter documentation corrections * [IO-206 ProxyInputStream - fix misleading parameter names * [IO-212 ProxyInputStream.skip() documentation corrections

commons-io-2.11.0-src/src/site/xdoc/upgradeto2_0_1.xml0100644 0000000 0000000 00000004005 13612062727 022731 0ustar00rootroot0000000 0000000 Upgrade from 2.0 to 2.0.1 Commons Documentation Team

These are the release notes and advice for upgrading Commons-IO from version 2.0 to version 2.0.1 Commons IO is a package of Java utility classes for java.io's hierarchy. Classes in this package are considered to be so standard and of such high reuse as to justify existence in java.io. Commons IO contains utility classes, stream implementations, file filters, file comparators and endian transformation classes. Compatibility with 2.0 and 1.4 ------------------------------ Binary compatible - Yes Source compatible - Yes Semantic compatible - Yes Check the bug fixes section for semantic bug fixes Commons IO 2.0.1 requires a minimum of JDK 1.5 (Commons IO 1.4 had a minimum of JDK 1.3) Enhancements from 2.0 --------------------- * [IO-256] - Provide thread factory for FileAlternationMonitor Bug fixes from 2.0 ------------------ * [IO-257] - BOMInputStream.read(byte[]) can return 0 which it should not * [IO-258] - XmlStreamReader consumes the stream during encoding detection

commons-io-2.11.0-src/src/site/xdoc/upgradeto2_1.xml0100644 0000000 0000000 00000006411 13612062727 022515 0ustar00rootroot0000000 0000000 Upgrade from 2.0.1 to 2.1 Commons Documentation Team

These are the release notes and advice for upgrading Commons-IO from version 2.0.1 to version 2.1 Commons IO is a package of Java utility classes for java.io's hierarchy. Classes in this package are considered to be so standard and of such high reuse as to justify existence in java.io. Commons IO contains utility classes, stream implementations, file filters, file comparators and endian transformation classes. Compatibility with 2.0.1 and 1.4 -------------------------------- Binary compatible - Yes Source compatible - Yes Semantic compatible - Yes Check the bug fixes section for semantic bug fixes Commons IO 2.1 requires a minimum of JDK 1.5 (Commons IO 1.4 had a minimum of JDK 1.3) New features since 2.0.1 ------------------------ o Use standard Maven directory layout Issue: IO-285. Thanks to ggregory. o Add IOUtils API toString for URL and URI to get contents Issue: IO-284. Thanks to ggregory. o Add API FileUtils.copyFile(File input, OutputStream output) Issue: IO-282. Thanks to ggregory. o FileAlterationObserver has no getter for FileFilter Issue: IO-262. o Add FileUtils.getFile API with varargs parameter Issue: IO-261. o Add new APPEND parameter for writing string into files Issue: IO-182. o Add new read method "toByteArray" to handle InputStream with known size. Issue: IO-251. Thanks to Marco Albini. Fixed Bugs since 2.0.1 ---------------------- o Dubious use of mkdirs() return code Issue: IO-280. Thanks to sebb. o ReaderInputStream enters infinite loop when it encounters an unmappable character Issue: IO-277. o FileUtils.moveFile() Javadoc should specify FileExistsException thrown Issue: IO-264. o ClassLoaderObjectInputStream does not handle Proxy classes Issue: IO-260. o Tailer returning partial lines when reaching EOF before EOL Issue: IO-274. Thanks to Frank Grimes. o FileUtils.copyFile() throws IOException when copying large files to a shared directory (on Windows) Issue: IO-266. Thanks to Igor Smereka. o FileSystemUtils.freeSpaceKb throws exception for Windows volumes with no visible files. Improve coverage by also looking for hidden files. Issue: IO-263. Thanks to Gil Adam. Changes since 2.0.1 ------------------- o FileAlterationMonitor.stop(boolean allowIntervalToFinish) Issue: IO-259.

commons-io-2.11.0-src/src/site/xdoc/upgradeto2_2.xml0100644 0000000 0000000 00000010071 13612062727 022513 0ustar00rootroot0000000 0000000 Upgrade from 2.1 to 2.2 Commons Documentation Team

These are the release notes and advice for upgrading Commons-IO from version 2.1 to version 2.2 Commons IO is a package of Java utility classes like java.io. Classes in this package are considered to be so standard and of such high reuse as to justify existence in java.io. Commons IO contains utility classes, stream implementations, file filters, file comparators, endian transformation classes, and much more. ============================================================================== Commons IO Package Version 2.2 ============================================================================== Changes in this version include: New features: o IO-305: New copyLarge() method in IOUtils that takes additional offset, length arguments Thanks to Manoj Mokashi. o IO-287: Use terabyte (TB) , petabyte (PB) and exabyte (EB) in FileUtils.byteCountToDisplaySize(long size) Thanks to Ron Kuris, Gary Gregory. o IO-173: FileUtils.listFiles() doesn't return directories Thanks to Marcos Vinícius da Silva. o IO-297: CharSequenceInputStream to efficiently stream content of a CharSequence Thanks to Oleg Kalnichevski. o IO-304: The second constructor of Tailer class does not pass 'delay' to the third one Thanks to liangly. o IO-303: TeeOutputStream does not call branch.close() when main.close() throws an exception Thanks to fabian.barney. o IO-302: ArrayIndexOutOfBoundsException in BOMInputStream when reading a file without BOM multiple times Thanks to jsteuerwald, detinho. o IO-301: Add IOUtils.closeQuietly(Selector) necessary Thanks to kaykay.unique. o IO-292: IOUtils.closeQuietly() should take a ServerSocket as a parameter Thanks to sebb. o IO-290: Add read/readFully methods to IOUtils Thanks to sebb. o IO-288: Supply a ReversedLinesFileReader Thanks to Georg Henzler. o IO-291: Add new function FileUtils.directoryContains. Thanks to ggregory. o IO-275: FileUtils.contentEquals and IOUtils.contentEquals - Add option to ignore "line endings" Added contentEqualsIgnoreEOL methods to both classes Thanks to CJ Aspromgos. Fixed Bugs: o IO-300: FileUtils.moveDirectoryToDirectory removes source directory if destination is a subdirectory o IO-307: ReaderInputStream#read(byte[] b, int off, int len) should check for valid parameters o IO-306: ReaderInputStream#read(byte[] b, int off, int len) should always return 0 for length == 0 o IO-276: "FileUtils#deleteDirectoryOnExit(File)" does not work Thanks to nkami. o IO-273: BoundedInputStream.read() treats max differently from BoundedInputStream.read(byte[]...) Thanks to sebb. o IO-298: Various methods of class 'org.apache.commons.io.FileUtils' incorrectly suppress 'java.io.IOException' Thanks to Christian Schulte. Changes: o IO-296: ReaderInputStream optimization: more efficient reading of small chunks of data Thanks to Oleg Kalnichevski. Compatibility with 2.1 and 1.4: Binary compatible: Yes Source compatible: Yes Semantic compatible: Yes. Check the bug fixes section for semantic bug fixes Commons IO 2.2 requires a minimum of JDK 1.5. Commons IO 1.4 requires a minimum of JDK 1.3.

commons-io-2.11.0-src/src/site/xdoc/upgradeto2_3.xml0100644 0000000 0000000 00000004405 13612062727 022520 0ustar00rootroot0000000 0000000 Upgrade from 2.2 to 2.3 Commons Documentation Team

These are the release notes and advice for upgrading Commons-IO from version 2.2 to version 2.3 Commons IO is a package of Java utility classes like java.io. Classes in this package are considered to be so standard and of such high reuse as to justify existence in java.io. The Commons IO library contains utility classes, stream implementations, file filters, file comparators, endian transformation classes, and much more. ============================================================================== Apache Commons IO Version 2.3-SNAPSHOT ============================================================================== Changes in this version include: New features: o IO-322: Add and use class Charsets. Thanks to ggregory. o IO-321: ByteOrderMark UTF_32LE is incorrect. Thanks to ggregory. o IO-318: Add Charset sister APIs to method that take a String charset name. Thanks to ggregory. Compatibility with 2.2 and 1.4: Binary compatible: Yes. Source compatible: No, see the rare case in https://issues.apache.org/jira/browse/IO-318. Semantic compatible: No, see the rare case in https://issues.apache.org/jira/browse/IO-318. Commons IO 2.3 requires JDK 1.6 or later. Commons IO 2.2 requires JDK 1.5 or later. Commons IO 1.4 requires JDK 1.3 or later.

commons-io-2.11.0-src/src/site/xdoc/upgradeto2_4.xml0100644 0000000 0000000 00000006633 13612062727 022526 0ustar00rootroot0000000 0000000 Upgrade from 2.3 to 2.4 Commons Documentation Team

These are the release notes and advice for upgrading Commons-IO from version 2.3 to version 2.4 Commons IO is a package of Java utility classes like java.io. Classes in this package are considered to be so standard and of such high reuse as to justify existence in java.io. The Commons IO library contains utility classes, stream implementations, file filters, file comparators, endian transformation classes, and much more. ============================================================================== Apache Commons IO Version 2.4-SNAPSHOT ============================================================================== Changes in this version include: New features: o IO-269: Tailer locks file from deletion/rename on Windows. Thanks to sebb. o IO-333: Export OSGi packages at version 1.x in addition to 2.x. Thanks to fmeschbe. o IO-320: Add XmlStreamReader support for UTF-32. Thanks to ggregory. o IO-331: BOMInputStream wrongly detects UTF-32LE_BOM files as UTF-16LE_BOM files in method getBOM(). Thanks to ggregory. o IO-327: Add byteCountToDisplaySize(BigInteger). Thanks to ggregory. o IO-326: Add new FileUtils.sizeOf[Directory] APIs to return BigInteger. Thanks to ggregory. o IO-325: Add IOUtils.toByteArray methods to work with URL and URI. Thanks to raviprak. o IO-324: Add missing Charset sister APIs to method that take a String charset name. Thanks to raviprak. Fixed Bugs: o IO-279: Tailer erroneously considers file as new. Thanks to Sergio Bossa, Chris Baron. o IO-335: Tailer#readLines - incorrect CR handling. o IO-334: FileUtils.toURLs throws NPE for null parameter; document the behavior. o IO-332: Improve tailer's reading performance. Thanks to liangly. o IO-279: Improve Tailer performance with buffered reads (see IO-332). o IO-329: FileUtils.writeLines uses unbuffered IO. Thanks to tivv. o IO-319: FileUtils.sizeOfDirectory follows symbolic links. Thanks to raviprak. Compatibility with 2.3: Binary compatible: Yes. Source compatible: Yes. Semantic compatible: Yes. Compatibility with 2.2 and 1.4: Binary compatible: Yes. Source compatible: No, see the rare case in https://issues.apache.org/jira/browse/IO-318. Semantic compatible: No, see the rare case in https://issues.apache.org/jira/browse/IO-318. Commons IO 2.4 requires JDK 1.6 or later. Commons IO 2.3 requires JDK 1.6 or later. Commons IO 2.2 requires JDK 1.5 or later. Commons IO 1.4 requires JDK 1.3 or later.

commons-io-2.11.0-src/src/site/xdoc/upgradeto2_5.xml0100644 0000000 0000000 00000025471 13612062727 022530 0ustar00rootroot0000000 0000000 Upgrade from 2.4 to 2.5 Commons Documentation Team

These are the release notes and advice for upgrading Commons-IO from version 2.4 to version 2.5 Commons IO is a package of Java utility classes like java.io. Classes in this package are considered to be so standard and of such high reuse as to justify existence in java.io. The Apache Commons IO library contains utility classes, stream implementations, file filters, file comparators, endian transformation classes, and much more. ============================================================================== Apache Commons IO Version 2.5 ============================================================================== New features and bug fixes. Changes in this version include: New features: o IO-487: Add ValidatingObjectInputStream for controlled deserialization o IO-471: Support for additional encodings in ReversedLinesFileReader Thanks to Leandro Reis. o IO-425: Setter method for threshold on ThresholdingOutputStream Thanks to Craig Swank. o IO-406: Introduce new class AppendableOutputStream Thanks to Niall Pemberton. o IO-459: Add WindowsLineEndingInputStream and UnixLineEndingInputStream. Thanks to Kristian Rosenvold. o IO-457: Add a BoundedReader, a wrapper that can be used to constrain access to an underlying stream when used with mark/reset - to avoid overflowing the mark limit of the underlying buffer. Thanks to Kristian Rosenvold. o IO-426: Add API IOUtils.closeQuietly(Closeable...) o IO-410: Readfully() That Returns A Byte Array Thanks to Beluga Behr. o IO-395: Overload IOUtils buffer methods to accept buffer size Thanks to Beluga Behr. o IO-382: Chunked IO for large arrays. Added writeChunked(byte[], OutputStream) and writeChunked(char[] Writer) Added ChunkedOutputStream, ChunkedWriter o IO-233: Add Methods for Buffering Streams/Writers To IOUtils Added overloaded buffer() methods - see also IO-330 o IO-330: IOUtils#toBufferedOutputStream/toBufferedWriter to conditionally wrap the output Added overloaded buffer() methods - see also IO-233 o IO-381: Add FileUtils.copyInputStreamToFile API with option to leave the source open. See copyInputStreamToFile(final InputStream source, final File destination, boolean closeSource) o IO-379: CharSequenceInputStream - add tests for available() Fix code so it really does reflect a minimum available. o IO-346: Add ByteArrayOutputStream.toInputStream() o IO-341: A constant for holding the BOM character (U+FEFF) o IO-361: Add API FileUtils.forceMkdirsParent(). o IO-360: Add API Charsets.requiredCharsets(). o IO-359: Add IOUtils.skip and skipFully(ReadableByteChannel, long). Thanks to yukoba. o IO-358: Add IOUtils.read and readFully(ReadableByteChannel, ByteBuffer buffer). Thanks to yukoba. o IO-353: Add API IOUtils.copy(InputStream, OutputStream, int) Thanks to ggregory. o IO-349: Add API with array offset and length argument to FileUtils.writeByteArrayToFile. Thanks to scop. o IO-348: Missing information in IllegalArgumentException thrown by org.apache.commons.io.FileUtils#validateListFilesParameters. Thanks to plcstpierre. o IO-345: Supply a hook method allowing Tailer actively determining stop condition. Thanks to mkresse. o IO-437: Make IOUtils.EOF public and reuse it in various classes. Fixed Bugs: o IO-446: adds an endOfFileReached method to the TailerListener Thanks to Jeffrey Barrus. o IO-484: FilenameUtils should handle embedded null bytes Thanks to Philippe Arteau. o IO-481: Changed/Corrected algorithm for waitFor o IO-428: BOMInputStream.skip returns wrong count if stream contains no BOM Thanks to Stefan Gmeiner. o IO-488: FileUtils.waitFor(...) swallows thread interrupted status Thanks to Bj�rn Buchner. o IO-452: Support for symlinks with missing target. Added support for JDK7 symlink features when present Thanks to David Standish. o IO-453: Regression in FileUtils.readFileToString from 2.0.1 Thanks to Steven Christou. o IO-451: ant test fails - resources missing from test classpath Thanks to David Standish. o IO-435: Document that FileUtils.deleteDirectory, directoryContains and cleanDirectory may throw an IllegalArgumentException in case the passed directory does not exist or is not a directory. Thanks to Dominik Stadler. o IO-424: Javadoc fixes, mostly to appease 1.8.0 Thanks to Ville Skytt�. o IO-389: FileUtils.sizeOfDirectory can throw IllegalArgumentException Thanks to Austin Doupnik. o IO-390: FileUtils.sizeOfDirectoryAsBigInteger can overflow. Ensure that recursive calls all use BigInteger o IO-385: FileUtils.doCopyFile can potentially loop for ever Exit loop if no data to copy o IO-383: FileUtils.doCopyFile caches the file size; needs to be documented Added Javadoc; show file lengths in exception message o IO-380: FileUtils.copyInputStreamToFile should document it closes the input source Thanks to claudio_ch. o IO-279: Tailer erroneously considers file as new. Fix to use file.lastModified() rather than System.currentTimeMillis() o IO-356: CharSequenceInputStream#reset() behaves incorrectly in case when buffer size is not dividable by data size. Fix code so skip relates to the encoded bytes; reset now re-encodes the data up to the point of the mark o IO-368: ClassLoaderObjectInputStream does not handle primitive typed members o IO-314: Deprecate all methods that use the default encoding o IO-338: When a file is rotated, finish reading previous file prior to starting new one o IO-354: Commons IO Tailer does not respect UTF-8 Charset. o IO-323: What should happen in FileUtils.sizeOf[Directory] when an overflow takes place? Added Javadoc. o IO-372: FileUtils.moveDirectory can produce misleading error message on failiure o IO-362: IOUtils.contentEquals* methods returns false if input1 == input2, should return true. Thanks to mmadson, ggregory. o IO-357: [Tailer] InterruptedException while the thread is sleeping is silently ignored Thanks to mortenh. o IO-352: Spelling fixes. Thanks to scop. o IO-436: Improper Javadoc comment for FilenameUtils.indexOfExtension. Thanks to christoph.schneegans. Changes: o IO-433: Converted all testcases to JUnit 4 o IO-466: Added testcase to show this was fixed with IO-423 o IO-479: Correct exception message in FileUtils.getFile(File, String...) Thanks to Zhouce Chen. o IO-465: Update to JUnit 4.12 Thanks to based2. o IO-462: IOExceptionWithCause no longer needed o IO-422: Deprecate Charsets Charset constants in favor of Java 7's java.nio.charset.StandardCharsets o IO-239: Convert IOCase to a Java 1.5+ Enumeration [N.B. this is binary compatible] o IO-328: getPrefixLength returns null if filename has leading slashes Javadoc: add examples to show correct behavior; add unit tests o IO-299: FileUtils.listFilesAndDirs includes original dir in results even when it doesn't match filter Javadoc: clarify that original dir is included in the results o IO-375: FilenameUtils.splitOnTokens(String text) check for '**' could be simplified o IO-374: WildcardFileFilter ctors should not use null to mean IOCase.SENSITIVE when delegating to other ctors Compatibility with 2.4: Binary compatible: Yes. Source compatible: Yes. Semantic compatible: Yes. Compatibility with 2.2 and 1.4: Binary compatible: Yes. Source compatible: No, see the rare case in https://issues.apache.org/jira/browse/IO-318. Semantic compatible: No, see the rare case in https://issues.apache.org/jira/browse/IO-318. Commons IO 2.5 requires JDK 1.6 or later. Commons IO 2.4 requires JDK 1.6 or later. Commons IO 2.3 requires JDK 1.6 or later. Commons IO 2.2 requires JDK 1.5 or later. Commons IO 1.4 requires JDK 1.3 or later.

commons-io-2.11.0-src/src/site/xdoc/upgradeto2_6.xml0100644 0000000 0000000 00000016646 13612062727 022535 0ustar00rootroot0000000 0000000 Upgrade from 2.5 to 2.6 Commons Documentation Team

These are the release notes and advice for upgrading Apache Commons IO from version 2.5 to version 2.6 Apache Commons IO is a package of Java utility classes like java.io. Classes in this package are considered to be so standard and of such high reuse as to justify existence in java.io. The Apache Commons IO library contains utility classes, stream implementations, file filters, file comparators, endian transformation classes, and much more. Apache Commons IO 2.6 requires at least Java 7 to build and run. DEPRECATIONS ============ All closeQuietly overloads in org.apache.commons.io.IOUtils have been deprecated. Use the try-with-resources statement or handle suppressed exceptions manually. The class org.apache.commons.io.FileSystemUtils has been deprecated. Use equivalent methods in java.nio.file.FileStore instead, e.g. Files.getFileStore(Paths.get("/home")).getUsableSpace() or iterate over FileSystems.getDefault().getFileStores(). COMPATIBILITY WITH JAVA 9 ================== The MANIFEST.MF now contains an additional entry: Automatic-Module-Name: org.apache.commons.io This should make it possible to use Commons IO 2.6 as a module in the Java 9 module system. For more information see the corresponding issue: https://issues.apache.org/jira/browse/IO-551 Building Commons IO 2.6 should work out of the box with the latest Java 9 release. Please report any Java 9 related issues at: https://issues.apache.org/jira/browse/IO NEW FEATURES ============ o IO-551: Add Automatic-Module-Name MANIFEST entry for Java 9 compatibility. o IO-367: Add convenience methods for copyToDirectory. Thanks to James Sawle. o IO-493: Add infinite circular input stream. Thanks to Piotr Turski. o IO-507: Add a ByteOrderUtils class. o IO-518: Add ObservableInputStream. o IO-519: Add MessageDigestCalculatingInputStream. o IO-513: Add convenience methods for reading class path resources. Thanks to Behrang Saeedzadeh. FIXED BUGS ========== o IO-550: Documentation issue, fix 404 Javadoc issues in the description page. Thanks to Jimi Adrian. o IO-442: Javadoc contradictory for FileFilterUtils.ageFileFilter(cutoff) and the filter it constructs: AgeFileFilter(cutoff). Thanks to Simon Robinson. o IO-534: FileUtilTestCase.testForceDeleteDir() should not delete testDirectory parent. o IO-528: Fix Tailer.run race condition runaway logging. Thanks to Dave Moten. o IO-483: getPrefixLength return -1 if unix file contains colon. Thanks to Marko Vasic. o IO-520: FileUtilsTestCase#testContentEqualsIgnoreEOL fails on Windows. o IO-516: .gitattributes not correctly applied. Thanks to Jason Pyeron. o IO-515: Allow Specifying Initial Buffer Size of DeferredFileOutputStream. Thanks to Brett Lounsbury, Gary Gregory. o IO-512: ThresholdingOutputStream.thresholdReached() results in FileNotFoundException. Thanks to Ralf Hauser. o IO-511: After a few unit tests, a few newly created directories not cleaned completely. Thanks to Ahmet Celik. o IO-502: Exceptions are suppressed incorrectly when copying files. Thanks to Christian Schulte. o IO-503: Update platform requirement to Java 7. o IO-537: BOMInputStream shouldn't sort array of BOMs in-place. Thanks to Borys Zibrov. CHANGES ======= o IO-542: FileUtils#readFileToByteArray: optimize reading of files with known size. Thanks to Ilmars Poikans. o IO-547: Throw a IllegalArgumentException instead of NullPointerException in FileSystemUtils.freeSpaceWindows(). Thanks to Nikhil Shinde, Michael Ernst, Gary Greory. o IO-506: Deprecate methods FileSystemUtils.freeSpaceKb(). Thanks to Christian Schulte. o IO-505: Make LineIterator implement Closeable to support try-with-resources statements. Thanks to Christian Schulte. o IO-504: Deprecated of all IOUtils.closeQuietly() methods and use try-with-resources internally. Thanks to Christian Schulte. REMOVED ======= o IO-514: Remove org.apache.commons.io.Java7Support. COMPATIBILITY WITH OLDER VERSIONS ================================= Compatibility with 2.5: Binary compatible: Yes. Source compatible: Yes. Semantic compatible: Yes. Compatibility with 2.6 and 1.4: Binary compatible: Yes. Source compatible: No, see the rare case in https://issues.apache.org/jira/browse/IO-318. Semantic compatible: No, see the rare case in https://issues.apache.org/jira/browse/IO-318. Commons IO 2.6 requires Java 7 or later. Commons IO 2.5 requires Java 6 or later. Commons IO 2.4 requires Java 6 or later. Commons IO 2.3 requires Java 6 or later. Commons IO 2.2 requires Java 5 or later. Commons IO 1.4 requires Java 1.3 or later.

commons-io-2.11.0-src/src/test/java/org/apache/commons/io/ByteOrderMarkTestCase.java0100644 0000000 0000000 00000014023 13612062727 030577 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.fail; import java.nio.charset.Charset; import org.junit.jupiter.api.Test; /** * Test for {@link ByteOrderMark}. * */ public class ByteOrderMarkTestCase { private static final ByteOrderMark TEST_BOM_1 = new ByteOrderMark("test1", 1); private static final ByteOrderMark TEST_BOM_2 = new ByteOrderMark("test2", 1, 2); private static final ByteOrderMark TEST_BOM_3 = new ByteOrderMark("test3", 1, 2, 3); /** Test {@link ByteOrderMark#getCharsetName()} */ @Test public void charsetName() { assertEquals("test1", TEST_BOM_1.getCharsetName(), "test1 name"); assertEquals("test2", TEST_BOM_2.getCharsetName(), "test2 name"); assertEquals("test3", TEST_BOM_3.getCharsetName(), "test3 name"); } /** Tests that {@link ByteOrderMark#getCharsetName()} can be loaded as a {@link java.nio.charset.Charset} as advertised. */ @Test public void constantCharsetNames() { assertNotNull(Charset.forName(ByteOrderMark.UTF_8.getCharsetName())); assertNotNull(Charset.forName(ByteOrderMark.UTF_16BE.getCharsetName())); assertNotNull(Charset.forName(ByteOrderMark.UTF_16LE.getCharsetName())); assertNotNull(Charset.forName(ByteOrderMark.UTF_32BE.getCharsetName())); assertNotNull(Charset.forName(ByteOrderMark.UTF_32LE.getCharsetName())); } /** Test {@link ByteOrderMark#length()} */ @Test public void testLength() { assertEquals(1, TEST_BOM_1.length(), "test1 length"); assertEquals(2, TEST_BOM_2.length(), "test2 length"); assertEquals(3, TEST_BOM_3.length(), "test3 length"); } /** Test {@link ByteOrderMark#get(int)} */ @Test public void get() { assertEquals(1, TEST_BOM_1.get(0), "test1 get(0)"); assertEquals(1, TEST_BOM_2.get(0), "test2 get(0)"); assertEquals(2, TEST_BOM_2.get(1), "test2 get(1)"); assertEquals(1, TEST_BOM_3.get(0), "test3 get(0)"); assertEquals(2, TEST_BOM_3.get(1), "test3 get(1)"); assertEquals(3, TEST_BOM_3.get(2), "test3 get(2)"); } /** Test {@link ByteOrderMark#getBytes()} */ @Test public void getBytes() { assertArrayEquals(TEST_BOM_1.getBytes(), new byte[]{(byte) 1}, "test1 bytes"); TEST_BOM_1.getBytes()[0] = 2; assertArrayEquals(TEST_BOM_1.getBytes(), new byte[]{(byte) 1}, "test1 bytes"); assertArrayEquals(TEST_BOM_2.getBytes(), new byte[]{(byte) 1, (byte) 2}, "test1 bytes"); assertArrayEquals(TEST_BOM_3.getBytes(), new byte[]{(byte) 1, (byte) 2, (byte) 3}, "test1 bytes"); } /** Test {@link ByteOrderMark#equals(Object)} */ @SuppressWarnings("EqualsWithItself") @Test public void testEquals() { assertEquals(TEST_BOM_1, TEST_BOM_1, "test1 equals"); assertEquals(TEST_BOM_2, TEST_BOM_2, "test2 equals"); assertEquals(TEST_BOM_3, TEST_BOM_3, "test3 equals"); assertNotEquals(TEST_BOM_1, new Object(), "Object not equal"); assertNotEquals(TEST_BOM_1, new ByteOrderMark("1a", 2), "test1-1 not equal"); assertNotEquals(TEST_BOM_1, new ByteOrderMark("1b", 1, 2), "test1-2 not test2"); assertNotEquals(TEST_BOM_2, new ByteOrderMark("2", 1, 1), "test2 not equal"); assertNotEquals(TEST_BOM_3, new ByteOrderMark("3", 1, 2, 4), "test3 not equal"); } /** Test {@link ByteOrderMark#hashCode()} */ @Test public void testHashCode() { final int bomClassHash = ByteOrderMark.class.hashCode(); assertEquals(bomClassHash + 1, TEST_BOM_1.hashCode(), "hash test1 "); assertEquals(bomClassHash + 3, TEST_BOM_2.hashCode(), "hash test2 "); assertEquals(bomClassHash + 6, TEST_BOM_3.hashCode(), "hash test3 "); } /** Test Errors */ @Test public void errors() { try { new ByteOrderMark(null, 1,2,3); fail("null charset name, expected IllegalArgumentException"); } catch (final IllegalArgumentException e) { // expected } try { new ByteOrderMark("", 1,2,3); fail("no charset name, expected IllegalArgumentException"); } catch (final IllegalArgumentException e) { // expected } try { new ByteOrderMark("a", (int[])null); fail("null bytes, expected IllegalArgumentException"); } catch (final IllegalArgumentException e) { // expected } try { new ByteOrderMark("b"); fail("empty bytes, expected IllegalArgumentException"); } catch (final IllegalArgumentException e) { // expected } } /** Test {@link ByteOrderMark#toString()} */ @Test public void testToString() { assertEquals("ByteOrderMark[test1: 0x1]", TEST_BOM_1.toString(), "test1 "); assertEquals("ByteOrderMark[test2: 0x1,0x2]", TEST_BOM_2.toString(), "test2 "); assertEquals("ByteOrderMark[test3: 0x1,0x2,0x3]", TEST_BOM_3.toString(), "test3 "); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/ByteOrderParserTest.java0100644 0000000 0000000 00000003057 13612062727 030352 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import java.nio.ByteOrder; import org.junit.jupiter.api.Test; public class ByteOrderParserTest { private ByteOrder parseByteOrder(final String value) { return ByteOrderParser.parseByteOrder(value); } @Test public void testParseBig() { assertEquals(ByteOrder.BIG_ENDIAN, parseByteOrder("BIG_ENDIAN")); } @Test public void testParseLittle() { assertEquals(ByteOrder.LITTLE_ENDIAN, parseByteOrder("LITTLE_ENDIAN")); } @Test public void testThrowsException() { assertThrows(IllegalArgumentException.class, () -> parseByteOrder("some value")); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/CharsetsTestCase.java0100644 0000000 0000000 00000005567 13612062727 027656 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import static org.junit.jupiter.api.Assertions.assertEquals; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.SortedMap; import org.junit.jupiter.api.Test; /** * Tests {@link Charsets}. * */ @SuppressWarnings("deprecation") // testing deprecated code public class CharsetsTestCase { @Test public void testRequiredCharsets() { final SortedMap requiredCharsets = Charsets.requiredCharsets(); // test for what we expect to be there as of Java 6 // Make sure the object at the given key is the right one assertEquals(requiredCharsets.get("US-ASCII").name(), "US-ASCII"); assertEquals(requiredCharsets.get("ISO-8859-1").name(), "ISO-8859-1"); assertEquals(requiredCharsets.get("UTF-8").name(), "UTF-8"); assertEquals(requiredCharsets.get("UTF-16").name(), "UTF-16"); assertEquals(requiredCharsets.get("UTF-16BE").name(), "UTF-16BE"); assertEquals(requiredCharsets.get("UTF-16LE").name(), "UTF-16LE"); } @Test public void testIso8859_1() { assertEquals("ISO-8859-1", Charsets.ISO_8859_1.name()); } @Test public void testToCharset() { assertEquals(Charset.defaultCharset(), Charsets.toCharset((String) null)); assertEquals(Charset.defaultCharset(), Charsets.toCharset((Charset) null)); assertEquals(Charset.defaultCharset(), Charsets.toCharset(Charset.defaultCharset())); assertEquals(StandardCharsets.UTF_8, Charsets.toCharset(StandardCharsets.UTF_8)); } @Test public void testUsAscii() { assertEquals("US-ASCII", Charsets.US_ASCII.name()); } @Test public void testUtf16() { assertEquals("UTF-16", Charsets.UTF_16.name()); } @Test public void testUtf16Be() { assertEquals("UTF-16BE", Charsets.UTF_16BE.name()); } @Test public void testUtf16Le() { assertEquals("UTF-16LE", Charsets.UTF_16LE.name()); } @Test public void testUtf8() { assertEquals("UTF-8", Charsets.UTF_8.name()); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/CopyUtilsTest.java0100644 0000000 0000000 00000021404 13612062727 027225 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.io.OutputStream; import java.io.Reader; import java.io.StringWriter; import java.io.Writer; import java.nio.charset.StandardCharsets; import org.apache.commons.io.output.ByteArrayOutputStream; import org.apache.commons.io.test.TestUtils; import org.apache.commons.io.test.ThrowOnCloseInputStream; import org.apache.commons.io.test.ThrowOnFlushAndCloseOutputStream; import org.junit.jupiter.api.Test; @SuppressWarnings("deprecation") // these are test cases for the deprecated CopyUtils /** * JUnit tests for CopyUtils. * * @see CopyUtils */ public class CopyUtilsTest { /* * NOTE this is not particularly beautiful code. A better way to check for * flush and close status would be to implement "trojan horse" wrapper * implementations of the various stream classes, which set a flag when * relevant methods are called. (JT) */ private static final int FILE_SIZE = 1024 * 4 + 1; private final byte[] inData = TestUtils.generateTestData(FILE_SIZE); // ---------------------------------------------------------------- // Tests // ---------------------------------------------------------------- @Test public void testCtor() { new CopyUtils(); // Nothing to assert, the constructor is public and does not blow up. } @Test public void copy_byteArrayToOutputStream() throws Exception { final ByteArrayOutputStream baout = new ByteArrayOutputStream(); final OutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, false, true); CopyUtils.copy(inData, out); assertEquals(inData.length, baout.size(), "Sizes differ"); assertArrayEquals(inData, baout.toByteArray(), "Content differs"); } @Test public void copy_byteArrayToWriter() throws Exception { final ByteArrayOutputStream baout = new ByteArrayOutputStream(); final OutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, false, true); final Writer writer = new java.io.OutputStreamWriter(out, StandardCharsets.US_ASCII); CopyUtils.copy(inData, writer); writer.flush(); assertEquals(inData.length, baout.size(), "Sizes differ"); assertArrayEquals(inData, baout.toByteArray(), "Content differs"); } @Test public void testCopy_byteArrayToWriterWithEncoding() throws Exception { final String inDataStr = "data"; final String charsetName = "UTF-8"; final StringWriter writer = new StringWriter(); CopyUtils.copy(inDataStr.getBytes(charsetName), writer, charsetName); assertEquals(inDataStr, writer.toString()); } @SuppressWarnings("resource") // 'in' is deliberately not closed @Test public void testCopy_inputStreamToOutputStream() throws Exception { InputStream in = new ByteArrayInputStream(inData); in = new ThrowOnCloseInputStream(in); final ByteArrayOutputStream baout = new ByteArrayOutputStream(); final OutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, false, true); final int count = CopyUtils.copy(in, out); assertEquals(0, in.available(), "Not all bytes were read"); assertEquals(inData.length, baout.size(), "Sizes differ"); assertArrayEquals(inData, baout.toByteArray(), "Content differs"); assertEquals(inData.length, count); } @SuppressWarnings("resource") // 'in' is deliberately not closed @Test public void copy_inputStreamToWriter() throws Exception { InputStream in = new ByteArrayInputStream(inData); in = new ThrowOnCloseInputStream(in); final ByteArrayOutputStream baout = new ByteArrayOutputStream(); final OutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, false, true); final Writer writer = new java.io.OutputStreamWriter(out, StandardCharsets.US_ASCII); CopyUtils.copy(in, writer); writer.flush(); assertEquals(0, in.available(), "Not all bytes were read"); assertEquals(inData.length, baout.size(), "Sizes differ"); assertArrayEquals(inData, baout.toByteArray(), "Content differs"); } @Test public void copy_inputStreamToWriterWithEncoding() throws Exception { final String inDataStr = "data"; final String charsetName = "UTF-8"; final StringWriter writer = new StringWriter(); CopyUtils.copy(new ByteArrayInputStream(inDataStr.getBytes(charsetName)), writer, charsetName); assertEquals(inDataStr, writer.toString()); } @SuppressWarnings("resource") // 'in' is deliberately not closed @Test public void testCopy_readerToOutputStream() throws Exception { InputStream in = new ByteArrayInputStream(inData); in = new ThrowOnCloseInputStream(in); final Reader reader = new java.io.InputStreamReader(in, StandardCharsets.US_ASCII); final ByteArrayOutputStream baout = new ByteArrayOutputStream(); final OutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, false, true); CopyUtils.copy(reader, out); //Note: this method *does* flush. It is equivalent to: // OutputStreamWriter _out = new OutputStreamWriter(fout); // IOUtils.copy( fin, _out, 4096 ); // copy( Reader, Writer, int ); // _out.flush(); // out = fout; // Note: rely on the method to flush assertEquals(inData.length, baout.size(), "Sizes differ"); assertArrayEquals(inData, baout.toByteArray(), "Content differs"); } @SuppressWarnings("resource") // 'in' is deliberately not closed @Test public void copy_readerToWriter() throws Exception { InputStream in = new ByteArrayInputStream(inData); in = new ThrowOnCloseInputStream(in); final Reader reader = new java.io.InputStreamReader(in, StandardCharsets.US_ASCII); final ByteArrayOutputStream baout = new ByteArrayOutputStream(); final OutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, false, true); final Writer writer = new java.io.OutputStreamWriter(out, StandardCharsets.US_ASCII); final int count = CopyUtils.copy(reader, writer); writer.flush(); assertEquals(inData.length, count, "The number of characters returned by copy is wrong"); assertEquals(inData.length, baout.size(), "Sizes differ"); assertArrayEquals(inData, baout.toByteArray(), "Content differs"); } @Test public void copy_stringToOutputStream() throws Exception { final String str = new String(inData, StandardCharsets.US_ASCII); final ByteArrayOutputStream baout = new ByteArrayOutputStream(); final OutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, false, true); CopyUtils.copy(str, out); //Note: this method *does* flush. It is equivalent to: // OutputStreamWriter _out = new OutputStreamWriter(fout); // IOUtils.copy( str, _out, 4096 ); // copy( Reader, Writer, int ); // _out.flush(); // out = fout; // note: we don't flush here; this IOUtils method does it for us assertEquals(inData.length, baout.size(), "Sizes differ"); assertArrayEquals(inData, baout.toByteArray(), "Content differs"); } @Test public void copy_stringToWriter() throws Exception { final String str = new String(inData, StandardCharsets.US_ASCII); final ByteArrayOutputStream baout = new ByteArrayOutputStream(); final OutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, false, true); final Writer writer = new java.io.OutputStreamWriter(out, StandardCharsets.US_ASCII); CopyUtils.copy(str, writer); writer.flush(); assertEquals(inData.length, baout.size(), "Sizes differ"); assertArrayEquals(inData, baout.toByteArray(), "Content differs"); } } // CopyUtilsTest commons-io-2.11.0-src/src/test/java/org/apache/commons/io/DemuxTestCase.java0100644 0000000 0000000 00000016044 13612062727 027154 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.io.OutputStream; import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Random; import org.apache.commons.io.input.DemuxInputStream; import org.apache.commons.io.output.ByteArrayOutputStream; import org.apache.commons.io.output.DemuxOutputStream; import org.apache.commons.io.test.TestUtils; import org.junit.jupiter.api.Test; /** * Basic unit tests for the multiplexing streams. */ public class DemuxTestCase { private static final String T1 = "Thread1"; private static final String T2 = "Thread2"; private static final String T3 = "Thread3"; private static final String T4 = "Thread4"; private static final String DATA1 = "Data for thread1"; private static final String DATA2 = "Data for thread2"; private static final String DATA3 = "Data for thread3"; private static final String DATA4 = "Data for thread4"; private static final Random c_random = new Random(); private final HashMap outputMap = new HashMap<>(); private final HashMap threadMap = new HashMap<>(); private String getOutput(final String threadName) { final ByteArrayOutputStream output = outputMap.get(threadName); assertNotNull(output, "getOutput()"); return output.toString(StandardCharsets.UTF_8); } private String getInput(final String threadName) { final ReaderThread thread = (ReaderThread) threadMap.get(threadName); assertNotNull(thread, "getInput()"); return thread.getData(); } private void doStart() { for (final String name : threadMap.keySet()) { final Thread thread = threadMap.get(name); thread.start(); } } private void doJoin() throws Exception { for (final String name : threadMap.keySet()) { final Thread thread = threadMap.get(name); thread.join(); } } private void startWriter(final String name, final String data, final DemuxOutputStream demux) { final ByteArrayOutputStream output = new ByteArrayOutputStream(); outputMap.put(name, output); final WriterThread thread = new WriterThread(name, data, output, demux); threadMap.put(name, thread); } private void startReader(final String name, final String data, final DemuxInputStream demux) { final ByteArrayInputStream input = new ByteArrayInputStream(data.getBytes()); final ReaderThread thread = new ReaderThread(name, input, demux); threadMap.put(name, thread); } @Test public void testOutputStream() throws Exception { final DemuxOutputStream output = new DemuxOutputStream(); startWriter(T1, DATA1, output); startWriter(T2, DATA2, output); startWriter(T3, DATA3, output); startWriter(T4, DATA4, output); doStart(); doJoin(); assertEquals(DATA1, getOutput(T1), "Data1"); assertEquals(DATA2, getOutput(T2), "Data2"); assertEquals(DATA3, getOutput(T3), "Data3"); assertEquals(DATA4, getOutput(T4), "Data4"); } @Test public void testInputStream() throws Exception { final DemuxInputStream input = new DemuxInputStream(); startReader(T1, DATA1, input); startReader(T2, DATA2, input); startReader(T3, DATA3, input); startReader(T4, DATA4, input); doStart(); doJoin(); assertEquals(DATA1, getInput(T1), "Data1"); assertEquals(DATA2, getInput(T2), "Data2"); assertEquals(DATA3, getInput(T3), "Data3"); assertEquals(DATA4, getInput(T4), "Data4"); } private static class ReaderThread extends Thread { private final StringBuffer stringBuffer = new StringBuffer(); private final InputStream inputStream; private final DemuxInputStream demuxInputStream; ReaderThread(final String name, final InputStream input, final DemuxInputStream demux) { super(name); inputStream = input; demuxInputStream = demux; } public String getData() { return stringBuffer.toString(); } @Override public void run() { demuxInputStream.bindStream(inputStream); try { int ch = demuxInputStream.read(); while (-1 != ch) { //System.out.println( "Reading: " + (char)ch ); stringBuffer.append((char) ch); final int sleepTime = Math.abs(c_random.nextInt() % 10); TestUtils.sleep(sleepTime); ch = demuxInputStream.read(); } } catch (final Exception e) { e.printStackTrace(); } } } private static class WriterThread extends Thread { private final byte[] byteArray; private final OutputStream outputStream; private final DemuxOutputStream demuxOutputStream; WriterThread(final String name, final String data, final OutputStream output, final DemuxOutputStream demux) { super(name); outputStream = output; demuxOutputStream = demux; byteArray = data.getBytes(); } @Override public void run() { demuxOutputStream.bindStream(outputStream); for (final byte element : byteArray) { try { //System.out.println( "Writing: " + (char)byteArray[ i ] ); demuxOutputStream.write(element); final int sleepTime = Math.abs(c_random.nextInt() % 10); TestUtils.sleep(sleepTime); } catch (final Exception e) { e.printStackTrace(); } } } } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/DirectoryWalkerTestCase.java0100644 0000000 0000000 00000052156 13612062727 031210 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import java.io.File; import java.io.FileFilter; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.apache.commons.io.filefilter.FileFilterUtils; import org.apache.commons.io.filefilter.IOFileFilter; import org.apache.commons.io.filefilter.NameFileFilter; import org.junit.jupiter.api.Test; /** * This is used to test DirectoryWalker for correctness. * * @see DirectoryWalker * */ public class DirectoryWalkerTestCase { // Directories private static final File current = new File("."); private static final File javaDir = new File("src/main/java"); private static final File orgDir = new File(javaDir, "org"); private static final File apacheDir = new File(orgDir, "apache"); private static final File commonsDir = new File(apacheDir, "commons"); private static final File ioDir = new File(commonsDir, "io"); private static final File outputDir = new File(ioDir, "output"); private static final File[] dirs = {orgDir, apacheDir, commonsDir, ioDir, outputDir}; // Files private static final File filenameUtils = new File(ioDir, "FilenameUtils.java"); private static final File ioUtils = new File(ioDir, "IOUtils.java"); private static final File proxyWriter = new File(outputDir, "ProxyWriter.java"); private static final File nullStream = new File(outputDir, "NullOutputStream.java"); private static final File[] ioFiles = {filenameUtils, ioUtils}; private static final File[] outputFiles = {proxyWriter, nullStream}; // Filters private static final IOFileFilter dirsFilter = createNameFilter(dirs); private static final IOFileFilter iofilesFilter = createNameFilter(ioFiles); private static final IOFileFilter outputFilesFilter = createNameFilter(outputFiles); private static final IOFileFilter ioDirAndFilesFilter = dirsFilter.or(iofilesFilter); private static final IOFileFilter dirsAndFilesFilter = ioDirAndFilesFilter.or(outputFilesFilter); // Filter to exclude SVN files private static final IOFileFilter NOT_SVN = FileFilterUtils.makeSVNAware(null); /** * Test Filtering */ @Test public void testFilter() { final List results = new TestFileFinder(dirsAndFilesFilter, -1).find(javaDir); assertEquals(1 + dirs.length + ioFiles.length + outputFiles.length, results.size(), "Result Size"); assertTrue(results.contains(javaDir), "Start Dir"); checkContainsFiles("Dir", dirs, results); checkContainsFiles("IO File", ioFiles, results); checkContainsFiles("Output File", outputFiles, results); } /** * Test Filtering and limit to depth 0 */ @Test public void testFilterAndLimitA() { final List results = new TestFileFinder(NOT_SVN, 0).find(javaDir); assertEquals(1, results.size(), "[A] Result Size"); assertTrue(results.contains(javaDir), "[A] Start Dir"); } /** * Test Filtering and limit to depth 1 */ @Test public void testFilterAndLimitB() { final List results = new TestFileFinder(NOT_SVN, 1).find(javaDir); assertEquals(2, results.size(), "[B] Result Size"); assertTrue(results.contains(javaDir), "[B] Start Dir"); assertTrue(results.contains(orgDir), "[B] Org Dir"); } /** * Test Filtering and limit to depth 3 */ @Test public void testFilterAndLimitC() { final List results = new TestFileFinder(NOT_SVN, 3).find(javaDir); assertEquals(4, results.size(), "[C] Result Size"); assertTrue(results.contains(javaDir), "[C] Start Dir"); assertTrue(results.contains(orgDir), "[C] Org Dir"); assertTrue(results.contains(apacheDir), "[C] Apache Dir"); assertTrue(results.contains(commonsDir), "[C] Commons Dir"); } /** * Test Filtering and limit to depth 5 */ @Test public void testFilterAndLimitD() { final List results = new TestFileFinder(dirsAndFilesFilter, 5).find(javaDir); assertEquals(1 + dirs.length + ioFiles.length, results.size(), "[D] Result Size"); assertTrue(results.contains(javaDir), "[D] Start Dir"); checkContainsFiles("[D] Dir", dirs, results); checkContainsFiles("[D] File", ioFiles, results); } /** * Test separate dir and file filters */ @Test public void testFilterDirAndFile1() { final List results = new TestFileFinder(dirsFilter, iofilesFilter, -1).find(javaDir); assertEquals(1 + dirs.length + ioFiles.length, results.size(), "[DirAndFile1] Result Size"); assertTrue(results.contains(javaDir), "[DirAndFile1] Start Dir"); checkContainsFiles("[DirAndFile1] Dir", dirs, results); checkContainsFiles("[DirAndFile1] File", ioFiles, results); } /** * Test separate dir and file filters */ @Test public void testFilterDirAndFile2() { final List results = new TestFileFinder(null, null, -1).find(javaDir); assertTrue(results.size() > 1 + dirs.length + ioFiles.length, "[DirAndFile2] Result Size"); assertTrue(results.contains(javaDir), "[DirAndFile2] Start Dir"); checkContainsFiles("[DirAndFile2] Dir", dirs, results); checkContainsFiles("[DirAndFile2] File", ioFiles, results); } /** * Test separate dir and file filters */ @Test public void testFilterDirAndFile3() { final List results = new TestFileFinder(dirsFilter, null, -1).find(javaDir); final List resultDirs = directoriesOnly(results); assertEquals(1 + dirs.length, resultDirs.size(), "[DirAndFile3] Result Size"); assertTrue(results.contains(javaDir), "[DirAndFile3] Start Dir"); checkContainsFiles("[DirAndFile3] Dir", dirs, resultDirs); } /** * Test separate dir and file filters */ @Test public void testFilterDirAndFile4() { final List results = new TestFileFinder(null, iofilesFilter, -1).find(javaDir); final List resultFiles = filesOnly(results); assertEquals(ioFiles.length, resultFiles.size(), "[DirAndFile4] Result Size"); assertTrue(results.contains(javaDir), "[DirAndFile4] Start Dir"); checkContainsFiles("[DirAndFile4] File", ioFiles, resultFiles); } /** * Test Limiting to current directory */ @Test public void testLimitToCurrent() { final List results = new TestFileFinder(null, 0).find(current); assertEquals(1, results.size(), "Result Size"); assertTrue(results.contains(new File(".")), "Current Dir"); } /** * test an invalid start directory */ @Test public void testMissingStartDirectory() { // TODO is this what we want with invalid directory? final File invalidDir = new File("invalid-dir"); final List results = new TestFileFinder(null, -1).find(invalidDir); assertEquals(1, results.size(), "Result Size"); assertTrue(results.contains(invalidDir), "Current Dir"); try { new TestFileFinder(null, -1).find(null); fail("Null start directory didn't throw Exception"); } catch (final NullPointerException ignore) { // expected result } } /** * test an invalid start directory */ @Test public void testHandleStartDirectoryFalse() { final List results = new TestFalseFileFinder(null, -1).find(current); assertEquals(0, results.size(), "Result Size"); } // ------------ Convenience Test Methods ------------------------------------ /** * Check the files in the array are in the results list. */ private void checkContainsFiles(final String prefix, final File[] files, final Collection results) { for (int i = 0; i < files.length; i++) { assertTrue(results.contains(files[i]), prefix + "["+i+"] " + files[i]); } } private void checkContainsString(final String prefix, final File[] files, final Collection results) { for (int i = 0; i < files.length; i++) { assertTrue(results.contains(files[i].toString()), prefix + "["+i+"] " + files[i]); } } /** * Extract the directories. */ private List directoriesOnly(final Collection results) { final List list = new ArrayList<>(results.size()); for (final File file : results) { if (file.isDirectory()) { list.add(file); } } return list; } /** * Extract the files. */ private List filesOnly(final Collection results) { final List list = new ArrayList<>(results.size()); for (final File file : results) { if (file.isFile()) { list.add(file); } } return list; } /** * Create a name filter containing the names of the files * in the array. */ private static IOFileFilter createNameFilter(final File[] files) { final String[] names = new String[files.length]; for (int i = 0; i < files.length; i++) { names[i] = files[i].getName(); } return new NameFileFilter(names); } /** * Test Cancel */ @Test public void testCancel() { String cancelName = null; // Cancel on a file try { cancelName = "DirectoryWalker.java"; new TestCancelWalker(cancelName, false).find(javaDir); fail("CancelException not thrown for '" + cancelName + "'"); } catch (final DirectoryWalker.CancelException cancel) { assertEquals(cancelName, cancel.getFile().getName(), "File: " + cancelName); assertEquals(5, cancel.getDepth(), "Depth: " + cancelName); } catch(final IOException ex) { fail("IOException: " + cancelName + " " + ex); } // Cancel on a directory try { cancelName = "commons"; new TestCancelWalker(cancelName, false).find(javaDir); fail("CancelException not thrown for '" + cancelName + "'"); } catch (final DirectoryWalker.CancelException cancel) { assertEquals(cancelName, cancel.getFile().getName(), "File: " + cancelName); assertEquals(3, cancel.getDepth(), "Depth: " + cancelName); } catch(final IOException ex) { fail("IOException: " + cancelName + " " + ex); } // Suppress CancelException (use same file name as preceding test) try { final List results = new TestCancelWalker(cancelName, true).find(javaDir); final File lastFile = results.get(results.size() - 1); assertEquals(cancelName, lastFile.getName(), "Suppress: " + cancelName); } catch(final IOException ex) { fail("Suppress threw " + ex); } } /** * Test Cancel */ @Test public void testMultiThreadCancel() { String cancelName = "DirectoryWalker.java"; TestMultiThreadCancelWalker walker = new TestMultiThreadCancelWalker(cancelName, false); // Cancel on a file try { walker.find(javaDir); fail("CancelException not thrown for '" + cancelName + "'"); } catch (final DirectoryWalker.CancelException cancel) { final File last = walker.results.get(walker.results.size() - 1); assertEquals(cancelName, last.getName()); assertEquals(5, cancel.getDepth(), "Depth: " + cancelName); } catch(final IOException ex) { fail("IOException: " + cancelName + " " + ex); } // Cancel on a directory try { cancelName = "commons"; walker = new TestMultiThreadCancelWalker(cancelName, false); walker.find(javaDir); fail("CancelException not thrown for '" + cancelName + "'"); } catch (final DirectoryWalker.CancelException cancel) { assertEquals(cancelName, cancel.getFile().getName(), "File: " + cancelName); assertEquals(3, cancel.getDepth(), "Depth: " + cancelName); } catch(final IOException ex) { fail("IOException: " + cancelName + " " + ex); } // Suppress CancelException (use same file name as preceding test) try { walker = new TestMultiThreadCancelWalker(cancelName, true); final List results = walker.find(javaDir); final File lastFile = results.get(results.size() - 1); assertEquals(cancelName, lastFile.getName(), "Suppress: " + cancelName); } catch(final IOException ex) { fail("Suppress threw " + ex); } } /** * Test Filtering */ @Test public void testFilterString() { final List results = new TestFileFinderString(dirsAndFilesFilter, -1).find(javaDir); assertEquals(results.size(), outputFiles.length + ioFiles.length, "Result Size"); checkContainsString("IO File", ioFiles, results); checkContainsString("Output File", outputFiles, results); } // ------------ Test DirectoryWalker implementation -------------------------- /** * Test DirectoryWalker implementation that finds files in a directory hierarchy * applying a file filter. */ private static class TestFileFinder extends DirectoryWalker { protected TestFileFinder(final FileFilter filter, final int depthLimit) { super(filter, depthLimit); } protected TestFileFinder(final IOFileFilter dirFilter, final IOFileFilter fileFilter, final int depthLimit) { super(dirFilter, fileFilter, depthLimit); } /** find files. */ protected List find(final File startDirectory) { final List results = new ArrayList<>(); try { walk(startDirectory, results); } catch(final IOException ex) { fail(ex.toString()); } return results; } /** Handles a directory end by adding the File to the result set. */ @Override protected void handleDirectoryEnd(final File directory, final int depth, final Collection results) { results.add(directory); } /** Handles a file by adding the File to the result set. */ @Override protected void handleFile(final File file, final int depth, final Collection results) { results.add(file); } } // ------------ Test DirectoryWalker implementation -------------------------- /** * Test DirectoryWalker implementation that always returns false * from handleDirectoryStart() */ private static class TestFalseFileFinder extends TestFileFinder { protected TestFalseFileFinder(final FileFilter filter, final int depthLimit) { super(filter, depthLimit); } /** Always returns false. */ @Override protected boolean handleDirectory(final File directory, final int depth, final Collection results) { return false; } } // ------------ Test DirectoryWalker implementation -------------------------- /** * Test DirectoryWalker implementation that finds files in a directory hierarchy * applying a file filter. */ static class TestCancelWalker extends DirectoryWalker { private final String cancelFileName; private final boolean suppressCancel; TestCancelWalker(final String cancelFileName,final boolean suppressCancel) { this.cancelFileName = cancelFileName; this.suppressCancel = suppressCancel; } /** find files. */ protected List find(final File startDirectory) throws IOException { final List results = new ArrayList<>(); walk(startDirectory, results); return results; } /** Handles a directory end by adding the File to the result set. */ @Override protected void handleDirectoryEnd(final File directory, final int depth, final Collection results) throws IOException { results.add(directory); if (cancelFileName.equals(directory.getName())) { throw new CancelException(directory, depth); } } /** Handles a file by adding the File to the result set. */ @Override protected void handleFile(final File file, final int depth, final Collection results) throws IOException { results.add(file); if (cancelFileName.equals(file.getName())) { throw new CancelException(file, depth); } } /** Handles Cancel. */ @Override protected void handleCancelled(final File startDirectory, final Collection results, final CancelException cancel) throws IOException { if (!suppressCancel) { super.handleCancelled(startDirectory, results, cancel); } } } /** * Test DirectoryWalker implementation that finds files in a directory hierarchy * applying a file filter. */ static class TestMultiThreadCancelWalker extends DirectoryWalker { private final String cancelFileName; private final boolean suppressCancel; private boolean cancelled; public List results; TestMultiThreadCancelWalker(final String cancelFileName, final boolean suppressCancel) { this.cancelFileName = cancelFileName; this.suppressCancel = suppressCancel; } /** find files. */ protected List find(final File startDirectory) throws IOException { results = new ArrayList<>(); walk(startDirectory, results); return results; } /** Handles a directory end by adding the File to the result set. */ @Override protected void handleDirectoryEnd(final File directory, final int depth, final Collection results) throws IOException { results.add(directory); assertFalse(cancelled); if (cancelFileName.equals(directory.getName())) { cancelled = true; } } /** Handles a file by adding the File to the result set. */ @Override protected void handleFile(final File file, final int depth, final Collection results) throws IOException { results.add(file); assertFalse(cancelled); if (cancelFileName.equals(file.getName())) { cancelled = true; } } /** Handles Cancelled. */ @Override protected boolean handleIsCancelled(final File file, final int depth, final Collection results) throws IOException { return cancelled; } /** Handles Cancel. */ @Override protected void handleCancelled(final File startDirectory, final Collection results, final CancelException cancel) throws IOException { if (!suppressCancel) { super.handleCancelled(startDirectory, results, cancel); } } } /** * Test DirectoryWalker implementation that finds files in a directory hierarchy * applying a file filter. */ private static class TestFileFinderString extends DirectoryWalker { protected TestFileFinderString(final FileFilter filter, final int depthLimit) { super(filter, depthLimit); } /** find files. */ protected List find(final File startDirectory) { final List results = new ArrayList<>(); try { walk(startDirectory, results); } catch(final IOException ex) { fail(ex.toString()); } return results; } /** Handles a file by adding the File to the result set. */ @Override protected void handleFile(final File file, final int depth, final Collection results) { results.add(file.toString()); } } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/DirectoryWalkerTestCaseJava4.java0100644 0000000 0000000 00000046414 13612062727 032076 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import java.io.File; import java.io.FileFilter; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.apache.commons.io.filefilter.FileFilterUtils; import org.apache.commons.io.filefilter.IOFileFilter; import org.apache.commons.io.filefilter.NameFileFilter; import org.apache.commons.io.filefilter.OrFileFilter; import org.junit.jupiter.api.Test; /** * This is used to test DirectoryWalker for correctness when using Java4 (i.e. no generics). * * @see DirectoryWalker */ @SuppressWarnings({"unchecked", "rawtypes"}) // Java4 public class DirectoryWalkerTestCaseJava4 { // Directories private static final File current = new File("."); private static final File javaDir = new File("src/main/java"); private static final File orgDir = new File(javaDir, "org"); private static final File apacheDir = new File(orgDir, "apache"); private static final File commonsDir = new File(apacheDir, "commons"); private static final File ioDir = new File(commonsDir, "io"); private static final File outputDir = new File(ioDir, "output"); private static final File[] dirs = {orgDir, apacheDir, commonsDir, ioDir, outputDir}; // Files private static final File filenameUtils = new File(ioDir, "FilenameUtils.java"); private static final File ioUtils = new File(ioDir, "IOUtils.java"); private static final File proxyWriter = new File(outputDir, "ProxyWriter.java"); private static final File nullStream = new File(outputDir, "NullOutputStream.java"); private static final File[] ioFiles = {filenameUtils, ioUtils}; private static final File[] outputFiles = {proxyWriter, nullStream}; // Filters private static final IOFileFilter dirsFilter = createNameFilter(dirs); private static final IOFileFilter iofilesFilter = createNameFilter(ioFiles); private static final IOFileFilter outputFilesFilter = createNameFilter(outputFiles); private static final IOFileFilter ioDirAndFilesFilter = new OrFileFilter(dirsFilter, iofilesFilter); private static final IOFileFilter dirsAndFilesFilter = new OrFileFilter(ioDirAndFilesFilter, outputFilesFilter); // Filter to exclude SVN files private static final IOFileFilter NOT_SVN = FileFilterUtils.makeSVNAware(null); /** * Test Filtering */ @Test public void testFilter() { final List results = new TestFileFinder(dirsAndFilesFilter, -1).find(javaDir); assertEquals(1 + dirs.length + ioFiles.length + outputFiles.length, results.size(), "Result Size"); assertTrue(results.contains(javaDir), "Start Dir"); checkContainsFiles("Dir", dirs, results); checkContainsFiles("IO File", ioFiles, results); checkContainsFiles("Output File", outputFiles, results); } /** * Test Filtering and limit to depth 0 */ @Test public void testFilterAndLimitA() { final List results = new TestFileFinder(NOT_SVN, 0).find(javaDir); assertEquals(1, results.size(), "[A] Result Size"); assertTrue(results.contains(javaDir), "[A] Start Dir"); } /** * Test Filtering and limit to depth 1 */ @Test public void testFilterAndLimitB() { final List results = new TestFileFinder(NOT_SVN, 1).find(javaDir); assertEquals(2, results.size(), "[B] Result Size"); assertTrue(results.contains(javaDir), "[B] Start Dir"); assertTrue(results.contains(orgDir), "[B] Org Dir"); } /** * Test Filtering and limit to depth 3 */ @Test public void testFilterAndLimitC() { final List results = new TestFileFinder(NOT_SVN, 3).find(javaDir); assertEquals(4, results.size(), "[C] Result Size"); assertTrue(results.contains(javaDir), "[C] Start Dir"); assertTrue(results.contains(orgDir), "[C] Org Dir"); assertTrue(results.contains(apacheDir), "[C] Apache Dir"); assertTrue(results.contains(commonsDir), "[C] Commons Dir"); } /** * Test Filtering and limit to depth 5 */ @Test public void testFilterAndLimitD() { final List results = new TestFileFinder(dirsAndFilesFilter, 5).find(javaDir); assertEquals(1 + dirs.length + ioFiles.length, results.size(), "[D] Result Size"); assertTrue(results.contains(javaDir), "[D] Start Dir"); checkContainsFiles("[D] Dir", dirs, results); checkContainsFiles("[D] File", ioFiles, results); } /** * Test separate dir and file filters */ @Test public void testFilterDirAndFile1() { final List results = new TestFileFinder(dirsFilter, iofilesFilter, -1).find(javaDir); assertEquals(1 + dirs.length + ioFiles.length, results.size(), "[DirAndFile1] Result Size"); assertTrue(results.contains(javaDir), "[DirAndFile1] Start Dir"); checkContainsFiles("[DirAndFile1] Dir", dirs, results); checkContainsFiles("[DirAndFile1] File", ioFiles, results); } /** * Test separate dir and file filters */ @Test public void testFilterDirAndFile2() { final List results = new TestFileFinder(null, null, -1).find(javaDir); assertTrue(results.size() > 1 + dirs.length + ioFiles.length, "[DirAndFile2] Result Size"); assertTrue(results.contains(javaDir), "[DirAndFile2] Start Dir"); checkContainsFiles("[DirAndFile2] Dir", dirs, results); checkContainsFiles("[DirAndFile2] File", ioFiles, results); } /** * Test separate dir and file filters */ @Test public void testFilterDirAndFile3() { final List results = new TestFileFinder(dirsFilter, null, -1).find(javaDir); final List resultDirs = directoriesOnly(results); assertEquals(1 + dirs.length, resultDirs.size(), "[DirAndFile3] Result Size"); assertTrue(results.contains(javaDir), "[DirAndFile3] Start Dir"); checkContainsFiles("[DirAndFile3] Dir", dirs, resultDirs); } /** * Test separate dir and file filters */ @Test public void testFilterDirAndFile4() { final List results = new TestFileFinder(null, iofilesFilter, -1).find(javaDir); final List resultFiles = filesOnly(results); assertEquals(ioFiles.length, resultFiles.size(), "[DirAndFile4] Result Size"); assertTrue(results.contains(javaDir), "[DirAndFile4] Start Dir"); checkContainsFiles("[DirAndFile4] File", ioFiles, resultFiles); } /** * Test Limiting to current directory */ @Test public void testLimitToCurrent() { final List results = new TestFileFinder(null, 0).find(current); assertEquals(1, results.size(), "Result Size"); assertTrue(results.contains(new File(".")), "Current Dir"); } /** * test an invalid start directory */ @Test public void testMissingStartDirectory() { // TODO is this what we want with invalid directory? final File invalidDir = new File("invalid-dir"); final List results = new TestFileFinder(null, -1).find(invalidDir); assertEquals(1, results.size(), "Result Size"); assertTrue(results.contains(invalidDir), "Current Dir"); try { new TestFileFinder(null, -1).find(null); fail("Null start directory didn't throw Exception"); } catch (final NullPointerException ignore) { // expected result } } /** * test an invalid start directory */ @Test public void testHandleStartDirectoryFalse() { final List results = new TestFalseFileFinder(null, -1).find(current); assertEquals(0, results.size(), "Result Size"); } // ------------ Convenience Test Methods ------------------------------------ /** * Check the files in the array are in the results list. */ private void checkContainsFiles(final String prefix, final File[] files, final Collection results) { for (int i = 0; i < files.length; i++) { assertTrue(results.contains(files[i]), prefix + "[" + i + "] " + files[i]); } } /** * Extract the directories. */ private List directoriesOnly(final Collection results) { final List list = new ArrayList(results.size()); for (final File file : results) { if (file.isDirectory()) { list.add(file); } } return list; } /** * Extract the files. */ private List filesOnly(final Collection results) { final List list = new ArrayList(results.size()); for (final File file : results) { if (file.isFile()) { list.add(file); } } return list; } /** * Create a name filter containing the names of the files * in the array. */ private static IOFileFilter createNameFilter(final File[] files) { final String[] names = new String[files.length]; for (int i = 0; i < files.length; i++) { names[i] = files[i].getName(); } return new NameFileFilter(names); } /** * Test Cancel * @throws IOException */ @Test public void testCancel() throws IOException { String cancelName = null; // Cancel on a file try { cancelName = "DirectoryWalker.java"; new TestCancelWalker(cancelName, false).find(javaDir); fail("CancelException not thrown for '" + cancelName + "'"); } catch (final DirectoryWalker.CancelException cancel) { assertEquals(cancelName, cancel.getFile().getName(), "File: " + cancelName); assertEquals(5, cancel.getDepth(), "Depth: " + cancelName); } // Cancel on a directory try { cancelName = "commons"; new TestCancelWalker(cancelName, false).find(javaDir); fail("CancelException not thrown for '" + cancelName + "'"); } catch (final DirectoryWalker.CancelException cancel) { assertEquals(cancelName, cancel.getFile().getName(), "File: " + cancelName); assertEquals(3, cancel.getDepth(), "Depth: " + cancelName); } // Suppress CancelException (use same file name as preceding test) final List results = new TestCancelWalker(cancelName, true).find(javaDir); final File lastFile = (File) results.get(results.size() - 1); assertEquals(cancelName, lastFile.getName(), "Suppress: " + cancelName); } /** * Test Cancel * @throws IOException */ @Test public void testMultiThreadCancel() throws IOException { String cancelName = "DirectoryWalker.java"; TestMultiThreadCancelWalker walker = new TestMultiThreadCancelWalker(cancelName, false); // Cancel on a file try { walker.find(javaDir); fail("CancelException not thrown for '" + cancelName + "'"); } catch (final DirectoryWalker.CancelException cancel) { final File last = (File) walker.results.get(walker.results.size() - 1); assertEquals(cancelName, last.getName()); assertEquals(5, cancel.getDepth(), "Depth: " + cancelName); } // Cancel on a directory try { cancelName = "commons"; walker = new TestMultiThreadCancelWalker(cancelName, false); walker.find(javaDir); fail("CancelException not thrown for '" + cancelName + "'"); } catch (final DirectoryWalker.CancelException cancel) { assertEquals(cancelName, cancel.getFile().getName(), "File: " + cancelName); assertEquals(3, cancel.getDepth(), "Depth: " + cancelName); } // Suppress CancelException (use same file name as preceding test) walker = new TestMultiThreadCancelWalker(cancelName, true); final List results = walker.find(javaDir); final File lastFile = (File) results.get(results.size() - 1); assertEquals(cancelName, lastFile.getName(), "Suppress: " + cancelName); } // ------------ Test DirectoryWalker implementation -------------------------- /** * Test DirectoryWalker implementation that finds files in a directory hierarchy * applying a file filter. */ private static class TestFileFinder extends DirectoryWalker { protected TestFileFinder(final FileFilter filter, final int depthLimit) { super(filter, depthLimit); } protected TestFileFinder(final IOFileFilter dirFilter, final IOFileFilter fileFilter, final int depthLimit) { super(dirFilter, fileFilter, depthLimit); } /** * find files. */ protected List find(final File startDirectory) { final List results = new ArrayList<>(); try { walk(startDirectory, results); } catch (final IOException ex) { fail(ex.toString()); } return results; } /** * Handles a directory end by adding the File to the result set. */ @Override protected void handleDirectoryEnd(final File directory, final int depth, final Collection results) { results.add(directory); } /** * Handles a file by adding the File to the result set. */ @Override protected void handleFile(final File file, final int depth, final Collection results) { results.add(file); } } // ------------ Test DirectoryWalker implementation -------------------------- /** * Test DirectoryWalker implementation that always returns false * from handleDirectoryStart() */ private static class TestFalseFileFinder extends TestFileFinder { protected TestFalseFileFinder(final FileFilter filter, final int depthLimit) { super(filter, depthLimit); } /** * Always returns false. */ @Override protected boolean handleDirectory(final File directory, final int depth, final Collection results) { return false; } } // ------------ Test DirectoryWalker implementation -------------------------- /** * Test DirectoryWalker implementation that finds files in a directory hierarchy * applying a file filter. */ static class TestCancelWalker extends DirectoryWalker { private final String cancelFileName; private final boolean suppressCancel; TestCancelWalker(final String cancelFileName, final boolean suppressCancel) { this.cancelFileName = cancelFileName; this.suppressCancel = suppressCancel; } /** * find files. */ protected List find(final File startDirectory) throws IOException { final List results = new ArrayList(); walk(startDirectory, results); return results; } /** * Handles a directory end by adding the File to the result set. */ @Override protected void handleDirectoryEnd(final File directory, final int depth, final Collection results) throws IOException { results.add(directory); if (cancelFileName.equals(directory.getName())) { throw new CancelException(directory, depth); } } /** * Handles a file by adding the File to the result set. */ @Override protected void handleFile(final File file, final int depth, final Collection results) throws IOException { results.add(file); if (cancelFileName.equals(file.getName())) { throw new CancelException(file, depth); } } /** * Handles Cancel. */ @Override protected void handleCancelled(final File startDirectory, final Collection results, final CancelException cancel) throws IOException { if (!suppressCancel) { super.handleCancelled(startDirectory, results, cancel); } } } /** * Test DirectoryWalker implementation that finds files in a directory hierarchy * applying a file filter. */ static class TestMultiThreadCancelWalker extends DirectoryWalker { private final String cancelFileName; private final boolean suppressCancel; private boolean cancelled; public List results; TestMultiThreadCancelWalker(final String cancelFileName, final boolean suppressCancel) { this.cancelFileName = cancelFileName; this.suppressCancel = suppressCancel; } /** * find files. */ protected List find(final File startDirectory) throws IOException { results = new ArrayList(); walk(startDirectory, results); return results; } /** * Handles a directory end by adding the File to the result set. */ @Override protected void handleDirectoryEnd(final File directory, final int depth, final Collection results) throws IOException { results.add(directory); assertFalse(cancelled); if (cancelFileName.equals(directory.getName())) { cancelled = true; } } /** * Handles a file by adding the File to the result set. */ @Override protected void handleFile(final File file, final int depth, final Collection results) throws IOException { results.add(file); assertFalse(cancelled); if (cancelFileName.equals(file.getName())) { cancelled = true; } } /** * Handles Cancelled. */ @Override protected boolean handleIsCancelled(final File file, final int depth, final Collection results) throws IOException { return cancelled; } /** * Handles Cancel. */ @Override protected void handleCancelled(final File startDirectory, final Collection results, final CancelException cancel) throws IOException { if (!suppressCancel) { super.handleCancelled(startDirectory, results, cancel); } } } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/EndianUtilsTest.java0100644 0000000 0000000 00000030310 13612062727 027505 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.EOFException; import java.io.IOException; import org.junit.jupiter.api.Test; /** * */ public class EndianUtilsTest { @Test public void testCtor() { new EndianUtils(); // Constructor does not blow up. } @Test public void testEOFException() throws IOException { final ByteArrayInputStream input = new ByteArrayInputStream(new byte[] {}); try { EndianUtils.readSwappedDouble(input); fail("Expected EOFException"); } catch (final EOFException e) { // expected } } @Test public void testSwapShort() { assertEquals( (short) 0, EndianUtils.swapShort( (short) 0 ) ); assertEquals( (short) 0x0201, EndianUtils.swapShort( (short) 0x0102 ) ); assertEquals( (short) 0xffff, EndianUtils.swapShort( (short) 0xffff ) ); assertEquals( (short) 0x0102, EndianUtils.swapShort( (short) 0x0201 ) ); } @Test public void testSwapInteger() { assertEquals( 0, EndianUtils.swapInteger( 0 ) ); assertEquals( 0x04030201, EndianUtils.swapInteger( 0x01020304 ) ); assertEquals( 0x01000000, EndianUtils.swapInteger( 0x00000001 ) ); assertEquals( 0x00000001, EndianUtils.swapInteger( 0x01000000 ) ); assertEquals( 0x11111111, EndianUtils.swapInteger( 0x11111111 ) ); assertEquals( 0xabcdef10, EndianUtils.swapInteger( 0x10efcdab ) ); assertEquals( 0xab, EndianUtils.swapInteger( 0xab000000 ) ); } @Test public void testSwapLong() { assertEquals( 0, EndianUtils.swapLong( 0 ) ); assertEquals( 0x0807060504030201L, EndianUtils.swapLong( 0x0102030405060708L ) ); assertEquals( 0xffffffffffffffffL, EndianUtils.swapLong( 0xffffffffffffffffL ) ); assertEquals( 0xab, EndianUtils.swapLong( 0xab00000000000000L ) ); } @Test public void testSwapFloat() { assertEquals( 0.0f, EndianUtils.swapFloat( 0.0f ), 0.0 ); final float f1 = Float.intBitsToFloat( 0x01020304 ); final float f2 = Float.intBitsToFloat( 0x04030201 ); assertEquals( f2, EndianUtils.swapFloat( f1 ), 0.0 ); } @Test public void testSwapDouble() { assertEquals( 0.0, EndianUtils.swapDouble( 0.0 ), 0.0 ); final double d1 = Double.longBitsToDouble( 0x0102030405060708L ); final double d2 = Double.longBitsToDouble( 0x0807060504030201L ); assertEquals( d2, EndianUtils.swapDouble( d1 ), 0.0 ); } /** * Tests all swapXxxx methods for symmetry when going from one endian * to another and back again. */ @Test public void testSymmetry() { assertEquals( (short) 0x0102, EndianUtils.swapShort( EndianUtils.swapShort( (short) 0x0102 ) ) ); assertEquals( 0x01020304, EndianUtils.swapInteger( EndianUtils.swapInteger( 0x01020304 ) ) ); assertEquals( 0x0102030405060708L, EndianUtils.swapLong( EndianUtils.swapLong( 0x0102030405060708L ) ) ); final float f1 = Float.intBitsToFloat( 0x01020304 ); assertEquals( f1, EndianUtils.swapFloat( EndianUtils.swapFloat( f1 ) ), 0.0 ); final double d1 = Double.longBitsToDouble( 0x0102030405060708L ); assertEquals( d1, EndianUtils.swapDouble( EndianUtils.swapDouble( d1 ) ), 0.0 ); } @Test public void testReadSwappedShort() throws IOException { final byte[] bytes = { 0x02, 0x01 }; assertEquals( 0x0102, EndianUtils.readSwappedShort( bytes, 0 ) ); final ByteArrayInputStream input = new ByteArrayInputStream(bytes); assertEquals( 0x0102, EndianUtils.readSwappedShort( input ) ); } @Test public void testWriteSwappedShort() throws IOException { byte[] bytes = new byte[2]; EndianUtils.writeSwappedShort( bytes, 0, (short) 0x0102 ); assertEquals( 0x02, bytes[0] ); assertEquals( 0x01, bytes[1] ); final ByteArrayOutputStream baos = new ByteArrayOutputStream(2); EndianUtils.writeSwappedShort( baos, (short) 0x0102 ); bytes = baos.toByteArray(); assertEquals( 0x02, bytes[0] ); assertEquals( 0x01, bytes[1] ); } @Test public void testReadSwappedUnsignedShort() throws IOException { final byte[] bytes = { 0x02, 0x01 }; assertEquals( 0x00000102, EndianUtils.readSwappedUnsignedShort( bytes, 0 ) ); final ByteArrayInputStream input = new ByteArrayInputStream(bytes); assertEquals( 0x00000102, EndianUtils.readSwappedUnsignedShort( input ) ); } @Test public void testReadSwappedInteger() throws IOException { final byte[] bytes = { 0x04, 0x03, 0x02, 0x01 }; assertEquals( 0x01020304, EndianUtils.readSwappedInteger( bytes, 0 ) ); final ByteArrayInputStream input = new ByteArrayInputStream(bytes); assertEquals( 0x01020304, EndianUtils.readSwappedInteger( input ) ); } @Test public void testWriteSwappedInteger() throws IOException { byte[] bytes = new byte[4]; EndianUtils.writeSwappedInteger( bytes, 0, 0x01020304 ); assertEquals( 0x04, bytes[0] ); assertEquals( 0x03, bytes[1] ); assertEquals( 0x02, bytes[2] ); assertEquals( 0x01, bytes[3] ); final ByteArrayOutputStream baos = new ByteArrayOutputStream(4); EndianUtils.writeSwappedInteger( baos, 0x01020304 ); bytes = baos.toByteArray(); assertEquals( 0x04, bytes[0] ); assertEquals( 0x03, bytes[1] ); assertEquals( 0x02, bytes[2] ); assertEquals( 0x01, bytes[3] ); } @Test public void testReadSwappedUnsignedInteger() throws IOException { final byte[] bytes = { 0x04, 0x03, 0x02, 0x01 }; assertEquals( 0x0000000001020304L, EndianUtils.readSwappedUnsignedInteger( bytes, 0 ) ); final ByteArrayInputStream input = new ByteArrayInputStream(bytes); assertEquals( 0x0000000001020304L, EndianUtils.readSwappedUnsignedInteger( input ) ); } @Test public void testReadSwappedLong() throws IOException { final byte[] bytes = { 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01 }; assertEquals( 0x0102030405060708L, EndianUtils.readSwappedLong( bytes, 0 ) ); final ByteArrayInputStream input = new ByteArrayInputStream(bytes); assertEquals( 0x0102030405060708L, EndianUtils.readSwappedLong( input ) ); } @Test public void testWriteSwappedLong() throws IOException { byte[] bytes = new byte[8]; EndianUtils.writeSwappedLong( bytes, 0, 0x0102030405060708L ); assertEquals( 0x08, bytes[0] ); assertEquals( 0x07, bytes[1] ); assertEquals( 0x06, bytes[2] ); assertEquals( 0x05, bytes[3] ); assertEquals( 0x04, bytes[4] ); assertEquals( 0x03, bytes[5] ); assertEquals( 0x02, bytes[6] ); assertEquals( 0x01, bytes[7] ); final ByteArrayOutputStream baos = new ByteArrayOutputStream(8); EndianUtils.writeSwappedLong( baos, 0x0102030405060708L ); bytes = baos.toByteArray(); assertEquals( 0x08, bytes[0] ); assertEquals( 0x07, bytes[1] ); assertEquals( 0x06, bytes[2] ); assertEquals( 0x05, bytes[3] ); assertEquals( 0x04, bytes[4] ); assertEquals( 0x03, bytes[5] ); assertEquals( 0x02, bytes[6] ); assertEquals( 0x01, bytes[7] ); } @Test public void testReadSwappedFloat() throws IOException { final byte[] bytes = { 0x04, 0x03, 0x02, 0x01 }; final float f1 = Float.intBitsToFloat( 0x01020304 ); final float f2 = EndianUtils.readSwappedFloat( bytes, 0 ); assertEquals( f1, f2, 0.0 ); final ByteArrayInputStream input = new ByteArrayInputStream(bytes); assertEquals( f1, EndianUtils.readSwappedFloat( input ), 0.0 ); } @Test public void testWriteSwappedFloat() throws IOException { byte[] bytes = new byte[4]; final float f1 = Float.intBitsToFloat( 0x01020304 ); EndianUtils.writeSwappedFloat( bytes, 0, f1 ); assertEquals( 0x04, bytes[0] ); assertEquals( 0x03, bytes[1] ); assertEquals( 0x02, bytes[2] ); assertEquals( 0x01, bytes[3] ); final ByteArrayOutputStream baos = new ByteArrayOutputStream(4); EndianUtils.writeSwappedFloat( baos, f1 ); bytes = baos.toByteArray(); assertEquals( 0x04, bytes[0] ); assertEquals( 0x03, bytes[1] ); assertEquals( 0x02, bytes[2] ); assertEquals( 0x01, bytes[3] ); } @Test public void testReadSwappedDouble() throws IOException { final byte[] bytes = { 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01 }; final double d1 = Double.longBitsToDouble( 0x0102030405060708L ); final double d2 = EndianUtils.readSwappedDouble( bytes, 0 ); assertEquals( d1, d2, 0.0 ); final ByteArrayInputStream input = new ByteArrayInputStream(bytes); assertEquals( d1, EndianUtils.readSwappedDouble( input ), 0.0 ); } @Test public void testWriteSwappedDouble() throws IOException { byte[] bytes = new byte[8]; final double d1 = Double.longBitsToDouble( 0x0102030405060708L ); EndianUtils.writeSwappedDouble( bytes, 0, d1 ); assertEquals( 0x08, bytes[0] ); assertEquals( 0x07, bytes[1] ); assertEquals( 0x06, bytes[2] ); assertEquals( 0x05, bytes[3] ); assertEquals( 0x04, bytes[4] ); assertEquals( 0x03, bytes[5] ); assertEquals( 0x02, bytes[6] ); assertEquals( 0x01, bytes[7] ); final ByteArrayOutputStream baos = new ByteArrayOutputStream(8); EndianUtils.writeSwappedDouble( baos, d1 ); bytes = baos.toByteArray(); assertEquals( 0x08, bytes[0] ); assertEquals( 0x07, bytes[1] ); assertEquals( 0x06, bytes[2] ); assertEquals( 0x05, bytes[3] ); assertEquals( 0x04, bytes[4] ); assertEquals( 0x03, bytes[5] ); assertEquals( 0x02, bytes[6] ); assertEquals( 0x01, bytes[7] ); } // tests #IO-101 @Test public void testSymmetryOfLong() { final double[] tests = {34.345, -345.5645, 545.12, 10.043, 7.123456789123}; for (final double test : tests) { // testing the real problem byte[] buffer = new byte[8]; final long ln1 = Double.doubleToLongBits( test ); EndianUtils.writeSwappedLong(buffer, 0, ln1); final long ln2 = EndianUtils.readSwappedLong(buffer, 0); assertEquals( ln1, ln2 ); // testing the bug report buffer = new byte[8]; EndianUtils.writeSwappedDouble(buffer, 0, test); final double val = EndianUtils.readSwappedDouble(buffer, 0); assertEquals( test, val, 0 ); } } // tests #IO-117 @Test public void testUnsignedOverrun() throws Exception { final byte[] target = { 0, 0, 0, (byte)0x80 }; final long expected = 0x80000000L; long actual = EndianUtils.readSwappedUnsignedInteger(target, 0); assertEquals(expected, actual, "readSwappedUnsignedInteger(byte[], int) was incorrect"); final ByteArrayInputStream in = new ByteArrayInputStream(target); actual = EndianUtils.readSwappedUnsignedInteger(in); assertEquals(expected, actual, "readSwappedUnsignedInteger(InputStream) was incorrect"); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/FileCleanerTestCase.java0100644 0000000 0000000 00000002215 13612062727 030236 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; @SuppressWarnings("deprecation") // testing deprecated class /** * This is used to test FileCleaner for correctness. * * @see FileCleaner */ public class FileCleanerTestCase extends FileCleaningTrackerTestCase { @Override protected FileCleaningTracker newInstance() { return FileCleaner.getInstance(); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/FileCleaningTrackerTestCase.java0100644 0000000 0000000 00000027262 13612062727 031732 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import java.io.BufferedOutputStream; import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; import java.lang.ref.ReferenceQueue; import java.nio.file.Files; import java.util.ArrayList; import java.util.List; import org.apache.commons.io.test.TestUtils; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; /** * This is used to test {@link FileCleaningTracker} for correctness. * * @see FileCleaningTracker */ public class FileCleaningTrackerTestCase { @TempDir public File temporaryFolder; protected FileCleaningTracker newInstance() { return new FileCleaningTracker(); } private File testFile; private FileCleaningTracker theInstance; /** */ @BeforeEach public void setUp() { testFile = new File(temporaryFolder, "file-test.txt"); theInstance = newInstance(); } @AfterEach public void tearDown() { // reset file cleaner class, so as not to break other tests /** * The following block of code can possibly be removed when the deprecated {@link FileCleaner} is gone. The * question is, whether we want to support reuse of {@link FileCleaningTracker} instances, which we should, IMO, * not. */ { if (theInstance != null) { theInstance.q = new ReferenceQueue<>(); theInstance.trackers.clear(); theInstance.deleteFailures.clear(); theInstance.exitWhenFinished = false; theInstance.reaper = null; } } theInstance = null; } @Test public void testFileCleanerFile() throws Exception { final String path = testFile.getPath(); assertFalse(testFile.exists()); RandomAccessFile r = new RandomAccessFile(testFile, "rw"); assertTrue(testFile.exists()); assertEquals(0, theInstance.getTrackCount()); theInstance.track(path, r); assertEquals(1, theInstance.getTrackCount()); r.close(); testFile = null; r = null; waitUntilTrackCount(); pauseForDeleteToComplete(new File(path)); assertEquals(0, theInstance.getTrackCount()); assertFalse(new File(path).exists(), showFailures()); } @Test public void testFileCleanerDirectory() throws Exception { TestUtils.createFile(testFile, 100); assertTrue(testFile.exists()); assertTrue(temporaryFolder.exists()); Object obj = new Object(); assertEquals(0, theInstance.getTrackCount()); theInstance.track(temporaryFolder, obj); assertEquals(1, theInstance.getTrackCount()); obj = null; waitUntilTrackCount(); assertEquals(0, theInstance.getTrackCount()); assertTrue(testFile.exists()); // not deleted, as dir not empty assertTrue(testFile.getParentFile().exists()); // not deleted, as dir not empty } @Test public void testFileCleanerDirectory_NullStrategy() throws Exception { TestUtils.createFile(testFile, 100); assertTrue(testFile.exists()); assertTrue(temporaryFolder.exists()); Object obj = new Object(); assertEquals(0, theInstance.getTrackCount()); theInstance.track(temporaryFolder, obj, null); assertEquals(1, theInstance.getTrackCount()); obj = null; waitUntilTrackCount(); assertEquals(0, theInstance.getTrackCount()); assertTrue(testFile.exists()); // not deleted, as dir not empty assertTrue(testFile.getParentFile().exists()); // not deleted, as dir not empty } @Test public void testFileCleanerDirectory_ForceStrategy() throws Exception { if (!testFile.getParentFile().exists()) { throw new IOException("Cannot create file " + testFile + " as the parent directory does not exist"); } try (final BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(testFile.toPath()))) { TestUtils.generateTestData(output, 100); } assertTrue(testFile.exists()); assertTrue(temporaryFolder.exists()); Object obj = new Object(); assertEquals(0, theInstance.getTrackCount()); theInstance.track(temporaryFolder, obj, FileDeleteStrategy.FORCE); assertEquals(1, theInstance.getTrackCount()); obj = null; waitUntilTrackCount(); pauseForDeleteToComplete(testFile.getParentFile()); assertEquals(0, theInstance.getTrackCount()); assertFalse(new File(testFile.getPath()).exists(), showFailures()); assertFalse(testFile.getParentFile().exists(), showFailures()); } @Test public void testFileCleanerNull() { try { theInstance.track((File) null, new Object()); fail(); } catch (final NullPointerException ex) { // expected } try { theInstance.track((File) null, new Object(), FileDeleteStrategy.NORMAL); fail(); } catch (final NullPointerException ex) { // expected } try { theInstance.track((String) null, new Object()); fail(); } catch (final NullPointerException ex) { // expected } try { theInstance.track((String) null, new Object(), FileDeleteStrategy.NORMAL); fail(); } catch (final NullPointerException ex) { // expected } } @Test public void testFileCleanerExitWhenFinishedFirst() throws Exception { assertFalse(theInstance.exitWhenFinished); theInstance.exitWhenFinished(); assertTrue(theInstance.exitWhenFinished); assertNull(theInstance.reaper); waitUntilTrackCount(); assertEquals(0, theInstance.getTrackCount()); assertTrue(theInstance.exitWhenFinished); assertNull(theInstance.reaper); } @Test public void testFileCleanerExitWhenFinished_NoTrackAfter() { assertFalse(theInstance.exitWhenFinished); theInstance.exitWhenFinished(); assertTrue(theInstance.exitWhenFinished); assertNull(theInstance.reaper); final String path = testFile.getPath(); final Object marker = new Object(); try { theInstance.track(path, marker); fail(); } catch (final IllegalStateException ex) { // expected } assertTrue(theInstance.exitWhenFinished); assertNull(theInstance.reaper); } @Test public void testFileCleanerExitWhenFinished1() throws Exception { final String path = testFile.getPath(); assertFalse(testFile.exists(), "1-testFile exists: " + testFile); RandomAccessFile r = new RandomAccessFile(testFile, "rw"); assertTrue(testFile.exists(), "2-testFile exists"); assertEquals(0, theInstance.getTrackCount(), "3-Track Count"); theInstance.track(path, r); assertEquals(1, theInstance.getTrackCount(), "4-Track Count"); assertFalse(theInstance.exitWhenFinished, "5-exitWhenFinished"); assertTrue(theInstance.reaper.isAlive(), "6-reaper.isAlive"); assertFalse(theInstance.exitWhenFinished, "7-exitWhenFinished"); theInstance.exitWhenFinished(); assertTrue(theInstance.exitWhenFinished, "8-exitWhenFinished"); assertTrue(theInstance.reaper.isAlive(), "9-reaper.isAlive"); r.close(); testFile = null; r = null; waitUntilTrackCount(); pauseForDeleteToComplete(new File(path)); assertEquals(0, theInstance.getTrackCount(), "10-Track Count"); assertFalse(new File(path).exists(), "11-testFile exists " + showFailures()); assertTrue(theInstance.exitWhenFinished, "12-exitWhenFinished"); assertFalse(theInstance.reaper.isAlive(), "13-reaper.isAlive"); } @Test public void testFileCleanerExitWhenFinished2() throws Exception { final String path = testFile.getPath(); assertFalse(testFile.exists()); RandomAccessFile r = new RandomAccessFile(testFile, "rw"); assertTrue(testFile.exists()); assertEquals(0, theInstance.getTrackCount()); theInstance.track(path, r); assertEquals(1, theInstance.getTrackCount()); assertFalse(theInstance.exitWhenFinished); assertTrue(theInstance.reaper.isAlive()); r.close(); testFile = null; r = null; waitUntilTrackCount(); pauseForDeleteToComplete(new File(path)); assertEquals(0, theInstance.getTrackCount()); assertFalse(new File(path).exists(), showFailures()); assertFalse(theInstance.exitWhenFinished); assertTrue(theInstance.reaper.isAlive()); assertFalse(theInstance.exitWhenFinished); theInstance.exitWhenFinished(); for (int i = 0; i < 20 && theInstance.reaper.isAlive(); i++) { TestUtils.sleep(500L); // allow reaper thread to die } assertTrue(theInstance.exitWhenFinished); assertFalse(theInstance.reaper.isAlive()); } private void pauseForDeleteToComplete(File file) { int count = 0; while(file.exists() && count++ < 40) { try { TestUtils.sleep(500L); } catch (final InterruptedException ignore) { } file = new File(file.getPath()); } } private String showFailures() { if (theInstance.deleteFailures.size() == 1) { return "[Delete Failed: " + theInstance.deleteFailures.get(0) + "]"; } return "[Delete Failures: " + theInstance.deleteFailures.size() + "]"; } private void waitUntilTrackCount() throws Exception { System.gc(); TestUtils.sleep(500); int count = 0; while(theInstance.getTrackCount() != 0 && count++ < 5) { List list = new ArrayList<>(); try { long i = 0; while (theInstance.getTrackCount() != 0) { list.add("A Big String A Big String A Big String A Big String A Big String A Big String A Big String A Big String A Big String A Big String " + (i++)); } } catch (final Throwable ignored) { } list = null; System.gc(); TestUtils.sleep(1000); } if (theInstance.getTrackCount() != 0) { throw new IllegalStateException("Your JVM is not releasing References, try running the testcase with less memory (-Xmx)"); } } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/FileDeleteStrategyTestCase.java0100644 0000000 0000000 00000013113 13612062727 031611 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import java.io.BufferedOutputStream; import java.io.File; import java.io.IOException; import java.nio.file.Files; import org.apache.commons.io.test.TestUtils; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; /** * Test for FileDeleteStrategy. * * @see FileDeleteStrategy */ public class FileDeleteStrategyTestCase { @TempDir public File temporaryFolder; @Test public void testDeleteNormal() throws Exception { final File baseDir = temporaryFolder; final File subDir = new File(baseDir, "test"); assertTrue(subDir.mkdir()); final File subFile = new File(subDir, "a.txt"); if (!subFile.getParentFile().exists()) { throw new IOException("Cannot create file " + subFile + " as the parent directory does not exist"); } try (final BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(subFile.toPath()))) { TestUtils.generateTestData(output, 16); } assertTrue(subDir.exists()); assertTrue(subFile.exists()); // delete dir try { FileDeleteStrategy.NORMAL.delete(subDir); fail(); } catch (final IOException ex) { // expected } assertTrue(subDir.exists()); assertTrue(subFile.exists()); // delete file FileDeleteStrategy.NORMAL.delete(subFile); assertTrue(subDir.exists()); assertFalse(subFile.exists()); // delete dir FileDeleteStrategy.NORMAL.delete(subDir); assertFalse(subDir.exists()); // delete dir FileDeleteStrategy.NORMAL.delete(subDir); // no error assertFalse(subDir.exists()); } @Test public void testDeleteQuietlyNormal() throws Exception { final File baseDir = temporaryFolder; final File subDir = new File(baseDir, "test"); assertTrue(subDir.mkdir()); final File subFile = new File(subDir, "a.txt"); if (!subFile.getParentFile().exists()) { throw new IOException("Cannot create file " + subFile + " as the parent directory does not exist"); } try (final BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(subFile.toPath()))) { TestUtils.generateTestData(output, 16); } assertTrue(subDir.exists()); assertTrue(subFile.exists()); // delete dir assertFalse(FileDeleteStrategy.NORMAL.deleteQuietly(subDir)); assertTrue(subDir.exists()); assertTrue(subFile.exists()); // delete file assertTrue(FileDeleteStrategy.NORMAL.deleteQuietly(subFile)); assertTrue(subDir.exists()); assertFalse(subFile.exists()); // delete dir assertTrue(FileDeleteStrategy.NORMAL.deleteQuietly(subDir)); assertFalse(subDir.exists()); // delete dir assertTrue(FileDeleteStrategy.NORMAL.deleteQuietly(subDir)); // no error assertFalse(subDir.exists()); } @Test public void testDeleteForce() throws Exception { final File baseDir = temporaryFolder; final File subDir = new File(baseDir, "test"); assertTrue(subDir.mkdir()); final File subFile = new File(subDir, "a.txt"); if (!subFile.getParentFile().exists()) { throw new IOException("Cannot create file " + subFile + " as the parent directory does not exist"); } try (final BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(subFile.toPath()))) { TestUtils.generateTestData(output, 16); } assertTrue(subDir.exists()); assertTrue(subFile.exists()); // delete dir FileDeleteStrategy.FORCE.delete(subDir); assertFalse(subDir.exists()); assertFalse(subFile.exists()); // delete dir FileDeleteStrategy.FORCE.delete(subDir); // no error assertFalse(subDir.exists()); } @Test public void testDeleteNull() throws Exception { try { FileDeleteStrategy.NORMAL.delete(null); fail(); } catch (final NullPointerException ex) { // expected } assertTrue(FileDeleteStrategy.NORMAL.deleteQuietly(null)); } @Test public void testToString() { assertEquals("FileDeleteStrategy[Normal]", FileDeleteStrategy.NORMAL.toString()); assertEquals("FileDeleteStrategy[Force]", FileDeleteStrategy.FORCE.toString()); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/FileSystemTestCase.java0100644 0000000 0000000 00000010651 13612062727 030154 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.apache.commons.lang3.SystemUtils; import org.junit.jupiter.api.Test; public class FileSystemTestCase { @Test public void testGetCurrent() { if (SystemUtils.IS_OS_WINDOWS) { assertEquals(FileSystem.WINDOWS, FileSystem.getCurrent()); } if (SystemUtils.IS_OS_LINUX) { assertEquals(FileSystem.LINUX, FileSystem.getCurrent()); } if (SystemUtils.IS_OS_MAC_OSX) { assertEquals(FileSystem.MAC_OSX, FileSystem.getCurrent()); } } @Test public void testIsLegalName() { for (final FileSystem fs : FileSystem.values()) { assertFalse(fs.isLegalFileName(""), fs.name()); // Empty is always illegal assertFalse(fs.isLegalFileName(null), fs.name()); // null is always illegal assertFalse(fs.isLegalFileName("\0"), fs.name()); // Assume NUL is always illegal assertTrue(fs.isLegalFileName("0"), fs.name()); // Assume simple name always legal for (final String candidate : fs.getReservedFileNames()) { // Reserved file names are not legal assertFalse(fs.isLegalFileName(candidate)); } } } @Test public void testIsReservedFileName() { for (final FileSystem fs : FileSystem.values()) { for (final String candidate : fs.getReservedFileNames()) { assertTrue(fs.isReservedFileName(candidate)); } } } @Test public void testReplacementWithNUL() { for (final FileSystem fs : FileSystem.values()) { try { fs.toLegalFileName("Test", '\0'); // Assume NUL is always illegal } catch (final IllegalArgumentException iae) { assertTrue(iae.getMessage().startsWith("The replacement character '\\0'"), iae.getMessage()); } } } @Test public void testSorted() { for (final FileSystem fs : FileSystem.values()) { final char[] chars = fs.getIllegalFileNameChars(); for (int i = 0; i < chars.length - 1; i++) { assertTrue(chars[i] < chars[i + 1], fs.name()); } } } @Test public void testSupportsDriveLetter() { assertTrue(FileSystem.WINDOWS.supportsDriveLetter()); assertFalse(FileSystem.GENERIC.supportsDriveLetter()); assertFalse(FileSystem.LINUX.supportsDriveLetter()); assertFalse(FileSystem.MAC_OSX.supportsDriveLetter()); } @Test public void testToLegalFileNameWindows() { final FileSystem fs = FileSystem.WINDOWS; final char replacement = '-'; for (char i = 0; i < 32; i++) { assertEquals(replacement, fs.toLegalFileName(String.valueOf(i), replacement).charAt(0)); } final char[] illegal = { '<', '>', ':', '"', '/', '\\', '|', '?', '*' }; for (char i = 0; i < illegal.length; i++) { assertEquals(replacement, fs.toLegalFileName(String.valueOf(i), replacement).charAt(0)); } for (char i = 'a'; i < 'z'; i++) { assertEquals(i, fs.toLegalFileName(String.valueOf(i), replacement).charAt(0)); } for (char i = 'A'; i < 'Z'; i++) { assertEquals(i, fs.toLegalFileName(String.valueOf(i), replacement).charAt(0)); } for (char i = '0'; i < '9'; i++) { assertEquals(i, fs.toLegalFileName(String.valueOf(i), replacement).charAt(0)); } } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/FileSystemUtilsTestCase.java0100644 0000000 0000000 00000063251 13612062727 031201 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.fail; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.time.Duration; import java.util.Locale; import org.junit.jupiter.api.Test; /** * This is used to test FileSystemUtils. * */ @SuppressWarnings("deprecation") // testing deprecated class public class FileSystemUtilsTestCase { private static final Duration NEG_1_TIMEOUT = Duration.ofMillis(-1); @Test public void testGetFreeSpace_String() throws Exception { // test coverage, as we can't check value if (File.separatorChar == '/') { // have to figure out unix block size final String[] cmd; String osName = System.getProperty("os.name"); osName = osName.toLowerCase(Locale.ENGLISH); if (osName.contains("hp-ux") || osName.contains("aix")) { cmd = new String[]{"df", "-P", "/"}; } else if (osName.contains("sunos") || osName.contains("sun os") || osName.contains("solaris")) { cmd = new String[]{"/usr/xpg4/bin/df", "-P", "/"}; } else { cmd = new String[]{"df", "/"}; } final Process proc = Runtime.getRuntime().exec(cmd); boolean kilobyteBlock = true; try (BufferedReader r = new BufferedReader(new InputStreamReader(proc.getInputStream()))){ final String line = r.readLine(); assertNotNull("Unexpected null line", line); if (line.contains("512")) { kilobyteBlock = false; } } // now perform the test final long free = FileSystemUtils.freeSpace("/"); final long kb = FileSystemUtils.freeSpaceKb("/"); // Assume disk space does not fluctuate // more than 1% between the above two calls; // this also also small enough to verify freeSpaceKb uses // kibibytes (1024) instead of SI kilobytes (1000) final double acceptableDelta = kb * 0.01d; if (kilobyteBlock) { assertEquals(free, kb, acceptableDelta); } else { assertEquals(free / 2d, kb, acceptableDelta); } } else { final long bytes = FileSystemUtils.freeSpace(""); final long kb = FileSystemUtils.freeSpaceKb(""); // Assume disk space does not fluctuate more than 1% final double acceptableDelta = kb * 0.01d; assertEquals((double) bytes / 1024, kb, acceptableDelta); } } @Test public void testGetFreeSpaceOS_String_NullPath() throws Exception { final FileSystemUtils fsu = new FileSystemUtils(); try { fsu.freeSpaceOS(null, 1, false, NEG_1_TIMEOUT); fail(); } catch (final IllegalArgumentException ignore) { } try { fsu.freeSpaceOS(null, 1, true, NEG_1_TIMEOUT); fail(); } catch (final IllegalArgumentException ignore) { } } @Test public void testGetFreeSpaceOS_String_InitError() throws Exception { final FileSystemUtils fsu = new FileSystemUtils(); try { fsu.freeSpaceOS("", -1, false, NEG_1_TIMEOUT); fail(); } catch (final IllegalStateException ignore) { } try { fsu.freeSpaceOS("", -1, true, NEG_1_TIMEOUT); fail(); } catch (final IllegalStateException ignore) { } } @Test public void testGetFreeSpaceOS_String_Other() throws Exception { final FileSystemUtils fsu = new FileSystemUtils(); try { fsu.freeSpaceOS("", 0, false, NEG_1_TIMEOUT); fail(); } catch (final IllegalStateException ignore) { } try { fsu.freeSpaceOS("", 0, true, NEG_1_TIMEOUT); fail(); } catch (final IllegalStateException ignore) { } } @Test public void testGetFreeSpaceOS_String_Windows() throws Exception { final FileSystemUtils fsu = new FileSystemUtils() { @Override protected long freeSpaceWindows(final String path, final Duration timeout) throws IOException { return 12345L; } }; assertEquals(12345L, fsu.freeSpaceOS("", 1, false, NEG_1_TIMEOUT)); assertEquals(12345L / 1024, fsu.freeSpaceOS("", 1, true, NEG_1_TIMEOUT)); } @Test public void testGetFreeSpaceOS_String_Unix() throws Exception { final FileSystemUtils fsu = new FileSystemUtils() { @Override protected long freeSpaceUnix(final String path, final boolean kb, final boolean posix, final Duration timeout) throws IOException { return kb ? 12345L : 54321; } }; assertEquals(54321L, fsu.freeSpaceOS("", 2, false, NEG_1_TIMEOUT)); assertEquals(12345L, fsu.freeSpaceOS("", 2, true, NEG_1_TIMEOUT)); } @Test public void testGetFreeSpaceWindows_String_ParseCommaFormatBytes() throws Exception { // this is the format of response when calling dir /c // we have now switched to dir /-c, so we should never get this final String lines = " Volume in drive C is HDD\n" + " Volume Serial Number is XXXX-YYYY\n" + "\n" + " Directory of C:\\Documents and Settings\\Xxxx\n" + "\n" + "19/08/2005 22:43 .\n" + "19/08/2005 22:43 ..\n" + "11/08/2005 01:07 81 build.properties\n" + "17/08/2005 21:44 Desktop\n" + " 7 File(s) 180,260 bytes\n" + " 10 Dir(s) 41,411,551,232 bytes free"; final FileSystemUtils fsu = new MockFileSystemUtils(0, lines); assertEquals(41411551232L, fsu.freeSpaceWindows("", NEG_1_TIMEOUT)); } @Test public void testGetFreeSpaceWindows_String_ParseCommaFormatBytes_Big() throws Exception { // test with very large free space final String lines = " Volume in drive C is HDD\n" + " Volume Serial Number is XXXX-YYYY\n" + "\n" + " Directory of C:\\Documents and Settings\\Xxxx\n" + "\n" + "19/08/2005 22:43 .\n" + "19/08/2005 22:43 ..\n" + "11/08/2005 01:07 81 build.properties\n" + "17/08/2005 21:44 Desktop\n" + " 7 File(s) 180,260 bytes\n" + " 10 Dir(s) 141,411,551,232 bytes free"; final FileSystemUtils fsu = new MockFileSystemUtils(0, lines); assertEquals(141411551232L, fsu.freeSpaceWindows("", NEG_1_TIMEOUT)); } @Test public void testGetFreeSpaceWindows_String_ParseCommaFormatBytes_Small() throws Exception { // test with very large free space final String lines = " Volume in drive C is HDD\n" + " Volume Serial Number is XXXX-YYYY\n" + "\n" + " Directory of C:\\Documents and Settings\\Xxxx\n" + "\n" + "19/08/2005 22:43 .\n" + "19/08/2005 22:43 ..\n" + "11/08/2005 01:07 81 build.properties\n" + "17/08/2005 21:44 Desktop\n" + " 7 File(s) 180,260 bytes\n" + " 10 Dir(s) 1,232 bytes free"; final FileSystemUtils fsu = new MockFileSystemUtils(0, lines); assertEquals(1232L, fsu.freeSpaceWindows("", NEG_1_TIMEOUT)); } @Test public void testGetFreeSpaceWindows_String_EmptyPath() throws Exception { final String lines = " Volume in drive C is HDD\n" + " Volume Serial Number is XXXX-YYYY\n" + "\n" + " Directory of C:\\Documents and Settings\\Xxxx\n" + "\n" + "19/08/2005 22:43 .\n" + "19/08/2005 22:43 ..\n" + "11/08/2005 01:07 81 build.properties\n" + "17/08/2005 21:44 Desktop\n" + " 7 File(s) 180260 bytes\n" + " 10 Dir(s) 41411551232 bytes free"; final FileSystemUtils fsu = new MockFileSystemUtils(0, lines, "dir /a /-c "); assertEquals(41411551232L, fsu.freeSpaceWindows("", NEG_1_TIMEOUT)); } @Test public void testGetFreeSpaceWindows_String_NormalResponse() throws Exception { final String lines = " Volume in drive C is HDD\n" + " Volume Serial Number is XXXX-YYYY\n" + "\n" + " Directory of C:\\Documents and Settings\\Xxxx\n" + "\n" + "19/08/2005 22:43 .\n" + "19/08/2005 22:43 ..\n" + "11/08/2005 01:07 81 build.properties\n" + "17/08/2005 21:44 Desktop\n" + " 7 File(s) 180260 bytes\n" + " 10 Dir(s) 41411551232 bytes free"; final FileSystemUtils fsu = new MockFileSystemUtils(0, lines, "dir /a /-c \"C:\""); assertEquals(41411551232L, fsu.freeSpaceWindows("C:", NEG_1_TIMEOUT)); } @Test public void testGetFreeSpaceWindows_String_StripDrive() throws Exception { final String lines = " Volume in drive C is HDD\n" + " Volume Serial Number is XXXX-YYYY\n" + "\n" + " Directory of C:\\Documents and Settings\\Xxxx\n" + "\n" + "19/08/2005 22:43 .\n" + "19/08/2005 22:43 ..\n" + "11/08/2005 01:07 81 build.properties\n" + "17/08/2005 21:44 Desktop\n" + " 7 File(s) 180260 bytes\n" + " 10 Dir(s) 41411551232 bytes free"; final FileSystemUtils fsu = new MockFileSystemUtils(0, lines, "dir /a /-c \"C:\\somedir\""); assertEquals(41411551232L, fsu.freeSpaceWindows("C:\\somedir", NEG_1_TIMEOUT)); } @Test public void testGetFreeSpaceWindows_String_quoted() throws Exception { final String lines = " Volume in drive C is HDD\n" + " Volume Serial Number is XXXX-YYYY\n" + "\n" + " Directory of C:\\Documents and Settings\\Xxxx\n" + "\n" + "19/08/2005 22:43 .\n" + "19/08/2005 22:43 ..\n" + "11/08/2005 01:07 81 build.properties\n" + "17/08/2005 21:44 Desktop\n" + " 7 File(s) 180260 bytes\n" + " 10 Dir(s) 41411551232 bytes free"; final FileSystemUtils fsu = new MockFileSystemUtils(0, lines, "dir /a /-c \"C:\\somedir\""); assertEquals(41411551232L, fsu.freeSpaceWindows("\"C:\\somedir\"", NEG_1_TIMEOUT)); } @Test public void testGetFreeSpaceWindows_String_EmptyResponse() { final String lines = ""; final FileSystemUtils fsu = new MockFileSystemUtils(0, lines); try { fsu.freeSpaceWindows("C:", NEG_1_TIMEOUT); fail(); } catch (final IOException ignore) { } } @Test public void testGetFreeSpaceWindows_String_EmptyMultiLineResponse() { final String lines = "\n\n"; final FileSystemUtils fsu = new MockFileSystemUtils(0, lines); assertThrows(IOException.class, () -> fsu.freeSpaceWindows("C:", NEG_1_TIMEOUT)); } @Test public void testGetFreeSpaceWindows_String_InvalidTextResponse() { final String lines = "BlueScreenOfDeath"; final FileSystemUtils fsu = new MockFileSystemUtils(0, lines); assertThrows(IOException.class, () -> fsu.freeSpaceWindows("C:", NEG_1_TIMEOUT)); } @Test public void testGetFreeSpaceWindows_String_NoSuchDirectoryResponse() { final String lines = " Volume in drive C is HDD\n" + " Volume Serial Number is XXXX-YYYY\n" + "\n" + " Directory of C:\\Documents and Settings\\empty" + "\n"; final FileSystemUtils fsu = new MockFileSystemUtils(1, lines); assertThrows(IOException.class, () -> fsu.freeSpaceWindows("C:", NEG_1_TIMEOUT)); } @Test public void testGetFreeSpaceUnix_String_EmptyPath() throws Exception { final String lines = "Filesystem 1K-blocks Used Available Use% Mounted on\n" + "xxx:/home/users/s 14428928 12956424 1472504 90% /home/users/s"; final FileSystemUtils fsu = new MockFileSystemUtils(0, lines); try { fsu.freeSpaceUnix("", false, false, NEG_1_TIMEOUT); fail(); } catch (final IllegalArgumentException ignore) { } try { fsu.freeSpaceUnix("", true, false, NEG_1_TIMEOUT); fail(); } catch (final IllegalArgumentException ignore) { } try { fsu.freeSpaceUnix("", true, true, NEG_1_TIMEOUT); fail(); } catch (final IllegalArgumentException ignore) { } try { fsu.freeSpaceUnix("", false, true, NEG_1_TIMEOUT); fail(); } catch (final IllegalArgumentException ignore) { } } @Test public void testGetFreeSpaceUnix_String_NormalResponseLinux() throws Exception { // from Sourceforge 'GNU bash, version 2.05b.0(1)-release (i386-redhat-linux-gnu)' final String lines = "Filesystem 1K-blocks Used Available Use% Mounted on\n" + "/dev/xxx 497944 308528 189416 62% /"; final FileSystemUtils fsu = new MockFileSystemUtils(0, lines); assertEquals(189416L, fsu.freeSpaceUnix("/", false, false, NEG_1_TIMEOUT)); } @Test public void testGetFreeSpaceUnix_String_NormalResponseFreeBSD() throws Exception { // from Apache 'FreeBSD 6.1-RELEASE (SMP-turbo)' final String lines = "Filesystem 1K-blocks Used Avail Capacity Mounted on\n" + "/dev/xxxxxx 128990 102902 15770 87% /"; final FileSystemUtils fsu = new MockFileSystemUtils(0, lines); assertEquals(15770L, fsu.freeSpaceUnix("/", false, false, NEG_1_TIMEOUT)); } @Test public void testGetFreeSpaceUnix_String_NormalResponseKbLinux() throws Exception { // from Sourceforge 'GNU bash, version 2.05b.0(1)-release (i386-redhat-linux-gnu)' // df, df -k and df -kP are all identical final String lines = "Filesystem 1K-blocks Used Available Use% Mounted on\n" + "/dev/xxx 497944 308528 189416 62% /"; final FileSystemUtils fsu = new MockFileSystemUtils(0, lines); assertEquals(189416L, fsu.freeSpaceUnix("/", true, false, NEG_1_TIMEOUT)); } @Test public void testGetFreeSpaceUnix_String_NormalResponseKbFreeBSD() throws Exception { // from Apache 'FreeBSD 6.1-RELEASE (SMP-turbo)' // df and df -k are identical, but df -kP uses 512 blocks (not relevant as not used) final String lines = "Filesystem 1K-blocks Used Avail Capacity Mounted on\n" + "/dev/xxxxxx 128990 102902 15770 87% /"; final FileSystemUtils fsu = new MockFileSystemUtils(0, lines); assertEquals(15770L, fsu.freeSpaceUnix("/", true, false, NEG_1_TIMEOUT)); } @Test public void testGetFreeSpaceUnix_String_NormalResponseKbSolaris() throws Exception { // from IO-91 - ' SunOS et 5.10 Generic_118822-25 sun4u sparc SUNW,Ultra-4' // non-kb response does not contain free space - see IO-91 final String lines = "Filesystem kbytes used avail capacity Mounted on\n" + "/dev/dsk/x0x0x0x0 1350955 815754 481163 63%"; final FileSystemUtils fsu = new MockFileSystemUtils(0, lines); assertEquals(481163L, fsu.freeSpaceUnix("/dev/dsk/x0x0x0x0", true, false, NEG_1_TIMEOUT)); } @Test public void testGetFreeSpaceUnix_String_LongResponse() throws Exception { final String lines = "Filesystem 1K-blocks Used Available Use% Mounted on\n" + "xxx-yyyyyyy-zzz:/home/users/s\n" + " 14428928 12956424 1472504 90% /home/users/s"; final FileSystemUtils fsu = new MockFileSystemUtils(0, lines); assertEquals(1472504L, fsu.freeSpaceUnix("/home/users/s", false, false, NEG_1_TIMEOUT)); } @Test public void testGetFreeSpaceUnix_String_LongResponseKb() throws Exception { final String lines = "Filesystem 1K-blocks Used Available Use% Mounted on\n" + "xxx-yyyyyyy-zzz:/home/users/s\n" + " 14428928 12956424 1472504 90% /home/users/s"; final FileSystemUtils fsu = new MockFileSystemUtils(0, lines); assertEquals(1472504L, fsu.freeSpaceUnix("/home/users/s", true, false, NEG_1_TIMEOUT)); } @Test public void testGetFreeSpaceUnix_String_EmptyResponse() { final String lines = ""; final FileSystemUtils fsu = new MockFileSystemUtils(0, lines); try { fsu.freeSpaceUnix("/home/users/s", false, false, NEG_1_TIMEOUT); fail(); } catch (final IOException ignore) { } try { fsu.freeSpaceUnix("/home/users/s", true, false, NEG_1_TIMEOUT); fail(); } catch (final IOException ignore) { } try { fsu.freeSpaceUnix("/home/users/s", false, true, NEG_1_TIMEOUT); fail(); } catch (final IOException ignore) { } try { fsu.freeSpaceUnix("/home/users/s", true, true, NEG_1_TIMEOUT); fail(); } catch (final IOException ignore) { } } @Test public void testGetFreeSpaceUnix_String_InvalidResponse1() { final String lines = "Filesystem 1K-blocks Used Available Use% Mounted on\n" + " 14428928 12956424 100"; final FileSystemUtils fsu = new MockFileSystemUtils(0, lines); try { fsu.freeSpaceUnix("/home/users/s", false, false, NEG_1_TIMEOUT); fail(); } catch (final IOException ignore) { } try { fsu.freeSpaceUnix("/home/users/s", true, false, NEG_1_TIMEOUT); fail(); } catch (final IOException ignore) { } try { fsu.freeSpaceUnix("/home/users/s", false, true, NEG_1_TIMEOUT); fail(); } catch (final IOException ignore) { } try { fsu.freeSpaceUnix("/home/users/s", true, true, NEG_1_TIMEOUT); fail(); } catch (final IOException ignore) { } } @Test public void testGetFreeSpaceUnix_String_InvalidResponse2() { final String lines = "Filesystem 1K-blocks Used Available Use% Mounted on\n" + "xxx:/home/users/s 14428928 12956424 nnnnnnn 90% /home/users/s"; final FileSystemUtils fsu = new MockFileSystemUtils(0, lines); try { fsu.freeSpaceUnix("/home/users/s", false, false, NEG_1_TIMEOUT); fail(); } catch (final IOException ignore) { } try { fsu.freeSpaceUnix("/home/users/s", true, false, NEG_1_TIMEOUT); fail(); } catch (final IOException ignore) { } try { fsu.freeSpaceUnix("/home/users/s", false, true, NEG_1_TIMEOUT); fail(); } catch (final IOException ignore) { } try { fsu.freeSpaceUnix("/home/users/s", true, true, NEG_1_TIMEOUT); fail(); } catch (final IOException ignore) { } } @Test public void testGetFreeSpaceUnix_String_InvalidResponse3() { final String lines = "Filesystem 1K-blocks Used Available Use% Mounted on\n" + "xxx:/home/users/s 14428928 12956424 -1 90% /home/users/s"; final FileSystemUtils fsu = new MockFileSystemUtils(0, lines); try { fsu.freeSpaceUnix("/home/users/s", false, false, NEG_1_TIMEOUT); fail(); } catch (final IOException ignore) { } try { fsu.freeSpaceUnix("/home/users/s", true, false, NEG_1_TIMEOUT); fail(); } catch (final IOException ignore) { } try { fsu.freeSpaceUnix("/home/users/s", false, true, NEG_1_TIMEOUT); fail(); } catch (final IOException ignore) { } try { fsu.freeSpaceUnix("/home/users/s", true, true, NEG_1_TIMEOUT); fail(); } catch (final IOException ignore) { } } @Test public void testGetFreeSpaceUnix_String_InvalidResponse4() { final String lines = "Filesystem 1K-blocks Used Available Use% Mounted on\n" + "xxx-yyyyyyy-zzz:/home/users/s"; final FileSystemUtils fsu = new MockFileSystemUtils(0, lines); try { fsu.freeSpaceUnix("/home/users/s", false, false, NEG_1_TIMEOUT); fail(); } catch (final IOException ignore) { } try { fsu.freeSpaceUnix("/home/users/s", true, false, NEG_1_TIMEOUT); fail(); } catch (final IOException ignore) { } try { fsu.freeSpaceUnix("/home/users/s", false, true, NEG_1_TIMEOUT); fail(); } catch (final IOException ignore) { } try { fsu.freeSpaceUnix("/home/users/s", true, true, NEG_1_TIMEOUT); fail(); } catch (final IOException ignore) { } } static class MockFileSystemUtils extends FileSystemUtils { private final int exitCode; private final byte[] bytes; private final String cmd; public MockFileSystemUtils(final int exitCode, final String lines) { this(exitCode, lines, null); } public MockFileSystemUtils(final int exitCode, final String lines, final String cmd) { this.exitCode = exitCode; this.bytes = lines.getBytes(); this.cmd = cmd; } @Override Process openProcess(final String[] params) { if (cmd != null) { assertEquals(cmd, params[params.length - 1]); } return new Process() { @Override public InputStream getErrorStream() { return null; } @Override public InputStream getInputStream() { return new ByteArrayInputStream(bytes); } @Override public OutputStream getOutputStream() { return null; } @Override public int waitFor() throws InterruptedException { return exitCode; } @Override public int exitValue() { return exitCode; } @Override public void destroy() { } }; } } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/FileUtilsCleanDirectoryTestCase.java0100644 0000000 0000000 00000010623 13612062727 032617 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.Assumptions.assumeTrue; import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.util.ArrayList; import java.util.List; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.DisabledOnOs; import org.junit.jupiter.api.condition.OS; import org.junit.jupiter.api.io.TempDir; /** * Test cases for FileUtils.cleanDirectory() method. * * TODO Redo this test using * {@link Files#createSymbolicLink(java.nio.file.Path, java.nio.file.Path, java.nio.file.attribute.FileAttribute...)}. */ public class FileUtilsCleanDirectoryTestCase { @TempDir public File top; // ----------------------------------------------------------------------- @Test public void testCleanEmpty() throws Exception { assertEquals(0, top.list().length); FileUtils.cleanDirectory(top); assertEquals(0, top.list().length); } @Test public void testDeletesRegular() throws Exception { FileUtils.touch(new File(top, "regular")); FileUtils.touch(new File(top, ".hidden")); assertEquals(2, top.list().length); FileUtils.cleanDirectory(top); assertEquals(0, top.list().length); } @Test public void testDeletesNested() throws Exception { final File nested = new File(top, "nested"); assertTrue(nested.mkdirs()); FileUtils.touch(new File(nested, "file")); assertEquals(1, top.list().length); FileUtils.cleanDirectory(top); assertEquals(0, top.list().length); } @DisabledOnOs(OS.WINDOWS) @Test public void testThrowsOnNullList() throws Exception { // test wont work if we can't restrict permissions on the // directory, so skip it. assumeTrue(chmod(top, 0, false)); try { // cleanDirectory calls forceDelete FileUtils.cleanDirectory(top); fail("expected IOException"); } catch (final IOException e) { assertEquals("Unknown I/O error listing contents of directory: " + top.getAbsolutePath(), e.getMessage()); } finally { chmod(top, 755, false); } } @DisabledOnOs(OS.WINDOWS) @Test public void testThrowsOnCannotDeleteFile() throws Exception { final File file = new File(top, "restricted"); FileUtils.touch(file); assumeTrue(chmod(top, 500, false)); try { // cleanDirectory calls forceDelete FileUtils.cleanDirectory(top); fail("expected IOException"); } catch (final IOException e) { final IOExceptionList list = (IOExceptionList) e; assertEquals("Cannot delete file: " + file.getAbsolutePath(), list.getCause(0).getMessage()); } finally { chmod(top, 755, false); } } /** Only runs on Linux. */ private boolean chmod(final File file, final int mode, final boolean recurse) throws InterruptedException { final List args = new ArrayList<>(); args.add("chmod"); if (recurse) { args.add("-R"); } args.add(Integer.toString(mode)); args.add(file.getAbsolutePath()); final Process proc; try { proc = Runtime.getRuntime().exec(args.toArray(new String[args.size()])); } catch (final IOException e) { return false; } return proc.waitFor() == 0; } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/FileUtilsCleanSymlinksTestCase.java0100644 0000000 0000000 00000023010 13612062727 032456 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.File; import java.util.ArrayList; import java.util.List; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; /** * Test cases for FileUtils.cleanDirectory() method that involve symlinks. * & FileUtils.isSymlink(File file) */ public class FileUtilsCleanSymlinksTestCase { @TempDir public File top; @Test public void testCleanDirWithSymlinkFile() throws Exception { if (System.getProperty("os.name").startsWith("Win")) { // Can't use "ln" for symlinks on the command line in Windows. return; } final File realOuter = new File(top, "realouter"); assertTrue(realOuter.mkdirs()); final File realInner = new File(realOuter, "realinner"); assertTrue(realInner.mkdirs()); final File realFile = new File(realInner, "file1"); FileUtils.touch(realFile); assertEquals(1, realInner.list().length); final File randomFile = new File(top, "randomfile"); FileUtils.touch(randomFile); final File symlinkFile = new File(realInner, "fakeinner"); assertTrue(setupSymlink(randomFile, symlinkFile)); assertEquals(2, realInner.list().length); // assert contents of the real directory were removed including the symlink FileUtils.cleanDirectory(realOuter); assertEquals(0, realOuter.list().length); // ensure that the contents of the symlink were NOT removed. assertTrue(randomFile.exists()); assertFalse(symlinkFile.exists()); } @Test public void testCleanDirWithASymlinkDir() throws Exception { if (System.getProperty("os.name").startsWith("Win")) { // Can't use "ln" for symlinks on the command line in Windows. return; } final File realOuter = new File(top, "realouter"); assertTrue(realOuter.mkdirs()); final File realInner = new File(realOuter, "realinner"); assertTrue(realInner.mkdirs()); FileUtils.touch(new File(realInner, "file1")); assertEquals(1, realInner.list().length); final File randomDirectory = new File(top, "randomDir"); assertTrue(randomDirectory.mkdirs()); FileUtils.touch(new File(randomDirectory, "randomfile")); assertEquals(1, randomDirectory.list().length); final File symlinkDirectory = new File(realOuter, "fakeinner"); assertTrue(setupSymlink(randomDirectory, symlinkDirectory)); assertEquals(1, symlinkDirectory.list().length); // assert contents of the real directory were removed including the symlink FileUtils.cleanDirectory(realOuter); assertEquals(0, realOuter.list().length); // ensure that the contents of the symlink were NOT removed. assertEquals(1, randomDirectory.list().length, "Contents of sym link should not have been removed"); } @Test public void testCleanDirWithParentSymlinks() throws Exception { if (System.getProperty("os.name").startsWith("Win")) { // Can't use "ln" for symlinks on the command line in Windows. return; } final File realParent = new File(top, "realparent"); assertTrue(realParent.mkdirs()); final File realInner = new File(realParent, "realinner"); assertTrue(realInner.mkdirs()); FileUtils.touch(new File(realInner, "file1")); assertEquals(1, realInner.list().length); final File randomDirectory = new File(top, "randomDir"); assertTrue(randomDirectory.mkdirs()); FileUtils.touch(new File(randomDirectory, "randomfile")); assertEquals(1, randomDirectory.list().length); final File symlinkDirectory = new File(realParent, "fakeinner"); assertTrue(setupSymlink(randomDirectory, symlinkDirectory)); assertEquals(1, symlinkDirectory.list().length); final File symlinkParentDirectory = new File(top, "fakeouter"); assertTrue(setupSymlink(realParent, symlinkParentDirectory)); // assert contents of the real directory were removed including the symlink FileUtils.cleanDirectory(symlinkParentDirectory);// should clean the contents of this but not recurse into other links assertEquals(0, symlinkParentDirectory.list().length); assertEquals(0, realParent.list().length); // ensure that the contents of the symlink were NOT removed. assertEquals(1, randomDirectory.list().length, "Contents of sym link should not have been removed"); } @Test public void testStillClearsIfGivenDirectoryIsASymlink() throws Exception { if (System.getProperty("os.name").startsWith("Win")) { // Can't use "ln" for symlinks on the command line in Windows. return; } final File randomDirectory = new File(top, "randomDir"); assertTrue(randomDirectory.mkdirs()); FileUtils.touch(new File(randomDirectory, "randomfile")); assertEquals(1, randomDirectory.list().length); final File symlinkDirectory = new File(top, "fakeDir"); assertTrue(setupSymlink(randomDirectory, symlinkDirectory)); FileUtils.cleanDirectory(symlinkDirectory); assertEquals(0, symlinkDirectory.list().length); assertEquals(0, randomDirectory.list().length); } @Test public void testIdentifiesSymlinkDir() throws Exception { if (System.getProperty("os.name").startsWith("Win")) { // Can't use "ln" for symlinks on the command line in Windows. return; } final File randomDirectory = new File(top, "randomDir"); assertTrue(randomDirectory.mkdirs()); final File symlinkDirectory = new File(top, "fakeDir"); assertTrue(setupSymlink(randomDirectory, symlinkDirectory)); assertTrue(FileUtils.isSymlink(symlinkDirectory)); assertFalse(FileUtils.isSymlink(randomDirectory)); } @Test public void testIdentifiesSymlinkFile() throws Exception { if (System.getProperty("os.name").startsWith("Win")) { // Can't use "ln" for symlinks on the command line in Windows. return; } final File randomFile = new File(top, "randomfile"); FileUtils.touch(randomFile); final File symlinkFile = new File(top, "fakeinner"); assertTrue(setupSymlink(randomFile, symlinkFile)); assertTrue(FileUtils.isSymlink(symlinkFile)); assertFalse(FileUtils.isSymlink(randomFile)); } @Test public void testIdentifiesBrokenSymlinkFile() throws Exception { if (System.getProperty("os.name").startsWith("Win")) { // Can't use "ln" for symlinks on the command line in Windows. return; } final File noexistFile = new File(top, "noexist"); final File symlinkFile = new File(top, "fakeinner"); final File badSymlinkInPathFile = new File(symlinkFile, "fakeinner"); final File noexistParentFile = new File("noexist", "file"); assertTrue(setupSymlink(noexistFile, symlinkFile)); assertTrue(FileUtils.isSymlink(symlinkFile)); assertFalse(FileUtils.isSymlink(noexistFile)); assertFalse(FileUtils.isSymlink(noexistParentFile)); assertFalse(FileUtils.isSymlink(badSymlinkInPathFile)); } @Test public void testCorrectlyIdentifySymlinkWithParentSymLink() throws Exception { if (System.getProperty("os.name").startsWith("Win")) { // Can't use "ln" for symlinks on the command line in Windows. return; } final File realParent = new File(top, "realparent"); assertTrue(realParent.mkdirs()); final File symlinkParentDirectory = new File(top, "fakeparent"); assertTrue(setupSymlink(realParent, symlinkParentDirectory)); final File realChild = new File(symlinkParentDirectory, "realChild"); assertTrue(realChild.mkdirs()); final File symlinkChild = new File(symlinkParentDirectory, "fakeChild"); assertTrue(setupSymlink(realChild, symlinkChild)); assertTrue(FileUtils.isSymlink(symlinkChild)); assertFalse(FileUtils.isSymlink(realChild)); } private boolean setupSymlink(final File res, final File link) throws Exception { // create symlink final List args = new ArrayList<>(); args.add("ln"); args.add("-s"); args.add(res.getAbsolutePath()); args.add(link.getAbsolutePath()); final Process proc; proc = Runtime.getRuntime().exec(args.toArray(new String[args.size()])); return proc.waitFor() == 0; } } ././@LongLink0100644 0000000 0000000 00000000151 13612062727 011636 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/java/org/apache/commons/io/FileUtilsCopyDirectoryToDirectoryTestCase.javacommons-io-2.11.0-src/src/test/java/org/apache/commons/io/FileUtilsCopyDirectoryToDirectoryTestCase.0100644 0000000 0000000 00000012167 13612062727 034042 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import org.apache.commons.io.file.PathUtils; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; /** * This class ensure the correctness of {@link FileUtils#copyDirectoryToDirectory(File, File)}. TODO: currently does not * cover happy cases * * @see FileUtils#copyDirectoryToDirectory(File, File) */ public class FileUtilsCopyDirectoryToDirectoryTestCase { private static void assertExceptionTypeAndMessage(final File srcDir, final File destDir, final Class expectedExceptionType, final String expectedMessage) { try { FileUtils.copyDirectoryToDirectory(srcDir, destDir); } catch (final Exception e) { final String msg = e.getMessage(); assertEquals(expectedExceptionType, e.getClass()); assertEquals(expectedMessage, msg); return; } fail(); } /** Temporary folder managed by JUnit. */ @TempDir public File temporaryFolder; private void assertAclEntryList(final Path sourcePath, final Path destPath) throws IOException { assertEquals(PathUtils.getAclEntryList(sourcePath), PathUtils.getAclEntryList(destPath)); } @Test public void copyDirectoryToDirectoryThrowsIllegalArgumentExceptionWithCorrectMessageWhenDstDirIsNotDirectory() throws IOException { final File srcDir = new File(temporaryFolder, "sourceDirectory"); srcDir.mkdir(); final File destDir = new File(temporaryFolder, "notadirectory"); destDir.createNewFile(); final String expectedMessage = String.format("Parameter 'destinationDir' is not a directory: '%s'", destDir); assertExceptionTypeAndMessage(srcDir, destDir, IllegalArgumentException.class, expectedMessage); } @Test public void copyDirectoryToDirectoryThrowsIllegalExceptionWithCorrectMessageWhenSrcDirIsNotDirectory() throws IOException { final File srcDir = File.createTempFile("notadireotry", null, temporaryFolder); final File destDir = new File(temporaryFolder, "destinationDirectory"); destDir.mkdirs(); final String expectedMessage = String.format("Parameter 'sourceDir' is not a directory: '%s'", srcDir); assertExceptionTypeAndMessage(srcDir, destDir, IllegalArgumentException.class, expectedMessage); } @Test public void copyDirectoryToDirectoryThrowsNullPointerExceptionWithCorrectMessageWhenDstDirIsNull() { final File srcDir = new File(temporaryFolder, "sourceDirectory"); srcDir.mkdir(); final File destDir = null; assertExceptionTypeAndMessage(srcDir, destDir, NullPointerException.class, "destinationDir"); } @Test public void copyDirectoryToDirectoryThrowsNullPointerExceptionWithCorrectMessageWhenSrcDirIsNull() { final File srcDir = null; final File destinationDirectory = new File(temporaryFolder, "destinationDirectory"); destinationDirectory.mkdir(); assertExceptionTypeAndMessage(srcDir, destinationDirectory, NullPointerException.class, "sourceDir"); } @Test public void copyFileAndCheckAcl() throws IOException { final Path sourcePath = Files.createTempFile("TempOutput", ".bin"); final Path destPath = Paths.get(temporaryFolder.getAbsolutePath(), "SomeFile.bin"); // Test copy attributes without replace FIRST. FileUtils.copyFile(sourcePath.toFile(), destPath.toFile(), true, StandardCopyOption.COPY_ATTRIBUTES); assertAclEntryList(sourcePath, destPath); // FileUtils.copyFile(sourcePath.toFile(), destPath.toFile()); assertAclEntryList(sourcePath, destPath); // FileUtils.copyFile(sourcePath.toFile(), destPath.toFile(), true, StandardCopyOption.REPLACE_EXISTING); assertAclEntryList(sourcePath, destPath); // FileUtils.copyFile(sourcePath.toFile(), destPath.toFile(), true, StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.COPY_ATTRIBUTES); assertAclEntryList(sourcePath, destPath); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/FileUtilsCopyToFileTestCase.java0100644 0000000 0000000 00000006454 13612062727 031734 0ustar00rootroot0000000 0000000 /* Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import org.apache.commons.io.test.TestUtils; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; /** * This is used to test FileUtils for correctness. */ public class FileUtilsCopyToFileTestCase { @TempDir public File temporaryFolder; private File testFile; private byte[] testData; @BeforeEach public void setUp() throws Exception { testFile = new File(temporaryFolder, "file1-test.txt"); if(!testFile.getParentFile().exists()) { throw new IOException("Cannot create file " + testFile + " as the parent directory does not exist"); } testData = TestUtils.generateTestData(1024); } /** * Tests that {@code copyToFile(InputStream, File)} does not close the input stream. * * @throws IOException * @see FileUtils#copyToFile(InputStream, File) * @see FileUtils#copyInputStreamToFile(InputStream, File) */ @Test public void testCopyToFile() throws IOException { try(CheckingInputStream inputStream = new CheckingInputStream(testData)) { FileUtils.copyToFile(inputStream, testFile); assertFalse(inputStream.isClosed(), "inputStream should NOT be closed"); } } /** * Tests that {@code copyInputStreamToFile(InputStream, File)} closes the input stream. * * @throws IOException * @see FileUtils#copyInputStreamToFile(InputStream, File) * @see FileUtils#copyToFile(InputStream, File) */ @Test public void testCopyInputStreamToFile() throws IOException { try(CheckingInputStream inputStream = new CheckingInputStream(testData)) { FileUtils.copyInputStreamToFile(inputStream, testFile); assertTrue(inputStream.isClosed(), "inputStream should be closed"); } } private class CheckingInputStream extends ByteArrayInputStream { private boolean closed; public CheckingInputStream(final byte[] data) { super(data); closed = false; } @Override public void close() throws IOException { super.close(); closed = true; } public boolean isClosed() { return closed; } } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/FileUtilsDeleteDirectoryBaseTestCase.java0100644 0000000 0000000 00000021730 13612062727 033573 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.File; import java.nio.file.Files; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; /** * Test cases for FileUtils.deleteDirectory() method. * */ public abstract class FileUtilsDeleteDirectoryBaseTestCase { @TempDir public File top; protected abstract boolean setupSymlink(final File res, final File link) throws Exception; @Test public void testDeleteDirWithASymlinkDir() throws Exception { final File realOuter = new File(top, "realouter"); assertTrue(realOuter.mkdirs()); final File realInner = new File(realOuter, "realinner"); assertTrue(realInner.mkdirs()); FileUtils.touch(new File(realInner, "file1")); assertEquals(1, realInner.list().length); final File randomDirectory = new File(top, "randomDir"); assertTrue(randomDirectory.mkdirs()); FileUtils.touch(new File(randomDirectory, "randomfile")); assertEquals(1, randomDirectory.list().length); final File symlinkDirectory = new File(realOuter, "fakeinner"); assertTrue(setupSymlink(randomDirectory, symlinkDirectory)); assertEquals(1, symlinkDirectory.list().length); // assert contents of the real directory were removed including the symlink FileUtils.deleteDirectory(realOuter); assertEquals(1, top.list().length); // ensure that the contents of the symlink were NOT removed. assertEquals(1, randomDirectory.list().length, "Contents of sym link should not have been removed"); } @Test public void testDeleteDirWithASymlinkDir2() throws Exception { final File realOuter = new File(top, "realouter"); assertTrue(realOuter.mkdirs()); final File realInner = new File(realOuter, "realinner"); assertTrue(realInner.mkdirs()); FileUtils.touch(new File(realInner, "file1")); assertEquals(1, realInner.list().length); final File randomDirectory = new File(top, "randomDir"); assertTrue(randomDirectory.mkdirs()); FileUtils.touch(new File(randomDirectory, "randomfile")); assertEquals(1, randomDirectory.list().length); final File symlinkDirectory = new File(realOuter, "fakeinner"); Files.createSymbolicLink(symlinkDirectory.toPath(), randomDirectory.toPath()); assertEquals(1, symlinkDirectory.list().length); // assert contents of the real directory were removed including the symlink FileUtils.deleteDirectory(realOuter); assertEquals(1, top.list().length); // ensure that the contents of the symlink were NOT removed. assertEquals(1, randomDirectory.list().length, "Contents of sym link should not have been removed"); } @Test public void testDeleteDirWithSymlinkFile() throws Exception { final File realOuter = new File(top, "realouter"); assertTrue(realOuter.mkdirs()); final File realInner = new File(realOuter, "realinner"); assertTrue(realInner.mkdirs()); final File realFile = new File(realInner, "file1"); FileUtils.touch(realFile); assertEquals(1, realInner.list().length); final File randomFile = new File(top, "randomfile"); FileUtils.touch(randomFile); final File symlinkFile = new File(realInner, "fakeinner"); assertTrue(setupSymlink(randomFile, symlinkFile)); assertEquals(2, realInner.list().length); assertEquals(2, top.list().length); // assert the real directory were removed including the symlink FileUtils.deleteDirectory(realOuter); assertEquals(1, top.list().length); // ensure that the contents of the symlink were NOT removed. assertTrue(randomFile.exists()); assertFalse(symlinkFile.exists()); } @Test public void testDeleteInvalidLinks() throws Exception { final File aFile = new File(top, "realParentDirA"); assertTrue(aFile.mkdir()); final File bFile = new File(aFile, "realChildDirB"); assertTrue(bFile.mkdir()); final File cFile = new File(top, "realParentDirC"); assertTrue(cFile.mkdir()); final File dFile = new File(cFile, "realChildDirD"); assertTrue(dFile.mkdir()); final File linkToC = new File(bFile, "linkToC"); Files.createSymbolicLink(linkToC.toPath(), cFile.toPath()); final File linkToB = new File(dFile, "linkToB"); Files.createSymbolicLink(linkToB.toPath(), bFile.toPath()); FileUtils.deleteDirectory(aFile); FileUtils.deleteDirectory(cFile); assertEquals(0, top.list().length); } @Test public void testDeleteParentSymlink() throws Exception { final File realParent = new File(top, "realparent"); assertTrue(realParent.mkdirs()); final File realInner = new File(realParent, "realinner"); assertTrue(realInner.mkdirs()); FileUtils.touch(new File(realInner, "file1")); assertEquals(1, realInner.list().length); final File randomDirectory = new File(top, "randomDir"); assertTrue(randomDirectory.mkdirs()); FileUtils.touch(new File(randomDirectory, "randomfile")); assertEquals(1, randomDirectory.list().length); final File symlinkDirectory = new File(realParent, "fakeinner"); assertTrue(setupSymlink(randomDirectory, symlinkDirectory)); assertEquals(1, symlinkDirectory.list().length); final File symlinkParentDirectory = new File(top, "fakeouter"); assertTrue(setupSymlink(realParent, symlinkParentDirectory)); // assert only the symlink is deleted, but not followed FileUtils.deleteDirectory(symlinkParentDirectory); assertEquals(2, top.list().length); // ensure that the contents of the symlink were NOT removed. assertEquals(1, randomDirectory.list().length, "Contents of sym link should not have been removed"); } @Test public void testDeleteParentSymlink2() throws Exception { final File realParent = new File(top, "realparent"); assertTrue(realParent.mkdirs()); final File realInner = new File(realParent, "realinner"); assertTrue(realInner.mkdirs()); FileUtils.touch(new File(realInner, "file1")); assertEquals(1, realInner.list().length); final File randomDirectory = new File(top, "randomDir"); assertTrue(randomDirectory.mkdirs()); FileUtils.touch(new File(randomDirectory, "randomfile")); assertEquals(1, randomDirectory.list().length); final File symlinkDirectory = new File(realParent, "fakeinner"); Files.createSymbolicLink(symlinkDirectory.toPath(), randomDirectory.toPath()); assertEquals(1, symlinkDirectory.list().length); final File symlinkParentDirectory = new File(top, "fakeouter"); Files.createSymbolicLink(symlinkParentDirectory.toPath(), realParent.toPath()); // assert only the symlink is deleted, but not followed FileUtils.deleteDirectory(symlinkParentDirectory); assertEquals(2, top.list().length); // ensure that the contents of the symlink were NOT removed. assertEquals(1, randomDirectory.list().length, "Contents of sym link should not have been removed"); } @Test public void testDeletesNested() throws Exception { final File nested = new File(top, "nested"); assertTrue(nested.mkdirs()); assertEquals(1, top.list().length); FileUtils.touch(new File(nested, "regular")); FileUtils.touch(new File(nested, ".hidden")); assertEquals(2, nested.list().length); FileUtils.deleteDirectory(nested); assertEquals(0, top.list().length); } @Test public void testDeletesRegular() throws Exception { final File nested = new File(top, "nested"); assertTrue(nested.mkdirs()); assertEquals(1, top.list().length); assertEquals(0, nested.list().length); FileUtils.deleteDirectory(nested); assertEquals(0, top.list().length); } } ././@LongLink0100644 0000000 0000000 00000000145 13612062727 011641 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/java/org/apache/commons/io/FileUtilsDeleteDirectoryLinuxTestCase.javacommons-io-2.11.0-src/src/test/java/org/apache/commons/io/FileUtilsDeleteDirectoryLinuxTestCase.java0100644 0000000 0000000 00000007214 13612062727 034021 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.Assumptions.assumeTrue; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.DisabledOnOs; import org.junit.jupiter.api.condition.OS; @DisabledOnOs({OS.WINDOWS, OS.MAC}) public class FileUtilsDeleteDirectoryLinuxTestCase extends FileUtilsDeleteDirectoryBaseTestCase { /** Only runs on Linux. */ private boolean chmod(final File file, final int mode, final boolean recurse) throws InterruptedException { final List args = new ArrayList<>(); args.add("chmod"); if (recurse) { args.add("-R"); } args.add(Integer.toString(mode)); args.add(file.getAbsolutePath()); final Process proc; try { proc = Runtime.getRuntime().exec(args.toArray(new String[args.size()])); } catch (final IOException e) { return false; } return proc.waitFor() == 0; } @Override protected boolean setupSymlink(final File res, final File link) throws Exception { // create symlink final List args = new ArrayList<>(); args.add("ln"); args.add("-s"); args.add(res.getAbsolutePath()); args.add(link.getAbsolutePath()); final Process proc; proc = Runtime.getRuntime().exec(args.toArray(new String[args.size()])); return proc.waitFor() == 0; } @Test public void testThrowsOnCannotDeleteFile() throws Exception { final File nested = new File(top, "nested"); assertTrue(nested.mkdirs()); final File file = new File(nested, "restricted"); FileUtils.touch(file); assumeTrue(chmod(nested, 500, false)); try { // deleteDirectory calls forceDelete FileUtils.deleteDirectory(nested); fail("expected IOException"); } catch (final IOException e) { final IOExceptionList list = (IOExceptionList) e; assertEquals("Cannot delete file: " + file.getAbsolutePath(), list.getCause(0).getMessage()); } finally { chmod(nested, 755, false); FileUtils.deleteDirectory(nested); } assertEquals(0, top.list().length); } @Test public void testThrowsOnNullList() throws Exception { final File nested = new File(top, "nested"); assertTrue(nested.mkdirs()); // test wont work if we can't restrict permissions on the // directory, so skip it. assumeTrue(chmod(nested, 0, false)); try { // cleanDirectory calls forceDelete FileUtils.deleteDirectory(nested); fail("expected IOException"); } catch (final IOException e) { assertEquals("Unknown I/O error listing contents of directory: " + nested.getAbsolutePath(), e.getMessage()); } finally { chmod(nested, 755, false); FileUtils.deleteDirectory(nested); } assertEquals(0, top.list().length); } } ././@LongLink0100644 0000000 0000000 00000000147 13612062727 011643 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/java/org/apache/commons/io/FileUtilsDeleteDirectoryWindowsTestCase.javacommons-io-2.11.0-src/src/test/java/org/apache/commons/io/FileUtilsDeleteDirectoryWindowsTestCase.ja0100644 0000000 0000000 00000004204 13612062727 034021 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import java.io.File; import java.io.InputStream; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.List; import org.junit.jupiter.api.condition.EnabledOnOs; import org.junit.jupiter.api.condition.OS; /** * Requires Windows admin karma or you get "You do not have sufficient privilege to perform this operation." */ @EnabledOnOs(OS.WINDOWS) public class FileUtilsDeleteDirectoryWindowsTestCase extends FileUtilsDeleteDirectoryBaseTestCase { @Override protected boolean setupSymlink(final File res, final File link) throws Exception { // create symlink final List args = new ArrayList<>(); args.add("cmd"); args.add("/C"); // Requires Windows admin karma or you get "You do not have sufficient privilege to perform this operation." args.add("mklink"); if (res.isDirectory()) { args.add("/D"); } args.add(link.getAbsolutePath()); args.add(res.getAbsolutePath()); final Process proc = Runtime.getRuntime().exec(args.toArray(new String[args.size()])); final InputStream errorStream = proc.getErrorStream(); final int rc = proc.waitFor(); System.err.print(IOUtils.toString(errorStream, Charset.defaultCharset())); System.err.flush(); return rc == 0; } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/FileUtilsDirectoryContainsTestCase.java0100644 0000000 0000000 00000014352 13612062727 033356 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import java.io.File; import java.io.IOException; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; /** * This class ensure the correctness of {@link FileUtils#directoryContains(File,File)}. * * @see FileUtils#directoryContains(File, File) * @since 2.2 */ public class FileUtilsDirectoryContainsTestCase { private File directory1; private File directory2; private File directory3; private File file1; private File file1ByRelativeDirectory2; private File file2; private File file2ByRelativeDirectory1; private File file3; @TempDir public File top; @SuppressWarnings("ResultOfMethodCallIgnored") @BeforeEach public void setUp() throws Exception { directory1 = new File(top, "directory1"); directory2 = new File(top, "directory2"); directory3 = new File(directory2, "directory3"); directory1.mkdir(); directory2.mkdir(); directory3.mkdir(); file1 = new File(directory1, "file1"); file2 = new File(directory2, "file2"); file3 = new File(top, "file3"); // Tests case with relative path file1ByRelativeDirectory2 = new File(top, "directory2/../directory1/file1"); file2ByRelativeDirectory1 = new File(top, "directory1/../directory2/file2"); FileUtils.touch(file1); FileUtils.touch(file2); FileUtils.touch(file3); } @Test public void testCanonicalPath() throws IOException { assertTrue(FileUtils.directoryContains(directory1, file1ByRelativeDirectory2)); assertTrue(FileUtils.directoryContains(directory2, file2ByRelativeDirectory1)); assertFalse(FileUtils.directoryContains(directory1, file2ByRelativeDirectory1)); assertFalse(FileUtils.directoryContains(directory2, file1ByRelativeDirectory2)); } @Test public void testDirectoryContainsDirectory() throws IOException { assertTrue(FileUtils.directoryContains(top, directory1)); assertTrue(FileUtils.directoryContains(top, directory2)); assertTrue(FileUtils.directoryContains(top, directory3)); assertTrue(FileUtils.directoryContains(directory2, directory3)); } @Test public void testDirectoryContainsFile() throws IOException { assertTrue(FileUtils.directoryContains(directory1, file1)); assertTrue(FileUtils.directoryContains(directory2, file2)); } @Test public void testDirectoryDoesNotContainFile() throws IOException { assertFalse(FileUtils.directoryContains(directory1, file2)); assertFalse(FileUtils.directoryContains(directory2, file1)); assertFalse(FileUtils.directoryContains(directory1, file3)); assertFalse(FileUtils.directoryContains(directory2, file3)); } @Test public void testDirectoryDoesNotContainsDirectory() throws IOException { assertFalse(FileUtils.directoryContains(directory1, top)); assertFalse(FileUtils.directoryContains(directory2, top)); assertFalse(FileUtils.directoryContains(directory3, top)); assertFalse(FileUtils.directoryContains(directory3, directory2)); } @Test public void testDirectoryDoesNotExist() throws IOException { final File dir = new File("DOESNOTEXIST"); assertFalse(dir.exists()); try { assertFalse(FileUtils.directoryContains(dir, file1)); fail("Expected " + IllegalArgumentException.class.getName()); } catch (final IllegalArgumentException e) { // expected } } @Test public void testSameFile() throws IOException { try { assertTrue(FileUtils.directoryContains(file1, file1)); fail("Expected " + IllegalArgumentException.class.getName()); } catch (final IllegalArgumentException e) { // expected } } @Test public void testIO466() throws IOException { final File fooFile = new File(directory1.getParent(), "directory1.txt"); assertFalse(FileUtils.directoryContains(directory1, fooFile)); } @Test public void testFileDoesNotExist() throws IOException { assertFalse(FileUtils.directoryContains(top, null)); final File file = new File("DOESNOTEXIST"); assertFalse(file.exists()); assertFalse(FileUtils.directoryContains(top, file)); } /** * Test to demonstrate a file which does not exist returns false * @throws IOException If an I/O error occurs */ @Test public void testFileDoesNotExistBug() throws IOException { final File file = new File(top, "DOESNOTEXIST"); assertTrue(top.exists(), "Check directory exists"); assertFalse(file.exists(), "Check file does not exist"); assertFalse(FileUtils.directoryContains(top, file), "Directory does not contain unrealized file"); } @Test public void testUnrealizedContainment() throws IOException { final File dir = new File("DOESNOTEXIST"); final File file = new File(dir, "DOESNOTEXIST2"); assertFalse(dir.exists()); assertFalse(file.exists()); try { assertTrue(FileUtils.directoryContains(dir, file)); } catch (final IllegalArgumentException e) { // expected } } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/FileUtilsFileNewerTestCase.java0100644 0000000 0000000 00000015702 13612062727 031573 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import java.io.BufferedOutputStream; import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.util.Date; import org.apache.commons.io.test.TestUtils; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; /** * This is used to test FileUtils for correctness. */ public class FileUtilsFileNewerTestCase { @TempDir public File temporaryFolder; // Test data private static final int FILE1_SIZE = 1; private static final int FILE2_SIZE = 1024 * 4 + 1; private File testFile1; private File testFile2; @BeforeEach public void setUp() throws Exception { testFile1 = new File(temporaryFolder, "file1-test.txt"); testFile2 = new File(temporaryFolder, "file2-test.txt"); if (!testFile1.getParentFile().exists()) { throw new IOException("Cannot create file " + testFile1 + " as the parent directory does not exist"); } try (final BufferedOutputStream output1 = new BufferedOutputStream(Files.newOutputStream(testFile1.toPath()))) { TestUtils.generateTestData(output1, FILE1_SIZE); } if (!testFile2.getParentFile().exists()) { throw new IOException("Cannot create file " + testFile2 + " as the parent directory does not exist"); } try (final BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(testFile2.toPath()))) { TestUtils.generateTestData(output, FILE2_SIZE); } } /** * Tests the {@code isFileNewer(File, *)} methods which a "normal" file. * @throws IOException * * @see FileUtils#isFileNewer(File, long) * @see FileUtils#isFileNewer(File, Date) * @see FileUtils#isFileNewer(File, File) */ @Test public void testIsFileNewer() throws IOException { if (!testFile1.exists()) { throw new IllegalStateException("The testFile1 should exist"); } final long fileLastModified = FileUtils.lastModified(testFile1); final long TWO_SECOND = 2000; testIsFileNewer("two second earlier is not newer" , testFile1, fileLastModified + TWO_SECOND, false); testIsFileNewer("same time is not newer" , testFile1, fileLastModified, false); testIsFileNewer("two second later is newer" , testFile1, fileLastModified - TWO_SECOND, true); } /** * Tests the {@code isFileNewer(File, *)} methods which a not existing file. * @throws IOException if an I/O error occurs. * * @see FileUtils#isFileNewer(File, long) * @see FileUtils#isFileNewer(File, Date) * @see FileUtils#isFileNewer(File, File) */ @Test public void testIsFileNewerImaginaryFile() throws IOException { final File imaginaryFile = new File(temporaryFolder, "imaginaryFile"); if (imaginaryFile.exists()) { throw new IllegalStateException("The imaginary File exists"); } testIsFileNewer("imaginary file can be newer" , imaginaryFile, FileUtils.lastModified(testFile2), false); } /** * Tests the {@code isFileNewer(File, *)} methods which the specified conditions. * * Creates : *
    *
  • a {@code Date} which represents the time reference
  • *
  • a temporary file with the same last modification date as the time reference
  • *
* Then compares (with the needed {@code isFileNewer} method) the last modification date of * the specified file with the specified time reference, the created {@code Date} and the temporary * file. *
* The test is successful if the three comparisons return the specified wanted result. * * @param description describes the tested situation * @param file the file of which the last modification date is compared * @param time the time reference measured in milliseconds since the epoch * @param wantedResult the expected result * @throws IOException if an I/O error occurs. * * @see FileUtils#isFileNewer(File, long) * @see FileUtils#isFileNewer(File, Date) * @see FileUtils#isFileNewer(File, File) */ protected void testIsFileNewer(final String description, final File file, final long time, final boolean wantedResult) throws IOException { assertEquals(wantedResult, FileUtils.isFileNewer(file, time), description + " - time"); assertEquals(wantedResult, FileUtils.isFileNewer(file, new Date(time)), description + " - date"); final File temporaryFile = testFile2; temporaryFile.setLastModified(time); assertEquals(time, FileUtils.lastModified(temporaryFile), "The temporary file hasn't the right last modification date"); assertEquals(wantedResult, FileUtils.isFileNewer(file, temporaryFile), description + " - file"); } /** * Tests the {@code isFileNewer(File, long)} method without specifying a {@code File}. *
* The test is successful if the method throws an {@code IllegalArgumentException}. */ @Test public void testIsFileNewerNoFile() { assertThrows(NullPointerException.class, () -> FileUtils.isFileNewer(null,0), "file"); } /** * Tests the {@code isFileNewer(File, Date)} method without specifying a {@code Date}. *
* The test is successful if the method throws an {@code IllegalArgumentException}. */ @Test public void testIsFileNewerNoDate() { assertThrows(NullPointerException.class, () -> FileUtils.isFileNewer(testFile1, (Date) null), "date"); } /** * Tests the {@code isFileNewer(File, File)} method without specifying a reference {@code File}. *
* The test is successful if the method throws an {@code IllegalArgumentException}. */ @Test public void testIsFileNewerNoFileReference() { assertThrows(NullPointerException.class, () -> FileUtils.isFileNewer(testFile1, (File) null), "reference"); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/FileUtilsListFilesTestCase.java0100644 0000000 0000000 00000017441 13612062727 031613 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import java.io.File; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import org.apache.commons.io.filefilter.FileFilterUtils; import org.apache.commons.io.filefilter.IOFileFilter; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; /** * Test cases for FileUtils.listFiles() methods. */ public class FileUtilsListFilesTestCase { @TempDir public File temporaryFolder; @SuppressWarnings("ResultOfMethodCallIgnored") @BeforeEach public void setUp() throws Exception { File dir = temporaryFolder; File file = new File(dir, "dummy-build.xml"); FileUtils.touch(file); file = new File(dir, "README"); FileUtils.touch(file); dir = new File(dir, "subdir1"); dir.mkdirs(); file = new File(dir, "dummy-build.xml"); FileUtils.touch(file); file = new File(dir, "dummy-readme.txt"); FileUtils.touch(file); dir = new File(dir, "subsubdir1"); dir.mkdirs(); file = new File(dir, "dummy-file.txt"); FileUtils.touch(file); file = new File(dir, "dummy-index.html"); FileUtils.touch(file); dir = dir.getParentFile(); dir = new File(dir, "CVS"); dir.mkdirs(); file = new File(dir, "Entries"); FileUtils.touch(file); file = new File(dir, "Repository"); FileUtils.touch(file); } private Collection filesToFilenames(final Collection files) { final Collection filenames = new ArrayList<>(files.size()); for (final File file : files) { filenames.add(file.getName()); } return filenames; } private Collection filesToFilenames(final Iterator files) { final Collection filenames = new ArrayList<>(); while (files.hasNext()) { filenames.add(files.next().getName()); } return filenames; } @Test public void testIterateFilesByExtension() { final String[] extensions = { "xml", "txt" }; Iterator files = FileUtils.iterateFiles(temporaryFolder, extensions, false); Collection filenames = filesToFilenames(files); assertEquals(1, filenames.size()); assertTrue(filenames.contains("dummy-build.xml")); assertFalse(filenames.contains("README")); assertFalse(filenames.contains("dummy-file.txt")); files = FileUtils.iterateFiles(temporaryFolder, extensions, true); filenames = filesToFilenames(files); assertEquals(4, filenames.size()); assertTrue(filenames.contains("dummy-file.txt")); assertFalse(filenames.contains("dummy-index.html")); files = FileUtils.iterateFiles(temporaryFolder, null, false); filenames = filesToFilenames(files); assertEquals(2, filenames.size()); assertTrue(filenames.contains("dummy-build.xml")); assertTrue(filenames.contains("README")); assertFalse(filenames.contains("dummy-file.txt")); } @Test public void testListFilesByExtension() { final String[] extensions = {"xml", "txt"}; Collection files = FileUtils.listFiles(temporaryFolder, extensions, false); assertEquals(1, files.size()); Collection filenames = filesToFilenames(files); assertTrue(filenames.contains("dummy-build.xml")); assertFalse(filenames.contains("README")); assertFalse(filenames.contains("dummy-file.txt")); files = FileUtils.listFiles(temporaryFolder, extensions, true); filenames = filesToFilenames(files); assertEquals(4, filenames.size()); assertTrue(filenames.contains("dummy-file.txt")); assertFalse(filenames.contains("dummy-index.html")); files = FileUtils.listFiles(temporaryFolder, null, false); assertEquals(2, files.size()); filenames = filesToFilenames(files); assertTrue(filenames.contains("dummy-build.xml")); assertTrue(filenames.contains("README")); assertFalse(filenames.contains("dummy-file.txt")); } @Test public void testListFiles() { Collection files; Collection filenames; IOFileFilter fileFilter; IOFileFilter dirFilter; // First, find non-recursively fileFilter = FileFilterUtils.trueFileFilter(); files = FileUtils.listFiles(temporaryFolder, fileFilter, null); filenames = filesToFilenames(files); assertTrue(filenames.contains("dummy-build.xml"), "'dummy-build.xml' is missing"); assertFalse(filenames.contains("dummy-index.html"), "'dummy-index.html' shouldn't be found"); assertFalse(filenames.contains("Entries"), "'Entries' shouldn't be found"); // Second, find recursively fileFilter = FileFilterUtils.trueFileFilter(); dirFilter = FileFilterUtils.notFileFilter(FileFilterUtils.nameFileFilter("CVS")); files = FileUtils.listFiles(temporaryFolder, fileFilter, dirFilter); filenames = filesToFilenames(files); assertTrue(filenames.contains("dummy-build.xml"), "'dummy-build.xml' is missing"); assertTrue(filenames.contains("dummy-index.html"), "'dummy-index.html' is missing"); assertFalse(filenames.contains("Entries"), "'Entries' shouldn't be found"); // Do the same as above but now with the filter coming from FileFilterUtils fileFilter = FileFilterUtils.trueFileFilter(); dirFilter = FileFilterUtils.makeCVSAware(null); files = FileUtils.listFiles(temporaryFolder, fileFilter, dirFilter); filenames = filesToFilenames(files); assertTrue(filenames.contains("dummy-build.xml"), "'dummy-build.xml' is missing"); assertTrue(filenames.contains("dummy-index.html"), "'dummy-index.html' is missing"); assertFalse(filenames.contains("Entries"), "'Entries' shouldn't be found"); // Again with the CVS filter but now with a non-null parameter fileFilter = FileFilterUtils.trueFileFilter(); dirFilter = FileFilterUtils.prefixFileFilter("sub"); dirFilter = FileFilterUtils.makeCVSAware(dirFilter); files = FileUtils.listFiles(temporaryFolder, fileFilter, dirFilter); filenames = filesToFilenames(files); assertTrue(filenames.contains("dummy-build.xml"), "'dummy-build.xml' is missing"); assertTrue(filenames.contains("dummy-index.html"), "'dummy-index.html' is missing"); assertFalse(filenames.contains("Entries"), "'Entries' shouldn't be found"); try { FileUtils.listFiles(temporaryFolder, null, null); fail("Expected error about null parameter"); } catch (final NullPointerException e) { // expected } } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/FileUtilsTestCase.java0100644 0000000 0000000 00000407756 13612062727 030010 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import java.io.BufferedOutputStream; import java.io.ByteArrayOutputStream; 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.OutputStream; import java.math.BigInteger; import java.net.URL; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; import java.time.Instant; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.ZoneId; import java.time.ZonedDateTime; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.GregorianCalendar; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.zip.CRC32; import java.util.zip.Checksum; import org.apache.commons.io.file.PathUtils; import org.apache.commons.io.file.PathUtilsIsEmptyTest; import org.apache.commons.io.filefilter.IOFileFilter; import org.apache.commons.io.filefilter.NameFileFilter; import org.apache.commons.io.filefilter.WildcardFileFilter; import org.apache.commons.io.test.TestUtils; import org.apache.commons.lang3.SystemUtils; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; /** * This is used to test FileUtils for correctness. * * @see FileUtils */ @SuppressWarnings({"deprecation", "ResultOfMethodCallIgnored"}) // unit tests include tests of many deprecated methods public class FileUtilsTestCase { /** * DirectoryWalker implementation that recursively lists all files and directories. */ static class ListDirectoryWalker extends DirectoryWalker { ListDirectoryWalker() { } @Override protected void handleDirectoryStart(final File directory, final int depth, final Collection results) throws IOException { // Add all directories except the starting directory if (depth > 0) { results.add(directory); } } @Override protected void handleFile(final File file, final int depth, final Collection results) throws IOException { results.add(file); } List list(final File startDirectory) throws IOException { final ArrayList files = new ArrayList<>(); walk(startDirectory, files); return files; } } // Test helper class to pretend a file is shorter than it is private static class ShorterFile extends File { private static final long serialVersionUID = 1L; public ShorterFile(final String pathname) { super(pathname); } @Override public long length() { return super.length() - 1; } } /** Test data. */ private static final long DATE3 = 1000000002000L; /** Test data. */ private static final long DATE2 = 1000000001000L; /** Test data. */ private static final long DATE1 = 1000000000000L; /** * Size of test directory. */ private static final int TEST_DIRECTORY_SIZE = 0; /** * Size of test directory. */ private static final BigInteger TEST_DIRECTORY_SIZE_BI = BigInteger.ZERO; /** * Size (greater of zero) of test file. */ private static final BigInteger TEST_DIRECTORY_SIZE_GT_ZERO_BI = BigInteger.valueOf(100); /** * List files recursively */ private static final ListDirectoryWalker LIST_WALKER = new ListDirectoryWalker(); @TempDir public File temporaryFolder; /** * Delay in milliseconds to make sure test for "last modified date" are accurate */ //private static final int LAST_MODIFIED_DELAY = 600; private File testFile1; private File testFile2; private long testFile1Size; private long testFile2Size; private void backDateFile10Minutes(final File testFile) throws IOException { final long mins10 = 1000 * 60 * 10; final long lastModified1 = getLastModifiedMillis(testFile); assertTrue(setLastModifiedMillis(testFile, lastModified1 - mins10)); // ensure it was changed assertNotEquals(getLastModifiedMillis(testFile), lastModified1, "Should have changed source date"); } private void consumeRemaining(final Iterator iterator) { if (iterator != null) { iterator.forEachRemaining(e -> {}); } } private void createCircularSymLink(final File file) throws IOException { if (!FilenameUtils.isSystemWindows()) { Runtime.getRuntime() .exec("ln -s " + file + "/.. " + file + "/cycle"); } else { try { Runtime.getRuntime() .exec("mklink /D " + file + "/cycle" + file + "/.. "); } catch (final IOException ioe) { // So that tests run in FAT filesystems //don't fail } } } private void createFilesForTestCopyDirectory(final File grandParentDir, final File parentDir, final File childDir) throws Exception { final File childDir2 = new File(parentDir, "child2"); final File grandChildDir = new File(childDir, "grandChild"); final File grandChild2Dir = new File(childDir2, "grandChild2"); final File file1 = new File(grandParentDir, "file1.txt"); final File file2 = new File(parentDir, "file2.txt"); final File file3 = new File(childDir, "file3.txt"); final File file4 = new File(childDir2, "file4.txt"); final File file5 = new File(grandChildDir, "file5.txt"); final File file6 = new File(grandChild2Dir, "file6.txt"); FileUtils.deleteDirectory(grandParentDir); grandChildDir.mkdirs(); grandChild2Dir.mkdirs(); FileUtils.writeStringToFile(file1, "File 1 in grandparent", "UTF8"); FileUtils.writeStringToFile(file2, "File 2 in parent", "UTF8"); FileUtils.writeStringToFile(file3, "File 3 in child", "UTF8"); FileUtils.writeStringToFile(file4, "File 4 in child2", "UTF8"); FileUtils.writeStringToFile(file5, "File 5 in grandChild", "UTF8"); FileUtils.writeStringToFile(file6, "File 6 in grandChild2", "UTF8"); } private long getLastModifiedMillis(final File file) throws IOException { return FileUtils.lastModified(file); } private String getName() { return this.getClass().getSimpleName(); } private void iterateFilesAndDirs(final File dir, final IOFileFilter fileFilter, final IOFileFilter dirFilter, final Collection expectedFilesAndDirs) { final Iterator iterator; int filesCount = 0; iterator = FileUtils.iterateFilesAndDirs(dir, fileFilter, dirFilter); try { final List actualFiles = new ArrayList<>(); while (iterator.hasNext()) { filesCount++; final File file = iterator.next(); actualFiles.add(file); assertTrue(expectedFilesAndDirs.contains(file), () -> "Unexpected directory/file " + file + ", expected one of " + expectedFilesAndDirs); } assertEquals(expectedFilesAndDirs.size(), filesCount, () -> actualFiles.toString()); } finally { // MUST consume until the end in order to close the underlying stream. consumeRemaining(iterator); } } void openOutputStream_noParent(final boolean createFile) throws Exception { final File file = new File("test.txt"); assertNull(file.getParentFile()); try { if (createFile) { TestUtils.createLineBasedFile(file, new String[]{"Hello"}); } try (FileOutputStream out = FileUtils.openOutputStream(file)) { out.write(0); } assertTrue(file.exists()); } finally { if (!file.delete()) { file.deleteOnExit(); } } } private boolean setLastModifiedMillis(final File testFile, final long millis) { return testFile.setLastModified(millis); // try { // Files.setLastModifiedTime(testFile.toPath(), FileTime.fromMillis(millis)); // } catch (IOException e) { // return false; // } // return true; } @BeforeEach public void setUp() throws Exception { testFile1 = new File(temporaryFolder, "file1-test.txt"); testFile2 = new File(temporaryFolder, "file1a-test.txt"); testFile1Size = testFile1.length(); testFile2Size = testFile2.length(); if (!testFile1.getParentFile().exists()) { throw new IOException("Cannot create file " + testFile1 + " as the parent directory does not exist"); } try (final BufferedOutputStream output3 = new BufferedOutputStream(Files.newOutputStream(testFile1.toPath()))) { TestUtils.generateTestData(output3, testFile1Size); } if (!testFile2.getParentFile().exists()) { throw new IOException("Cannot create file " + testFile2 + " as the parent directory does not exist"); } try (final BufferedOutputStream output2 = new BufferedOutputStream(Files.newOutputStream(testFile2.toPath()))) { TestUtils.generateTestData(output2, testFile2Size); } FileUtils.deleteDirectory(temporaryFolder); temporaryFolder.mkdirs(); if (!testFile1.getParentFile().exists()) { throw new IOException("Cannot create file " + testFile1 + " as the parent directory does not exist"); } try (final BufferedOutputStream output1 = new BufferedOutputStream(Files.newOutputStream(testFile1.toPath()))) { TestUtils.generateTestData(output1, testFile1Size); } if (!testFile2.getParentFile().exists()) { throw new IOException("Cannot create file " + testFile2 + " as the parent directory does not exist"); } try (final BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(testFile2.toPath()))) { TestUtils.generateTestData(output, testFile2Size); } } @Test public void test_openInputStream_exists() throws Exception { final File file = new File(temporaryFolder, "test.txt"); TestUtils.createLineBasedFile(file, new String[]{"Hello"}); try (FileInputStream in = FileUtils.openInputStream(file)) { assertEquals('H', in.read()); } } @Test public void test_openInputStream_existsButIsDirectory() { final File directory = new File(temporaryFolder, "subdir"); directory.mkdirs(); assertThrows(IOException.class, () -> FileUtils.openInputStream(directory)); } @Test public void test_openInputStream_notExists() { final File directory = new File(temporaryFolder, "test.txt"); try (FileInputStream in = FileUtils.openInputStream(directory)) { fail(); } catch (final IOException ioe) { // expected } } @Test public void test_openOutputStream_exists() throws Exception { final File file = new File(temporaryFolder, "test.txt"); TestUtils.createLineBasedFile(file, new String[]{"Hello"}); try (FileOutputStream out = FileUtils.openOutputStream(file)) { out.write(0); } assertTrue(file.exists()); } @Test public void test_openOutputStream_existsButIsDirectory() { final File directory = new File(temporaryFolder, "subdir"); directory.mkdirs(); assertThrows(IllegalArgumentException.class, () -> FileUtils.openOutputStream(directory)); } @Test public void test_openOutputStream_noParentCreateFile() throws Exception { openOutputStream_noParent(true); } @Test public void test_openOutputStream_noParentNoFile() throws Exception { openOutputStream_noParent(false); } @Test public void test_openOutputStream_notExists() throws Exception { final File file = new File(temporaryFolder, "a/test.txt"); try (FileOutputStream out = FileUtils.openOutputStream(file)) { out.write(0); } assertTrue(file.exists()); } @Test public void test_openOutputStream_notExistsCannotCreate() { // according to Wikipedia, most filing systems have a 256 limit on filename final String longStr = "abcdevwxyzabcdevwxyzabcdevwxyzabcdevwxyzabcdevwxyz" + "abcdevwxyzabcdevwxyzabcdevwxyzabcdevwxyzabcdevwxyz" + "abcdevwxyzabcdevwxyzabcdevwxyzabcdevwxyzabcdevwxyz" + "abcdevwxyzabcdevwxyzabcdevwxyzabcdevwxyzabcdevwxyz" + "abcdevwxyzabcdevwxyzabcdevwxyzabcdevwxyzabcdevwxyz" + "abcdevwxyzabcdevwxyzabcdevwxyzabcdevwxyzabcdevwxyz"; // 300 chars final File file = new File(temporaryFolder, "a/" + longStr + "/test.txt"); try (FileOutputStream out = FileUtils.openOutputStream(file)) { fail(); } catch (final IOException ioe) { // expected } } // byteCountToDisplaySize @Test public void testByteCountToDisplaySizeBigInteger() { final BigInteger b1023 = BigInteger.valueOf(1023); final BigInteger b1025 = BigInteger.valueOf(1025); final BigInteger KB1 = BigInteger.valueOf(1024); final BigInteger MB1 = KB1.multiply(KB1); final BigInteger GB1 = MB1.multiply(KB1); final BigInteger GB2 = GB1.add(GB1); final BigInteger TB1 = GB1.multiply(KB1); final BigInteger PB1 = TB1.multiply(KB1); final BigInteger EB1 = PB1.multiply(KB1); assertEquals("0 bytes", FileUtils.byteCountToDisplaySize(BigInteger.ZERO)); assertEquals("1 bytes", FileUtils.byteCountToDisplaySize(BigInteger.ONE)); assertEquals("1023 bytes", FileUtils.byteCountToDisplaySize(b1023)); assertEquals("1 KB", FileUtils.byteCountToDisplaySize(KB1)); assertEquals("1 KB", FileUtils.byteCountToDisplaySize(b1025)); assertEquals("1023 KB", FileUtils.byteCountToDisplaySize(MB1.subtract(BigInteger.ONE))); assertEquals("1 MB", FileUtils.byteCountToDisplaySize(MB1)); assertEquals("1 MB", FileUtils.byteCountToDisplaySize(MB1.add(BigInteger.ONE))); assertEquals("1023 MB", FileUtils.byteCountToDisplaySize(GB1.subtract(BigInteger.ONE))); assertEquals("1 GB", FileUtils.byteCountToDisplaySize(GB1)); assertEquals("1 GB", FileUtils.byteCountToDisplaySize(GB1.add(BigInteger.ONE))); assertEquals("2 GB", FileUtils.byteCountToDisplaySize(GB2)); assertEquals("1 GB", FileUtils.byteCountToDisplaySize(GB2.subtract(BigInteger.ONE))); assertEquals("1 TB", FileUtils.byteCountToDisplaySize(TB1)); assertEquals("1 PB", FileUtils.byteCountToDisplaySize(PB1)); assertEquals("1 EB", FileUtils.byteCountToDisplaySize(EB1)); assertEquals("7 EB", FileUtils.byteCountToDisplaySize(Long.MAX_VALUE)); // Other MAX_VALUEs assertEquals("63 KB", FileUtils.byteCountToDisplaySize(BigInteger.valueOf(Character.MAX_VALUE))); assertEquals("31 KB", FileUtils.byteCountToDisplaySize(BigInteger.valueOf(Short.MAX_VALUE))); assertEquals("1 GB", FileUtils.byteCountToDisplaySize(BigInteger.valueOf(Integer.MAX_VALUE))); } @SuppressWarnings("NumericOverflow") @Test public void testByteCountToDisplaySizeLong() { assertEquals("0 bytes", FileUtils.byteCountToDisplaySize(0)); assertEquals("1 bytes", FileUtils.byteCountToDisplaySize(1)); assertEquals("1023 bytes", FileUtils.byteCountToDisplaySize(1023)); assertEquals("1 KB", FileUtils.byteCountToDisplaySize(1024)); assertEquals("1 KB", FileUtils.byteCountToDisplaySize(1025)); assertEquals("1023 KB", FileUtils.byteCountToDisplaySize(1024 * 1023)); assertEquals("1 MB", FileUtils.byteCountToDisplaySize(1024 * 1024)); assertEquals("1 MB", FileUtils.byteCountToDisplaySize(1024 * 1025)); assertEquals("1023 MB", FileUtils.byteCountToDisplaySize(1024 * 1024 * 1023)); assertEquals("1 GB", FileUtils.byteCountToDisplaySize(1024 * 1024 * 1024)); assertEquals("1 GB", FileUtils.byteCountToDisplaySize(1024 * 1024 * 1025)); assertEquals("2 GB", FileUtils.byteCountToDisplaySize(1024L * 1024 * 1024 * 2)); assertEquals("1 GB", FileUtils.byteCountToDisplaySize(1024 * 1024 * 1024 * 2 - 1)); assertEquals("1 TB", FileUtils.byteCountToDisplaySize(1024L * 1024 * 1024 * 1024)); assertEquals("1 PB", FileUtils.byteCountToDisplaySize(1024L * 1024 * 1024 * 1024 * 1024)); assertEquals("1 EB", FileUtils.byteCountToDisplaySize(1024L * 1024 * 1024 * 1024 * 1024 * 1024)); assertEquals("7 EB", FileUtils.byteCountToDisplaySize(Long.MAX_VALUE)); // Other MAX_VALUEs assertEquals("63 KB", FileUtils.byteCountToDisplaySize(Character.MAX_VALUE)); assertEquals("31 KB", FileUtils.byteCountToDisplaySize(Short.MAX_VALUE)); assertEquals("1 GB", FileUtils.byteCountToDisplaySize(Integer.MAX_VALUE)); } @Test public void testChecksum() throws Exception { // create a test file final String text = "Imagination is more important than knowledge - Einstein"; final File file = new File(temporaryFolder, "checksum-test.txt"); FileUtils.writeStringToFile(file, text, "US-ASCII"); // compute the expected checksum final Checksum expectedChecksum = new CRC32(); expectedChecksum.update(text.getBytes(StandardCharsets.US_ASCII), 0, text.length()); final long expectedValue = expectedChecksum.getValue(); // compute the checksum of the file final Checksum testChecksum = new CRC32(); final Checksum resultChecksum = FileUtils.checksum(file, testChecksum); final long resultValue = resultChecksum.getValue(); assertSame(testChecksum, resultChecksum); assertEquals(expectedValue, resultValue); } @Test public void testChecksumCRC32() throws Exception { // create a test file final String text = "Imagination is more important than knowledge - Einstein"; final File file = new File(temporaryFolder, "checksum-test.txt"); FileUtils.writeStringToFile(file, text, "US-ASCII"); // compute the expected checksum final Checksum expectedChecksum = new CRC32(); expectedChecksum.update(text.getBytes(StandardCharsets.US_ASCII), 0, text.length()); final long expectedValue = expectedChecksum.getValue(); // compute the checksum of the file final long resultValue = FileUtils.checksumCRC32(file); assertEquals(expectedValue, resultValue); } @Test public void testChecksumDouble() throws Exception { // create a test file final String text1 = "Imagination is more important than knowledge - Einstein"; final File file1 = new File(temporaryFolder, "checksum-test.txt"); FileUtils.writeStringToFile(file1, text1, "US-ASCII"); // create a second test file final String text2 = "To be or not to be - Shakespeare"; final File file2 = new File(temporaryFolder, "checksum-test2.txt"); FileUtils.writeStringToFile(file2, text2, "US-ASCII"); // compute the expected checksum final Checksum expectedChecksum = new CRC32(); expectedChecksum.update(text1.getBytes(StandardCharsets.US_ASCII), 0, text1.length()); expectedChecksum.update(text2.getBytes(StandardCharsets.US_ASCII), 0, text2.length()); final long expectedValue = expectedChecksum.getValue(); // compute the checksum of the file final Checksum testChecksum = new CRC32(); FileUtils.checksum(file1, testChecksum); FileUtils.checksum(file2, testChecksum); final long resultValue = testChecksum.getValue(); assertEquals(expectedValue, resultValue); } @Test public void testChecksumOnDirectory() throws Exception { try { FileUtils.checksum(new File("."), new CRC32()); fail(); } catch (final IllegalArgumentException ex) { // expected } } @Test public void testChecksumOnNullChecksum() throws Exception { // create a test file final String text = "Imagination is more important than knowledge - Einstein"; final File file = new File(temporaryFolder, "checksum-test.txt"); FileUtils.writeStringToFile(file, text, "US-ASCII"); try { FileUtils.checksum(file, null); fail(); } catch (final NullPointerException ex) { // expected } } @Test public void testChecksumOnNullFile() throws Exception { try { FileUtils.checksum(null, new CRC32()); fail(); } catch (final NullPointerException ex) { // expected } } // Compare sizes of a directory tree using long and BigInteger methods @Test public void testCompareSizeOf() { final File start = new File("src/test/java"); final long sizeLong1 = FileUtils.sizeOf(start); final BigInteger sizeBig = FileUtils.sizeOfAsBigInteger(start); final long sizeLong2 = FileUtils.sizeOf(start); assertEquals(sizeLong1, sizeLong2, "Size should not change"); assertEquals(sizeLong1, sizeBig.longValue(), "longSize should equal BigSize"); } @Test public void testContentEquals() throws Exception { // Non-existent files final File file = new File(temporaryFolder, getName()); final File file2 = new File(temporaryFolder, getName() + "2"); assertTrue(FileUtils.contentEquals(null, null)); assertFalse(FileUtils.contentEquals(null, file)); assertFalse(FileUtils.contentEquals(file, null)); // both don't exist assertTrue(FileUtils.contentEquals(file, file)); assertTrue(FileUtils.contentEquals(file, file2)); assertTrue(FileUtils.contentEquals(file2, file2)); assertTrue(FileUtils.contentEquals(file2, file)); // Directories assertThrows(IllegalArgumentException.class, () -> FileUtils.contentEquals(temporaryFolder, temporaryFolder)); // Different files final File objFile1 = new File(temporaryFolder, getName() + ".object"); objFile1.deleteOnExit(); FileUtils.copyURLToFile( getClass().getResource("/java/lang/Object.class"), objFile1); final File objFile1b = new File(temporaryFolder, getName() + ".object2"); objFile1.deleteOnExit(); FileUtils.copyURLToFile( getClass().getResource("/java/lang/Object.class"), objFile1b); final File objFile2 = new File(temporaryFolder, getName() + ".collection"); objFile2.deleteOnExit(); FileUtils.copyURLToFile( getClass().getResource("/java/util/Collection.class"), objFile2); assertFalse(FileUtils.contentEquals(objFile1, objFile2)); assertFalse(FileUtils.contentEquals(objFile1b, objFile2)); assertTrue(FileUtils.contentEquals(objFile1, objFile1b)); assertTrue(FileUtils.contentEquals(objFile1, objFile1)); assertTrue(FileUtils.contentEquals(objFile1b, objFile1b)); assertTrue(FileUtils.contentEquals(objFile2, objFile2)); // Equal files file.createNewFile(); file2.createNewFile(); assertTrue(FileUtils.contentEquals(file, file)); assertTrue(FileUtils.contentEquals(file, file2)); } // toFiles @Test public void testContentEqualsIgnoreEOL() throws Exception { // Non-existent files final File file1 = new File(temporaryFolder, getName()); final File file2 = new File(temporaryFolder, getName() + "2"); assertTrue(FileUtils.contentEqualsIgnoreEOL(null, null, null)); assertFalse(FileUtils.contentEqualsIgnoreEOL(null, file1, null)); assertFalse(FileUtils.contentEqualsIgnoreEOL(file1, null, null)); // both don't exist assertTrue(FileUtils.contentEqualsIgnoreEOL(file1, file1, null)); assertTrue(FileUtils.contentEqualsIgnoreEOL(file1, file2, null)); assertTrue(FileUtils.contentEqualsIgnoreEOL(file2, file2, null)); assertTrue(FileUtils.contentEqualsIgnoreEOL(file2, file1, null)); // Directories assertThrows(IllegalArgumentException.class, () -> FileUtils.contentEqualsIgnoreEOL(temporaryFolder, temporaryFolder, null)); // Different files final File tfile1 = new File(temporaryFolder, getName() + ".txt1"); tfile1.deleteOnExit(); FileUtils.write(tfile1, "123\r"); final File tfile2 = new File(temporaryFolder, getName() + ".txt2"); tfile1.deleteOnExit(); FileUtils.write(tfile2, "123\n"); final File tfile3 = new File(temporaryFolder, getName() + ".collection"); tfile3.deleteOnExit(); FileUtils.write(tfile3, "123\r\n2"); assertTrue(FileUtils.contentEqualsIgnoreEOL(tfile1, tfile1, null)); assertTrue(FileUtils.contentEqualsIgnoreEOL(tfile2, tfile2, null)); assertTrue(FileUtils.contentEqualsIgnoreEOL(tfile3, tfile3, null)); assertTrue(FileUtils.contentEqualsIgnoreEOL(tfile1, tfile2, null)); assertFalse(FileUtils.contentEqualsIgnoreEOL(tfile1, tfile3, null)); assertFalse(FileUtils.contentEqualsIgnoreEOL(tfile2, tfile3, null)); final URL urlCR = getClass().getResource("FileUtilsTestDataCR.dat"); assertNotNull(urlCR); final File cr = new File(urlCR.toURI()); assertTrue(cr.exists()); final URL urlCRLF = getClass().getResource("FileUtilsTestDataCRLF.dat"); assertNotNull(urlCRLF); final File crlf = new File(urlCRLF.toURI()); assertTrue(crlf.exists()); final URL urlLF = getClass().getResource("FileUtilsTestDataLF.dat"); assertNotNull(urlLF); final File lf = new File(urlLF.toURI()); assertTrue(lf.exists()); assertTrue(FileUtils.contentEqualsIgnoreEOL(cr, cr, null)); assertTrue(FileUtils.contentEqualsIgnoreEOL(crlf, crlf, null)); assertTrue(FileUtils.contentEqualsIgnoreEOL(lf, lf, null)); assertTrue(FileUtils.contentEqualsIgnoreEOL(cr, crlf, null)); assertTrue(FileUtils.contentEqualsIgnoreEOL(cr, lf, null)); assertTrue(FileUtils.contentEqualsIgnoreEOL(crlf, lf, null)); // Check the files behave OK when EOL is not ignored assertTrue(FileUtils.contentEquals(cr, cr)); assertTrue(FileUtils.contentEquals(crlf, crlf)); assertTrue(FileUtils.contentEquals(lf, lf)); assertFalse(FileUtils.contentEquals(cr, crlf)); assertFalse(FileUtils.contentEquals(cr, lf)); assertFalse(FileUtils.contentEquals(crlf, lf)); // Equal files file1.createNewFile(); file2.createNewFile(); assertTrue(FileUtils.contentEqualsIgnoreEOL(file1, file1, null)); assertTrue(FileUtils.contentEqualsIgnoreEOL(file1, file2, null)); } @Test public void testCopyDirectoryExceptions() { // // NullPointerException assertThrows(NullPointerException.class, () -> FileUtils.copyDirectory(null, null)); assertThrows(NullPointerException.class, () -> FileUtils.copyDirectory(null, testFile1)); assertThrows(NullPointerException.class, () -> FileUtils.copyDirectory(testFile1, null)); assertThrows(NullPointerException.class, () -> FileUtils.copyDirectory(null, new File("a"))); // // IllegalArgumentException assertThrows(IllegalArgumentException.class, () -> FileUtils.copyDirectory(testFile1, new File("a"))); assertThrows(IllegalArgumentException.class, () -> FileUtils.copyDirectory(testFile1, new File("a"))); assertThrows(IllegalArgumentException.class, () -> FileUtils.copyDirectory(temporaryFolder, temporaryFolder)); // // IOException assertThrows(IOException.class, () -> FileUtils.copyDirectory(new File("doesnt-exist"), new File("a"))); assertThrows(IllegalArgumentException.class, () -> FileUtils.copyDirectory(temporaryFolder, testFile1)); } @Test public void testCopyDirectoryFiltered() throws Exception { final File grandParentDir = new File(temporaryFolder, "grandparent"); final File parentDir = new File(grandParentDir, "parent"); final File childDir = new File(parentDir, "child"); createFilesForTestCopyDirectory(grandParentDir, parentDir, childDir); final NameFileFilter filter = new NameFileFilter("parent", "child", "file3.txt"); final File destDir = new File(temporaryFolder, "copydest"); FileUtils.copyDirectory(grandParentDir, destDir, filter); final List files = LIST_WALKER.list(destDir); assertEquals(3, files.size()); assertEquals("parent", files.get(0).getName()); assertEquals("child", files.get(1).getName()); assertEquals("file3.txt", files.get(2).getName()); } @Test public void testCopyDirectoryPreserveDates() throws Exception { final File source = new File(temporaryFolder, "source"); final File sourceDirectory = new File(source, "directory"); final File sourceFile = new File(sourceDirectory, "hello.txt"); // Prepare source data source.mkdirs(); sourceDirectory.mkdir(); FileUtils.writeStringToFile(sourceFile, "HELLO WORLD", "UTF8"); // Set dates in reverse order to avoid overwriting previous values // Also, use full seconds (arguments are in ms) close to today // but still highly unlikely to occur in the real world assertTrue(setLastModifiedMillis(sourceFile, DATE3)); assertTrue(setLastModifiedMillis(sourceDirectory, DATE2)); assertTrue(setLastModifiedMillis(source, DATE1)); final File target = new File(temporaryFolder, "target"); final File targetDirectory = new File(target, "directory"); final File targetFile = new File(targetDirectory, "hello.txt"); // Test with preserveFileDate disabled // On Windows, the last modified time is copied by default. FileUtils.copyDirectory(source, target, false); assertNotEquals(DATE1, getLastModifiedMillis(target)); assertNotEquals(DATE2, getLastModifiedMillis(targetDirectory)); if (!SystemUtils.IS_OS_WINDOWS) { assertNotEquals(DATE3, getLastModifiedMillis(targetFile)); } FileUtils.deleteDirectory(target); // Test with preserveFileDate enabled FileUtils.copyDirectory(source, target, true); assertEquals(DATE1, getLastModifiedMillis(target)); assertEquals(DATE2, getLastModifiedMillis(targetDirectory)); assertEquals(DATE3, getLastModifiedMillis(targetFile)); FileUtils.deleteDirectory(target); // also if the target directory already exists (IO-190) target.mkdirs(); FileUtils.copyDirectory(source, target, true); assertEquals(DATE1, getLastModifiedMillis(target)); assertEquals(DATE2, getLastModifiedMillis(targetDirectory)); assertEquals(DATE3, getLastModifiedMillis(targetFile)); FileUtils.deleteDirectory(target); // also if the target subdirectory already exists (IO-190) targetDirectory.mkdirs(); FileUtils.copyDirectory(source, target, true); assertEquals(DATE1, getLastModifiedMillis(target)); assertEquals(DATE2, getLastModifiedMillis(targetDirectory)); assertEquals(DATE3, getLastModifiedMillis(targetFile)); FileUtils.deleteDirectory(target); } /* Test for IO-141 */ @Test public void testCopyDirectoryToChild() throws Exception { final File grandParentDir = new File(temporaryFolder, "grandparent"); final File parentDir = new File(grandParentDir, "parent"); final File childDir = new File(parentDir, "child"); createFilesForTestCopyDirectory(grandParentDir, parentDir, childDir); final long expectedCount = LIST_WALKER.list(grandParentDir).size() + LIST_WALKER.list(parentDir).size(); final long expectedSize = FileUtils.sizeOfDirectory(grandParentDir) + FileUtils.sizeOfDirectory(parentDir); FileUtils.copyDirectory(parentDir, childDir); assertEquals(expectedCount, LIST_WALKER.list(grandParentDir).size()); assertEquals(expectedSize, FileUtils.sizeOfDirectory(grandParentDir)); assertTrue(expectedCount > 0, "Count > 0"); assertTrue(expectedSize > 0, "Size > 0"); } // toURLs @Test public void testCopyDirectoryToDirectory_NonExistingDest() throws Exception { if (!testFile1.getParentFile().exists()) { throw new IOException("Cannot create file " + testFile1 + " as the parent directory does not exist"); } final OutputStream output1 = new BufferedOutputStream(Files.newOutputStream(testFile1.toPath())); try { TestUtils.generateTestData(output1, 1234); } finally { IOUtils.closeQuietly(output1); } if (!testFile2.getParentFile().exists()) { throw new IOException("Cannot create file " + testFile2 + " as the parent directory does not exist"); } final OutputStream output = new BufferedOutputStream(Files.newOutputStream(testFile2.toPath())); try { TestUtils.generateTestData(output, 4321); } finally { IOUtils.closeQuietly(output); } final File srcDir = temporaryFolder; final File subDir = new File(srcDir, "sub"); subDir.mkdir(); final File subFile = new File(subDir, "A.txt"); FileUtils.writeStringToFile(subFile, "HELLO WORLD", "UTF8"); final File destDir = new File(System.getProperty("java.io.tmpdir"), "tmp-FileUtilsTestCase"); FileUtils.deleteDirectory(destDir); final File actualDestDir = new File(destDir, srcDir.getName()); FileUtils.copyDirectoryToDirectory(srcDir, destDir); assertTrue(destDir.exists(), "Check exists"); assertTrue(actualDestDir.exists(), "Check exists"); final long srcSize = FileUtils.sizeOfDirectory(srcDir); assertTrue(srcSize > 0, "Size > 0"); assertEquals(srcSize, FileUtils.sizeOfDirectory(actualDestDir), "Check size"); assertTrue(new File(actualDestDir, "sub/A.txt").exists()); FileUtils.deleteDirectory(destDir); } // @Test public void testToURLs2() throws Exception { // File[] files = new File[] { // new File(temporaryFolder, "file1.txt"), // null, // }; // URL[] urls = FileUtils.toURLs(files); // // assertEquals(files.length, urls.length); // assertTrue(urls[0].toExternalForm().startsWith("file:")); // assertTrue(urls[0].toExternalForm().indexOf("file1.txt") > 0); // assertEquals(null, urls[1]); // } // // @Test public void testToURLs3() throws Exception { // File[] files = null; // URL[] urls = FileUtils.toURLs(files); // // assertEquals(0, urls.length); // } @Test public void testCopyDirectoryToExistingDest() throws Exception { if (!testFile1.getParentFile().exists()) { throw new IOException("Cannot create file " + testFile1 + " as the parent directory does not exist"); } final OutputStream output1 = new BufferedOutputStream(Files.newOutputStream(testFile1.toPath())); try { TestUtils.generateTestData(output1, 1234); } finally { IOUtils.closeQuietly(output1); } if (!testFile2.getParentFile().exists()) { throw new IOException("Cannot create file " + testFile2 + " as the parent directory does not exist"); } final OutputStream output = new BufferedOutputStream(Files.newOutputStream(testFile2.toPath())); try { TestUtils.generateTestData(output, 4321); } finally { IOUtils.closeQuietly(output); } final File srcDir = temporaryFolder; final File subDir = new File(srcDir, "sub"); subDir.mkdir(); final File subFile = new File(subDir, "A.txt"); FileUtils.writeStringToFile(subFile, "HELLO WORLD", "UTF8"); final File destDir = new File(System.getProperty("java.io.tmpdir"), "tmp-FileUtilsTestCase"); FileUtils.deleteDirectory(destDir); destDir.mkdirs(); FileUtils.copyDirectory(srcDir, destDir); final long srcSize = FileUtils.sizeOfDirectory(srcDir); assertTrue(srcSize > 0, "Size > 0"); assertEquals(srcSize, FileUtils.sizeOfDirectory(destDir)); assertTrue(new File(destDir, "sub/A.txt").exists()); } // contentEquals /* Test for IO-141 */ @Test public void testCopyDirectoryToGrandChild() throws Exception { final File grandParentDir = new File(temporaryFolder, "grandparent"); final File parentDir = new File(grandParentDir, "parent"); final File childDir = new File(parentDir, "child"); createFilesForTestCopyDirectory(grandParentDir, parentDir, childDir); final long expectedCount = LIST_WALKER.list(grandParentDir).size() * 2; final long expectedSize = FileUtils.sizeOfDirectory(grandParentDir) * 2; FileUtils.copyDirectory(grandParentDir, childDir); assertEquals(expectedCount, LIST_WALKER.list(grandParentDir).size()); assertEquals(expectedSize, FileUtils.sizeOfDirectory(grandParentDir)); assertTrue(expectedSize > 0, "Size > 0"); } /* Test for IO-217 FileUtils.copyDirectoryToDirectory makes infinite loops */ @Test public void testCopyDirectoryToItself() throws Exception { final File dir = new File(temporaryFolder, "itself"); dir.mkdirs(); FileUtils.copyDirectoryToDirectory(dir, dir); assertEquals(1, LIST_WALKER.list(dir).size()); } // copyURLToFile @Test public void testCopyDirectoryToNonExistingDest() throws Exception { if (!testFile1.getParentFile().exists()) { throw new IOException("Cannot create file " + testFile1 + " as the parent directory does not exist"); } final OutputStream output1 = new BufferedOutputStream(Files.newOutputStream(testFile1.toPath())); try { TestUtils.generateTestData(output1, 1234); } finally { IOUtils.closeQuietly(output1); } if (!testFile2.getParentFile().exists()) { throw new IOException("Cannot create file " + testFile2 + " as the parent directory does not exist"); } final OutputStream output = new BufferedOutputStream(Files.newOutputStream(testFile2.toPath())); try { TestUtils.generateTestData(output, 4321); } finally { IOUtils.closeQuietly(output); } final File srcDir = temporaryFolder; final File subDir = new File(srcDir, "sub"); subDir.mkdir(); final File subFile = new File(subDir, "A.txt"); FileUtils.writeStringToFile(subFile, "HELLO WORLD", "UTF8"); final File destDir = new File(System.getProperty("java.io.tmpdir"), "tmp-FileUtilsTestCase"); FileUtils.deleteDirectory(destDir); FileUtils.copyDirectory(srcDir, destDir); assertTrue(destDir.exists(), "Check exists"); final long sizeOfSrcDirectory = FileUtils.sizeOfDirectory(srcDir); assertTrue(sizeOfSrcDirectory > 0, "Size > 0"); assertEquals(sizeOfSrcDirectory, FileUtils.sizeOfDirectory(destDir), "Check size"); assertTrue(new File(destDir, "sub/A.txt").exists()); FileUtils.deleteDirectory(destDir); } @Test public void testCopyFile1() throws Exception { final File destination = new File(temporaryFolder, "copy1.txt"); backDateFile10Minutes(testFile1); // set test file back 10 minutes FileUtils.copyFile(testFile1, destination); assertTrue(destination.exists(), "Check Exist"); assertEquals(testFile1Size, destination.length(), "Check Full copy"); assertEquals(getLastModifiedMillis(testFile1), getLastModifiedMillis(destination), "Check last modified date preserved"); } // forceMkdir @Test public void testCopyFile1ToDir() throws Exception { final File directory = new File(temporaryFolder, "subdir"); if (!directory.exists()) { directory.mkdirs(); } final File destination = new File(directory, testFile1.getName()); backDateFile10Minutes(testFile1); FileUtils.copyFileToDirectory(testFile1, directory); assertTrue(destination.exists(), "Check Exist"); assertEquals(testFile1Size, destination.length(), "Check Full copy"); assertEquals(FileUtils.lastModified(testFile1), FileUtils.lastModified(destination), "Check last modified date preserved"); assertThrows(IllegalArgumentException.class, () -> FileUtils.copyFileToDirectory(destination, directory), "Should not be able to copy a file into the same directory as itself"); } @Test public void testCopyFile2() throws Exception { final File destination = new File(temporaryFolder, "copy2.txt"); backDateFile10Minutes(testFile1); // set test file back 10 minutes FileUtils.copyFile(testFile1, destination); assertTrue(destination.exists(), "Check Exist"); assertEquals(testFile2Size, destination.length(), "Check Full copy"); assertEquals(getLastModifiedMillis(testFile1) , getLastModifiedMillis(destination), "Check last modified date preserved"); } // sizeOfDirectory @Test public void testCopyFile2ToDir() throws Exception { final File directory = new File(temporaryFolder, "subdir"); if (!directory.exists()) { directory.mkdirs(); } final File destination = new File(directory, testFile1.getName()); backDateFile10Minutes(testFile1); FileUtils.copyFileToDirectory(testFile1, directory); assertTrue(destination.exists(), "Check Exist"); assertEquals(testFile2Size, destination.length(), "Check Full copy"); assertEquals(FileUtils.lastModified(testFile1), FileUtils.lastModified(destination), "Check last modified date preserved"); } @Test public void testCopyFile2WithoutFileDatePreservation() throws Exception { final File destFile = new File(temporaryFolder, "copy2.txt"); backDateFile10Minutes(testFile1); // set test file back 10 minutes // destination file time should not be less than this (allowing for granularity) final long nowMillis = System.currentTimeMillis() - 1000L; // On Windows, the last modified time is copied by default. FileUtils.copyFile(testFile1, destFile, false); assertTrue(destFile.exists(), "Check Exist"); assertEquals(testFile1Size, destFile.length(), "Check Full copy"); final long destLastModMillis = getLastModifiedMillis(destFile); final long unexpectedMillis = getLastModifiedMillis(testFile1); if (!SystemUtils.IS_OS_WINDOWS) { final long deltaMillis = destLastModMillis - unexpectedMillis; assertNotEquals(unexpectedMillis, destLastModMillis, "Check last modified date not same as input, delta " + deltaMillis); assertTrue(destLastModMillis > nowMillis, destLastModMillis + " > " + nowMillis + " (delta " + deltaMillis + ")"); } } @Test @Disabled public void testCopyFileLarge() throws Exception { final File largeFile = new File(temporaryFolder, "large.txt"); final File destination = new File(temporaryFolder, "copylarge.txt"); System.out.println("START: " + new java.util.Date()); if (!largeFile.getParentFile().exists()) { throw new IOException("Cannot create file " + largeFile + " as the parent directory does not exist"); } final OutputStream output = new BufferedOutputStream(Files.newOutputStream(largeFile.toPath())); try { TestUtils.generateTestData(output, FileUtils.ONE_GB); } finally { IOUtils.closeQuietly(output); } System.out.println("CREATED: " + new java.util.Date()); FileUtils.copyFile(largeFile, destination); System.out.println("COPIED: " + new java.util.Date()); assertTrue(destination.exists(), "Check Exist"); assertEquals(largeFile.length(), destination.length(), "Check Full copy"); } @Test public void testCopyFileToOutputStream() throws Exception { final ByteArrayOutputStream destination = new ByteArrayOutputStream(); FileUtils.copyFile(testFile1, destination); assertEquals(testFile1Size, destination.size(), "Check Full copy size"); final byte[] expected = FileUtils.readFileToByteArray(testFile1); assertArrayEquals(expected, destination.toByteArray(), "Check Full copy"); } @Test public void testCopyToDirectoryWithDirectory() throws IOException { final File destDirectory = new File(temporaryFolder, "destination"); if (!destDirectory.exists()) { destDirectory.mkdirs(); } // Create a test directory final File inputDirectory = new File(temporaryFolder, "input"); if (!inputDirectory.exists()) { inputDirectory.mkdirs(); } final File outputDirDestination = new File(destDirectory, inputDirectory.getName()); FileUtils.copyToDirectory(testFile1, inputDirectory); final File destFile1 = new File(outputDirDestination, testFile1.getName()); FileUtils.copyToDirectory(testFile2, inputDirectory); final File destFile2 = new File(outputDirDestination, testFile2.getName()); FileUtils.copyToDirectory(inputDirectory, destDirectory); // Check the directory was created assertTrue(outputDirDestination.exists(), "Check Exists"); assertTrue(outputDirDestination.isDirectory(), "Check Directory"); // Check each file assertTrue(destFile1.exists(), "Check Exists"); assertEquals(testFile1Size, destFile1.length(), "Check Full Copy"); assertTrue(destFile2.exists(), "Check Exists"); assertEquals(testFile2Size, destFile2.length(), "Check Full Copy"); } @Test public void testCopyToDirectoryWithFile() throws IOException { final File directory = new File(temporaryFolder, "subdir"); if (!directory.exists()) { directory.mkdirs(); } final File destination = new File(directory, testFile1.getName()); FileUtils.copyToDirectory(testFile1, directory); assertTrue(destination.exists(), "Check Exists"); assertEquals(testFile1Size, destination.length(), "Check Full Copy"); } @Test public void testCopyToDirectoryWithFileSourceDoesNotExist() { assertThrows(IOException.class, () -> FileUtils.copyToDirectory(new File(temporaryFolder, "doesNotExists"), temporaryFolder)); } // copyFile @Test public void testCopyToDirectoryWithFileSourceIsNull() { assertThrows(NullPointerException.class, () -> FileUtils.copyToDirectory((File) null, temporaryFolder)); } @Test public void testCopyToDirectoryWithIterable() throws IOException { final File directory = new File(temporaryFolder, "subdir"); if (!directory.exists()) { directory.mkdirs(); } final List input = new ArrayList<>(); input.add(testFile1); input.add(testFile2); final File destFile1 = new File(directory, testFile1.getName()); final File destFile2 = new File(directory, testFile2.getName()); FileUtils.copyToDirectory(input, directory); // Check each file assertTrue(destFile1.exists(), "Check Exists"); assertEquals(testFile1Size, destFile1.length(), "Check Full Copy"); assertTrue(destFile2.exists(), "Check Exists"); assertEquals(testFile2Size, destFile2.length(), "Check Full Copy"); } @Test public void testCopyToDirectoryWithIterableSourceDoesNotExist() { assertThrows(IOException.class, () -> FileUtils.copyToDirectory(Collections.singleton(new File(temporaryFolder, "doesNotExists")), temporaryFolder)); } @Test public void testCopyToDirectoryWithIterableSourceIsNull() { assertThrows(NullPointerException.class, () -> FileUtils.copyToDirectory((List) null, temporaryFolder)); } @Test public void testCopyToSelf() throws Exception { final File destination = new File(temporaryFolder, "copy3.txt"); //Prepare a test file FileUtils.copyFile(testFile1, destination); assertThrows(IllegalArgumentException.class, () -> FileUtils.copyFile(destination, destination)); } @Test public void testCopyURLToFile() throws Exception { // Creates file final File file = new File(temporaryFolder, getName()); file.deleteOnExit(); // Loads resource final String resourceName = "/java/lang/Object.class"; FileUtils.copyURLToFile(getClass().getResource(resourceName), file); // Tests that resuorce was copied correctly try (InputStream fis = Files.newInputStream(file.toPath())) { assertTrue(IOUtils.contentEquals(getClass().getResourceAsStream(resourceName), fis), "Content is not equal."); } //TODO Maybe test copy to itself like for copyFile() } @Test public void testCopyURLToFileWithTimeout() throws Exception { // Creates file final File file = new File(temporaryFolder, "testCopyURLToFileWithTimeout"); file.deleteOnExit(); // Loads resource final String resourceName = "/java/lang/Object.class"; FileUtils.copyURLToFile(getClass().getResource(resourceName), file, 500, 500); // Tests that resuorce was copied correctly try (InputStream fis = Files.newInputStream(file.toPath())) { assertTrue(IOUtils.contentEquals(getClass().getResourceAsStream(resourceName), fis), "Content is not equal."); } //TODO Maybe test copy to itself like for copyFile() } @Test public void testDecodeUrl() { assertEquals("", FileUtils.decodeUrl("")); assertEquals("foo", FileUtils.decodeUrl("foo")); assertEquals("+", FileUtils.decodeUrl("+")); assertEquals("% ", FileUtils.decodeUrl("%25%20")); assertEquals("%20", FileUtils.decodeUrl("%2520")); assertEquals("jar:file:/C:/dir/sub dir/1.0/foo-1.0.jar!/org/Bar.class", FileUtils .decodeUrl("jar:file:/C:/dir/sub%20dir/1.0/foo-1.0.jar!/org/Bar.class")); } @Test public void testDecodeUrlEncodingUtf8() { assertEquals("\u00E4\u00F6\u00FC\u00DF", FileUtils.decodeUrl("%C3%A4%C3%B6%C3%BC%C3%9F")); } @Test public void testDecodeUrlLenient() { assertEquals(" ", FileUtils.decodeUrl(" ")); assertEquals("\u00E4\u00F6\u00FC\u00DF", FileUtils.decodeUrl("\u00E4\u00F6\u00FC\u00DF")); assertEquals("%", FileUtils.decodeUrl("%")); assertEquals("% ", FileUtils.decodeUrl("%%20")); assertEquals("%2", FileUtils.decodeUrl("%2")); assertEquals("%2G", FileUtils.decodeUrl("%2G")); } @Test public void testDecodeUrlNullSafe() { assertNull(FileUtils.decodeUrl(null)); } @Test public void testDelete() throws Exception { assertEquals(testFile1, FileUtils.delete(testFile1)); assertThrows(IOException.class, () -> FileUtils.delete(new File("does not exist.nope"))); } @Test public void testDeleteDirectoryWithNonDirectory() throws Exception { try { FileUtils.deleteDirectory(testFile1); fail(); } catch (final IllegalArgumentException ex) { // expected } } @Test public void testDeleteQuietlyDir() throws IOException { final File testDirectory = new File(temporaryFolder, "testDeleteQuietlyDir"); final File testFile = new File(testDirectory, "testDeleteQuietlyFile"); testDirectory.mkdirs(); if (!testFile.getParentFile().exists()) { throw new IOException("Cannot create file " + testFile + " as the parent directory does not exist"); } final OutputStream output = new BufferedOutputStream(Files.newOutputStream(testFile.toPath())); try { TestUtils.generateTestData(output, 0); } finally { IOUtils.closeQuietly(output); } assertTrue(testDirectory.exists()); assertTrue(testFile.exists()); FileUtils.deleteQuietly(testDirectory); assertFalse(testDirectory.exists(), "Check No Exist"); assertFalse(testFile.exists(), "Check No Exist"); } @Test public void testDeleteQuietlyFile() throws IOException { final File testFile = new File(temporaryFolder, "testDeleteQuietlyFile"); if (!testFile.getParentFile().exists()) { throw new IOException("Cannot create file " + testFile + " as the parent directory does not exist"); } final OutputStream output = new BufferedOutputStream(Files.newOutputStream(testFile.toPath())); try { TestUtils.generateTestData(output, 0); } finally { IOUtils.closeQuietly(output); } assertTrue(testFile.exists()); FileUtils.deleteQuietly(testFile); assertFalse(testFile.exists(), "Check No Exist"); } @Test public void testDeleteQuietlyForNull() { try { FileUtils.deleteQuietly(null); } catch (final Exception ex) { fail(ex.getMessage()); } } @Test public void testDeleteQuietlyNonExistent() { final File testFile = new File("testDeleteQuietlyNonExistent"); assertFalse(testFile.exists()); try { FileUtils.deleteQuietly(testFile); } catch (final Exception ex) { fail(ex.getMessage()); } } /* * Test the FileUtils implementation. */ @Test public void testFileUtils() throws Exception { // Loads file from classpath final File file1 = new File(temporaryFolder, "test.txt"); final String filename = file1.getAbsolutePath(); //Create test file on-the-fly (used to be in CVS) try (OutputStream out = Files.newOutputStream(file1.toPath())) { out.write("This is a test".getBytes(StandardCharsets.UTF_8)); } final File file2 = new File(temporaryFolder, "test2.txt"); FileUtils.writeStringToFile(file2, filename, "UTF-8"); assertTrue(file2.exists()); assertTrue(file2.length() > 0); final String file2contents = FileUtils.readFileToString(file2, "UTF-8"); assertEquals(filename, file2contents, "Second file's contents correct"); assertTrue(file2.delete()); final String contents = FileUtils.readFileToString(new File(filename), "UTF-8"); assertEquals("This is a test", contents, "FileUtils.fileRead()"); } // copyToDirectory @Test public void testForceDeleteAFile1() throws Exception { final File destination = new File(temporaryFolder, "copy1.txt"); destination.createNewFile(); assertTrue(destination.exists(), "Copy1.txt doesn't exist to delete"); FileUtils.forceDelete(destination); assertFalse(destination.exists(), "Check No Exist"); } @Test public void testForceDeleteAFile2() throws Exception { final File destination = new File(temporaryFolder, "copy2.txt"); destination.createNewFile(); assertTrue(destination.exists(), "Copy2.txt doesn't exist to delete"); FileUtils.forceDelete(destination); assertFalse(destination.exists(), "Check No Exist"); } @Test public void testForceDeleteAFile3() throws Exception { final File destination = new File(temporaryFolder, "no_such_file"); assertFalse(destination.exists(), "Check No Exist"); try { FileUtils.forceDelete(destination); fail("Should generate FileNotFoundException"); } catch (final FileNotFoundException ignored) { } } @Test public void testForceDeleteDir() throws Exception { final File testDirectory = temporaryFolder; assertTrue(testDirectory.exists(), "TestDirectory must exist"); FileUtils.forceDelete(testDirectory); assertFalse(testDirectory.exists(), "TestDirectory must not exist"); } @Test public void testForceDeleteReadOnlyFile() throws Exception { File destination = File.createTempFile("test-", ".txt"); assertTrue(destination.setReadOnly()); assertTrue(destination.canRead()); assertFalse(destination.canWrite()); // sanity check that File.delete() in deletes read-only files. assertTrue(destination.delete()); destination = File.createTempFile("test-", ".txt"); // real test assertTrue(destination.setReadOnly()); assertTrue(destination.canRead()); assertFalse(destination.canWrite()); assertTrue(destination.exists(), "File doesn't exist to delete"); FileUtils.forceDelete(destination); assertFalse(destination.exists(), "Check deletion"); } @Test public void testForceMkdir() throws Exception { // Tests with existing directory FileUtils.forceMkdir(temporaryFolder); // Creates test file final File testFile = new File(temporaryFolder, getName()); testFile.deleteOnExit(); testFile.createNewFile(); assertTrue(testFile.exists(), "Test file does not exist."); // Tests with existing file assertThrows(IOException.class, () -> FileUtils.forceMkdir(testFile)); testFile.delete(); // Tests with non-existent directory FileUtils.forceMkdir(testFile); assertTrue(testFile.exists(), "Directory was not created."); } @Test public void testForceMkdirParent() throws Exception { // Tests with existing directory assertTrue(temporaryFolder.exists()); final File testParentDir = new File(temporaryFolder, "testForceMkdirParent"); testParentDir.delete(); assertFalse(testParentDir.exists()); final File testFile = new File(testParentDir, "test.txt"); assertFalse(testParentDir.exists()); assertFalse(testFile.exists()); // Create FileUtils.forceMkdirParent(testFile); assertTrue(testParentDir.exists()); assertFalse(testFile.exists()); // Again FileUtils.forceMkdirParent(testFile); assertTrue(testParentDir.exists()); assertFalse(testFile.exists()); } @Test public void testGetFile() { final File expected_A = new File("src"); final File expected_B = new File(expected_A, "main"); final File expected_C = new File(expected_B, "java"); assertEquals(expected_A, FileUtils.getFile("src"), "A"); assertEquals(expected_B, FileUtils.getFile("src", "main"), "B"); assertEquals(expected_C, FileUtils.getFile("src", "main", "java"), "C"); try { FileUtils.getFile((String[]) null); fail("Expected NullPointerException"); } catch (final NullPointerException e) { // expected } } // forceDelete @Test public void testGetFile_Parent() { final File parent = new File("parent"); final File expected_A = new File(parent, "src"); final File expected_B = new File(expected_A, "main"); final File expected_C = new File(expected_B, "java"); assertEquals(expected_A, FileUtils.getFile(parent, "src"), "A"); assertEquals(expected_B, FileUtils.getFile(parent, "src", "main"), "B"); assertEquals(expected_C, FileUtils.getFile(parent, "src", "main", "java"), "C"); try { FileUtils.getFile(parent, (String[]) null); fail("Expected NullPointerException"); } catch (final NullPointerException e) { // expected } try { FileUtils.getFile((File) null, "src"); fail("Expected NullPointerException"); } catch (final NullPointerException e) { // expected } } @Test public void testGetTempDirectory() { final File tempDirectory = new File(System.getProperty("java.io.tmpdir")); assertEquals(tempDirectory, FileUtils.getTempDirectory()); } @Test public void testGetTempDirectoryPath() { assertEquals(System.getProperty("java.io.tmpdir"), FileUtils.getTempDirectoryPath()); } // copyFileToDirectory @Test public void testGetUserDirectory() { final File userDirectory = new File(System.getProperty("user.home")); assertEquals(userDirectory, FileUtils.getUserDirectory()); } @Test public void testGetUserDirectoryPath() { assertEquals(System.getProperty("user.home"), FileUtils.getUserDirectoryPath()); } // forceDelete // This test relies on FileUtils.copyFile using File.length to check the output size @Test public void testIncorrectOutputSize() { final File inFile = new File("pom.xml"); final File outFile = new ShorterFile("target/pom.tmp"); // it will report a shorter file try { FileUtils.copyFile(inFile, outFile); fail("Expected IOException"); } catch (final Exception e) { final String msg = e.toString(); assertTrue(msg.contains("Failed to copy full contents"), msg); } finally { outFile.delete(); // tidy up } } @Test public void testIO276() throws Exception { final File dir = new File("target", "IO276"); assertTrue(dir.mkdirs(), dir + " should not be present"); final File file = new File(dir, "IO276.txt"); assertTrue(file.createNewFile(), file + " should not be present"); FileUtils.forceDeleteOnExit(dir); // If this does not work, test will fail next time (assuming target is not cleaned) } @Test public void testIO300() { final File testDirectory = temporaryFolder; final File src = new File(testDirectory, "dir1"); final File dest = new File(src, "dir2"); assertTrue(dest.mkdirs()); assertTrue(src.exists()); try { FileUtils.moveDirectoryToDirectory(src, dest, false); fail("expected IOException"); } catch (final IOException ioe) { // expected } assertTrue(src.exists()); } @Test public void testIsEmptyDirectory() throws IOException { final Path tempDir = Files.createTempDirectory(getClass().getCanonicalName()); final File tempDirAsFile = tempDir.toFile(); try { Assertions.assertTrue(FileUtils.isEmptyDirectory(tempDirAsFile)); } finally { Files.delete(tempDir); } Assertions.assertFalse(FileUtils.isEmptyDirectory(PathUtilsIsEmptyTest.DIR_SIZE_1.toFile())); } // isFileNewer / isFileOlder @Test public void testIsFileNewerOlder() throws Exception { final File reference = new File(temporaryFolder, "FileUtils-reference.txt"); final File oldFile = new File(temporaryFolder, "FileUtils-old.txt"); final File newFile = new File(temporaryFolder, "FileUtils-new.txt"); final File invalidFile = new File(temporaryFolder, "FileUtils-invalid-file.txt"); // Create Files if (!oldFile.getParentFile().exists()) { throw new IOException("Cannot create file " + oldFile + " as the parent directory does not exist"); } final OutputStream output1 = new BufferedOutputStream(Files.newOutputStream(oldFile.toPath())); try { TestUtils.generateTestData(output1, 0); } finally { IOUtils.closeQuietly(output1); } do { try { TestUtils.sleep(1000); } catch (final InterruptedException ie) { // ignore } if (!reference.getParentFile().exists()) { throw new IOException("Cannot create file " + reference + " as the parent directory does not exist"); } final OutputStream output = new BufferedOutputStream(Files.newOutputStream(reference.toPath())); try { TestUtils.generateTestData(output, 0); } finally { IOUtils.closeQuietly(output); } } while (getLastModifiedMillis(oldFile) == getLastModifiedMillis(reference)); final Date date = new Date(); final long now = date.getTime(); final Instant instant = date.toInstant(); final ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(instant, ZoneId.systemDefault()); final LocalDateTime localDateTime = zonedDateTime.toLocalDateTime(); final LocalDate localDate = zonedDateTime.toLocalDate(); final LocalDate localDatePlusDay = localDate.plusDays(1); final LocalTime localTime = LocalTime.ofSecondOfDay(0); do { try { TestUtils.sleep(1000); } catch (final InterruptedException ie) { // ignore } if (!newFile.getParentFile().exists()) { throw new IOException("Cannot create file " + newFile + " as the parent directory does not exist"); } final OutputStream output = new BufferedOutputStream(Files.newOutputStream(newFile.toPath())); try { TestUtils.generateTestData(output, 0); } finally { IOUtils.closeQuietly(output); } } while (getLastModifiedMillis(reference) == getLastModifiedMillis(newFile)); // Test isFileNewer() assertFalse(FileUtils.isFileNewer(oldFile, reference), "Old File - Newer - File"); assertFalse(FileUtils.isFileNewer(oldFile, date), "Old File - Newer - Date"); assertFalse(FileUtils.isFileNewer(oldFile, now), "Old File - Newer - Mili"); assertFalse(FileUtils.isFileNewer(oldFile, instant), "Old File - Newer - Instant"); assertFalse(FileUtils.isFileNewer(oldFile, zonedDateTime), "Old File - Newer - ZonedDateTime"); assertFalse(FileUtils.isFileNewer(oldFile, localDateTime), "Old File - Newer - LocalDateTime"); assertFalse(FileUtils.isFileNewer(oldFile, localDateTime, ZoneId.systemDefault()), "Old File - Newer - LocalDateTime,ZoneId"); assertFalse(FileUtils.isFileNewer(oldFile, localDate), "Old File - Newer - LocalDate"); assertTrue(FileUtils.isFileNewer(oldFile, localDate, localTime), "Old File - Newer - LocalDate,ZoneId"); assertFalse(FileUtils.isFileNewer(oldFile, localDatePlusDay), "Old File - Newer - LocalDate plus one day"); assertFalse(FileUtils.isFileNewer(oldFile, localDatePlusDay, localTime), "Old File - Newer - LocalDate plus one day,ZoneId"); assertTrue(FileUtils.isFileNewer(newFile, reference), "New File - Newer - File"); assertTrue(FileUtils.isFileNewer(newFile, date), "New File - Newer - Date"); assertTrue(FileUtils.isFileNewer(newFile, now), "New File - Newer - Mili"); assertTrue(FileUtils.isFileNewer(newFile, instant), "New File - Newer - Instant"); assertTrue(FileUtils.isFileNewer(newFile, zonedDateTime), "New File - Newer - ZonedDateTime"); assertTrue(FileUtils.isFileNewer(newFile, localDateTime), "New File - Newer - LocalDateTime"); assertTrue(FileUtils.isFileNewer(newFile, localDateTime, ZoneId.systemDefault()), "New File - Newer - LocalDateTime,ZoneId"); assertFalse(FileUtils.isFileNewer(newFile, localDate), "New File - Newer - LocalDate"); assertTrue(FileUtils.isFileNewer(newFile, localDate, localTime), "New File - Newer - LocalDate,ZoneId"); assertFalse(FileUtils.isFileNewer(newFile, localDatePlusDay), "New File - Newer - LocalDate plus one day"); assertFalse(FileUtils.isFileNewer(newFile, localDatePlusDay, localTime), "New File - Newer - LocalDate plus one day,ZoneId"); assertFalse(FileUtils.isFileNewer(invalidFile, reference), "Invalid - Newer - File"); final String invalidFileName = invalidFile.getName(); try { FileUtils.isFileNewer(newFile, invalidFile); fail("Should have cause IllegalArgumentException"); } catch (final IllegalArgumentException iae) { final String message = iae.getMessage(); assertTrue(message.contains(invalidFileName), "Message should contain: " + invalidFileName + " but was: " + message); } // Test isFileOlder() assertTrue(FileUtils.isFileOlder(oldFile, reference), "Old File - Older - File"); assertTrue(FileUtils.isFileOlder(oldFile, date), "Old File - Older - Date"); assertTrue(FileUtils.isFileOlder(oldFile, now), "Old File - Older - Mili"); assertTrue(FileUtils.isFileOlder(oldFile, instant), "Old File - Older - Instant"); assertTrue(FileUtils.isFileOlder(oldFile, zonedDateTime), "Old File - Older - ZonedDateTime"); assertTrue(FileUtils.isFileOlder(oldFile, localDateTime), "Old File - Older - LocalDateTime"); assertTrue(FileUtils.isFileOlder(oldFile, localDateTime, ZoneId.systemDefault()), "Old File - Older - LocalDateTime,LocalTime"); assertTrue(FileUtils.isFileOlder(oldFile, localDate), "Old File - Older - LocalDate"); assertFalse(FileUtils.isFileOlder(oldFile, localDate, localTime), "Old File - Older - LocalDate,ZoneId"); assertTrue(FileUtils.isFileOlder(oldFile, localDatePlusDay), "Old File - Older - LocalDate plus one day"); assertTrue(FileUtils.isFileOlder(oldFile, localDatePlusDay, localTime), "Old File - Older - LocalDate plus one day,LocalTime"); assertFalse(FileUtils.isFileOlder(newFile, reference), "New File - Older - File"); assertFalse(FileUtils.isFileOlder(newFile, date), "New File - Older - Date"); assertFalse(FileUtils.isFileOlder(newFile, now), "New File - Older - Mili"); assertFalse(FileUtils.isFileOlder(newFile, instant), "New File - Older - Instant"); assertFalse(FileUtils.isFileOlder(newFile, zonedDateTime), "New File - Older - ZonedDateTime"); assertFalse(FileUtils.isFileOlder(newFile, localDateTime), "New File - Older - LocalDateTime"); assertFalse(FileUtils.isFileOlder(newFile, localDateTime, ZoneId.systemDefault()), "New File - Older - LocalDateTime,ZoneId"); assertTrue(FileUtils.isFileOlder(newFile, localDate), "New File - Older - LocalDate"); assertFalse(FileUtils.isFileOlder(newFile, localDate, localTime), "New File - Older - LocalDate,LocalTime"); assertTrue(FileUtils.isFileOlder(newFile, localDatePlusDay), "New File - Older - LocalDate plus one day"); assertTrue(FileUtils.isFileOlder(newFile, localDatePlusDay, localTime), "New File - Older - LocalDate plus one day,LocalTime"); assertFalse(FileUtils.isFileOlder(invalidFile, reference), "Invalid - Older - File"); assertThrows(IllegalArgumentException.class, () -> FileUtils.isFileOlder(newFile, invalidFile)); try { FileUtils.isFileOlder(newFile, invalidFile); fail("Should have cause IllegalArgumentException"); } catch (final IllegalArgumentException iae) { final String message = iae.getMessage(); assertTrue(message.contains(invalidFileName), "Message should contain: " + invalidFileName + " but was: " + message); } // ----- Test isFileNewer() exceptions ----- // Null File assertThrows(NullPointerException.class, () -> FileUtils.isFileNewer(null, now)); // Null reference File assertThrows(NullPointerException.class, () -> FileUtils.isFileNewer(oldFile, (File) null)); // Invalid reference File assertThrows(IllegalArgumentException.class, () -> FileUtils.isFileNewer(oldFile, invalidFile)); // Null reference Date assertThrows(NullPointerException.class, () -> FileUtils.isFileNewer(oldFile, (Date) null)); // ----- Test isFileOlder() exceptions ----- // Null File assertThrows(NullPointerException.class, () -> FileUtils.isFileOlder(null, now)); // Null reference File assertThrows(NullPointerException.class, () -> FileUtils.isFileOlder(oldFile, (File) null)); // Null reference Date assertThrows(NullPointerException.class, () -> FileUtils.isFileOlder(oldFile, (Date) null)); // Invalid reference File assertThrows(IllegalArgumentException.class, () -> FileUtils.isFileOlder(oldFile, invalidFile)); } @Test public void testIsDirectory() throws IOException { assertFalse(FileUtils.isDirectory(null)); assertTrue(FileUtils.isDirectory(temporaryFolder)); assertFalse(FileUtils.isDirectory(testFile1)); final Path tempDir = Files.createTempDirectory(getClass().getCanonicalName()); final File tempDirAsFile = tempDir.toFile(); Files.delete(tempDir); assertFalse(FileUtils.isDirectory(tempDirAsFile)); } @Test public void testIsRegularFile() throws IOException { assertFalse(FileUtils.isRegularFile(null)); assertFalse(FileUtils.isRegularFile(temporaryFolder)); assertTrue(FileUtils.isRegularFile(testFile1)); Files.delete(testFile1.toPath()); assertFalse(FileUtils.isRegularFile(testFile1)); } @Test public void testIterateFiles() throws Exception { final File srcDir = temporaryFolder; final File subDir = new File(srcDir, "list_test"); final File subSubDir = new File(subDir, "subSubDir"); final File notSubSubDir = new File(subDir, "notSubSubDir"); assertTrue(subDir.mkdir()); assertTrue(subSubDir.mkdir()); assertTrue(notSubSubDir.mkdir()); Iterator iterator = null; try { // Need list to be appendable final List expectedFileNames = new ArrayList<>( Arrays.asList("a.txt", "b.txt", "c.txt", "d.txt", "e.txt", "f.txt")); final int[] fileSizes = {123, 234, 345, 456, 678, 789}; assertEquals(expectedFileNames.size(), fileSizes.length); Collections.sort(expectedFileNames); Arrays.sort(fileSizes); for (int i = 0; i < fileSizes.length; ++i) { TestUtils.generateTestData(new File(subDir, expectedFileNames.get(i)), fileSizes[i]); } // final String subSubFileName = "z.txt"; TestUtils.generateTestData(new File(subSubDir, subSubFileName), 1); expectedFileNames.add(subSubFileName); // final String notSubSubFileName = "not.txt"; TestUtils.generateTestData(new File(notSubSubDir, notSubSubFileName), 1); final WildcardFileFilter allFilesFileFilter = new WildcardFileFilter("*.*"); final NameFileFilter dirFilter = new NameFileFilter("subSubDir"); iterator = FileUtils.iterateFiles(subDir, allFilesFileFilter, dirFilter); final Map matchedFileNames = new HashMap<>(); final List actualFileNames = new ArrayList<>(); while (iterator.hasNext()) { boolean found = false; final String fileName = iterator.next().getName(); actualFileNames.add(fileName); for (int j = 0; !found && j < expectedFileNames.size(); ++j) { final String expectedFileName = expectedFileNames.get(j); if (expectedFileName.equals(fileName)) { matchedFileNames.put(expectedFileName, expectedFileName); found = true; } } } assertEquals(expectedFileNames.size(), matchedFileNames.size()); Collections.sort(actualFileNames); assertEquals(expectedFileNames, actualFileNames); } finally { consumeRemaining(iterator); notSubSubDir.delete(); subSubDir.delete(); subDir.delete(); } } @Test public void testIterateFilesAndDirs() throws IOException { final File srcDir = temporaryFolder; // temporaryFolder/srcDir // - subdir1 // -- subdir2 // --- a.txt // --- subdir3 // --- subdir4 final File subDir1 = new File(srcDir, "subdir1"); final File subDir2 = new File(subDir1, "subdir2"); final File subDir3 = new File(subDir2, "subdir3"); final File subDir4 = new File(subDir2, "subdir4"); assertTrue(subDir1.mkdir()); assertTrue(subDir2.mkdir()); assertTrue(subDir3.mkdir()); assertTrue(subDir4.mkdir()); final File someFile = new File(subDir2, "a.txt"); final WildcardFileFilter fileFilterAllFiles = new WildcardFileFilter("*.*"); final WildcardFileFilter fileFilterAllDirs = new WildcardFileFilter("*"); final WildcardFileFilter fileFilterExtTxt = new WildcardFileFilter("*.txt"); try { try (final OutputStream output = new BufferedOutputStream(Files.newOutputStream(someFile.toPath()))) { TestUtils.generateTestData(output, 100); } // // "*.*" and "*" Collection expectedFilesAndDirs = Arrays.asList(subDir1, subDir2, someFile, subDir3, subDir4); iterateFilesAndDirs(subDir1, fileFilterAllFiles, fileFilterAllDirs, expectedFilesAndDirs); // // "*.txt" and "*" final int filesCount; expectedFilesAndDirs = Arrays.asList(subDir1, subDir2, someFile, subDir3, subDir4); iterateFilesAndDirs(subDir1, fileFilterExtTxt, fileFilterAllDirs, expectedFilesAndDirs); // // "*.*" and "subdir2" expectedFilesAndDirs = Arrays.asList(subDir1, subDir2, someFile); iterateFilesAndDirs(subDir1, fileFilterAllFiles, new NameFileFilter("subdir2"), expectedFilesAndDirs); // // "*.txt" and "subdir2" expectedFilesAndDirs = Arrays.asList(subDir1, subDir2, someFile); iterateFilesAndDirs(subDir1, fileFilterExtTxt, new NameFileFilter("subdir2"), expectedFilesAndDirs); } finally { someFile.delete(); subDir4.delete(); subDir3.delete(); subDir2.delete(); subDir1.delete(); } } @Test public void testListFiles() throws Exception { final File srcDir = temporaryFolder; final File subDir = new File(srcDir, "list_test"); final File subDir2 = new File(subDir, "subdir"); subDir.mkdir(); subDir2.mkdir(); try { final String[] expectedFileNames = {"a.txt", "b.txt", "c.txt", "d.txt", "e.txt", "f.txt"}; final int[] fileSizes = {123, 234, 345, 456, 678, 789}; for (int i = 0; i < expectedFileNames.length; ++i) { final File theFile = new File(subDir, expectedFileNames[i]); if (!theFile.getParentFile().exists()) { throw new IOException("Cannot create file " + theFile + " as the parent directory does not exist"); } final BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(theFile.toPath())); try { TestUtils.generateTestData(output, fileSizes[i]); } finally { IOUtils.closeQuietly(output); } } final Collection actualFiles = FileUtils.listFiles(subDir, new WildcardFileFilter("*.*"), new WildcardFileFilter("*")); final int count = actualFiles.size(); final Object[] fileObjs = actualFiles.toArray(); assertEquals(expectedFileNames.length, actualFiles.size(), () -> actualFiles.toString()); final Map foundFileNames = new HashMap<>(); for (int i = 0; i < count; ++i) { boolean found = false; for (int j = 0; !found && j < expectedFileNames.length; ++j) { if (expectedFileNames[j].equals(((File) fileObjs[i]).getName())) { foundFileNames.put(expectedFileNames[j], expectedFileNames[j]); found = true; } } } assertEquals(foundFileNames.size(), expectedFileNames.length, () -> foundFileNames.toString()); } finally { subDir.delete(); } } @Test public void testListFilesWithDirs() throws IOException { final File srcDir = temporaryFolder; final File subDir1 = new File(srcDir, "subdir"); final File subDir2 = new File(subDir1, "subdir2"); subDir1.mkdir(); subDir2.mkdir(); try { final File someFile = new File(subDir2, "a.txt"); if (!someFile.getParentFile().exists()) { throw new IOException("Cannot create file " + someFile + " as the parent directory does not exist"); } final BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(someFile.toPath())); try { TestUtils.generateTestData(output, 100); } finally { IOUtils.closeQuietly(output); } final File subDir3 = new File(subDir2, "subdir3"); subDir3.mkdir(); final Collection files = FileUtils.listFilesAndDirs(subDir1, new WildcardFileFilter("*.*"), new WildcardFileFilter("*")); assertEquals(4, files.size()); assertTrue(files.contains(subDir1), "Should contain the directory."); assertTrue(files.contains(subDir2), "Should contain the directory."); assertTrue(files.contains(someFile), "Should contain the file."); assertTrue(files.contains(subDir3), "Should contain the directory."); } finally { subDir1.delete(); } } @Test public void testMoveDirectory_CopyDelete() throws Exception { final File dir = temporaryFolder; final File src = new File(dir, "testMoveDirectory2Source") { private static final long serialVersionUID = 1L; // Force renameTo to fail @Override public boolean renameTo(final File dest) { return false; } }; final File testDir = new File(src, "foo"); final File testFile = new File(testDir, "bar"); testDir.mkdirs(); if (!testFile.getParentFile().exists()) { throw new IOException("Cannot create file " + testFile + " as the parent directory does not exist"); } final OutputStream output = new BufferedOutputStream(Files.newOutputStream(testFile.toPath())); try { TestUtils.generateTestData(output, 0); } finally { IOUtils.closeQuietly(output); } final File destination = new File(dir, "testMoveDirectory1Dest"); FileUtils.deleteDirectory(destination); // Move the directory FileUtils.moveDirectory(src, destination); // Check results assertTrue(destination.exists(), "Check Exist"); assertFalse(src.exists(), "Original deleted"); final File movedDir = new File(destination, testDir.getName()); final File movedFile = new File(movedDir, testFile.getName()); assertTrue(movedDir.exists(), "Check dir moved"); assertTrue(movedFile.exists(), "Check file moved"); } @Test public void testMoveDirectory_Errors() throws Exception { assertThrows(NullPointerException.class, () -> FileUtils.moveDirectory(null, new File("foo"))); assertThrows(NullPointerException.class, () -> FileUtils.moveDirectory(new File("foo"), null)); try { FileUtils.moveDirectory(new File("nonexistant"), new File("foo")); fail("Expected FileNotFoundException for source"); } catch (final FileNotFoundException e) { // expected } final File testFile = new File(temporaryFolder, "testMoveDirectoryFile"); if (!testFile.getParentFile().exists()) { throw new IOException("Cannot create file " + testFile + " as the parent directory does not exist"); } final OutputStream output = new BufferedOutputStream(Files.newOutputStream(testFile.toPath())); try { TestUtils.generateTestData(output, 0); } finally { IOUtils.closeQuietly(output); } assertThrows(IllegalArgumentException.class, () -> FileUtils.moveDirectory(testFile, new File("foo"))); final File testSrcFile = new File(temporaryFolder, "testMoveDirectorySource"); final File testDestFile = new File(temporaryFolder, "testMoveDirectoryDest"); testSrcFile.mkdir(); testDestFile.mkdir(); try { FileUtils.moveDirectory(testSrcFile, testDestFile); fail("Expected FileExistsException when dest already exists"); } catch (final FileExistsException e) { // expected } } @Test public void testMoveDirectory_Rename() throws Exception { final File dir = temporaryFolder; final File src = new File(dir, "testMoveDirectory1Source"); final File testDir = new File(src, "foo"); final File testFile = new File(testDir, "bar"); testDir.mkdirs(); if (!testFile.getParentFile().exists()) { throw new IOException("Cannot create file " + testFile + " as the parent directory does not exist"); } final OutputStream output = new BufferedOutputStream(Files.newOutputStream(testFile.toPath())); try { TestUtils.generateTestData(output, 0); } finally { IOUtils.closeQuietly(output); } final File destination = new File(dir, "testMoveDirectory1Dest"); FileUtils.deleteDirectory(destination); // Move the directory FileUtils.moveDirectory(src, destination); // Check results assertTrue(destination.exists(), "Check Exist"); assertFalse(src.exists(), "Original deleted"); final File movedDir = new File(destination, testDir.getName()); final File movedFile = new File(movedDir, testFile.getName()); assertTrue(movedDir.exists(), "Check dir moved"); assertTrue(movedFile.exists(), "Check file moved"); } @Test public void testMoveDirectoryToDirectory() throws Exception { final File dir = temporaryFolder; final File src = new File(dir, "testMoveDirectory1Source"); final File testChildDir = new File(src, "foo"); final File testFile = new File(testChildDir, "bar"); testChildDir.mkdirs(); if (!testFile.getParentFile().exists()) { throw new IOException("Cannot create file " + testFile + " as the parent directory does not exist"); } final OutputStream output = new BufferedOutputStream(Files.newOutputStream(testFile.toPath())); try { TestUtils.generateTestData(output, 0); } finally { IOUtils.closeQuietly(output); } final File destDir = new File(dir, "testMoveDirectory1Dest"); FileUtils.deleteDirectory(destDir); assertFalse(destDir.exists(), "Check Exist before"); // Move the directory FileUtils.moveDirectoryToDirectory(src, destDir, true); // Check results assertTrue(destDir.exists(), "Check Exist after"); assertFalse(src.exists(), "Original deleted"); final File movedDir = new File(destDir, src.getName()); final File movedChildDir = new File(movedDir, testChildDir.getName()); final File movedFile = new File(movedChildDir, testFile.getName()); assertTrue(movedDir.exists(), "Check dir moved"); assertTrue(movedChildDir.exists(), "Check child dir moved"); assertTrue(movedFile.exists(), "Check file moved"); } @Test public void testMoveDirectoryToDirectory_Errors() throws Exception { assertThrows(NullPointerException.class, () -> FileUtils.moveDirectoryToDirectory(null, new File("foo"), true)); assertThrows(NullPointerException.class, () -> FileUtils.moveDirectoryToDirectory(new File("foo"), null, true)); final File testFile1 = new File(temporaryFolder, "testMoveFileFile1"); final File testFile2 = new File(temporaryFolder, "testMoveFileFile2"); if (!testFile1.getParentFile().exists()) { throw new IOException("Cannot create file " + testFile1 + " as the parent directory does not exist"); } final BufferedOutputStream output1 = new BufferedOutputStream(Files.newOutputStream(testFile1.toPath())); try { TestUtils.generateTestData(output1, 0); } finally { IOUtils.closeQuietly(output1); } if (!testFile2.getParentFile().exists()) { throw new IOException("Cannot create file " + testFile2 + " as the parent directory does not exist"); } final BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(testFile2.toPath())); try { TestUtils.generateTestData(output, 0); } finally { IOUtils.closeQuietly(output); } try { FileUtils.moveDirectoryToDirectory(testFile1, testFile2, true); fail("Expected IOException when dest not a directory"); } catch (final IOException e) { // expected } final File nonexistant = new File(temporaryFolder, "testMoveFileNonExistant"); try { FileUtils.moveDirectoryToDirectory(testFile1, nonexistant, false); fail("Expected IOException when dest does not exist and create=false"); } catch (final IOException e) { // expected } } @Test public void testMoveFile_CopyDelete() throws Exception { final File destination = new File(temporaryFolder, "move2.txt"); final File src = new File(testFile1.getAbsolutePath()) { private static final long serialVersionUID = 1L; // Force renameTo to fail, as if destination is on another // filesystem @Override public boolean renameTo(final File f) { return false; } }; FileUtils.moveFile(src, destination); assertTrue(destination.exists(), "Check Exist"); assertFalse(src.exists(), "Original deleted"); } @Test public void testMoveFile_CopyDelete_Failed() throws Exception { final File destination = new File(temporaryFolder, "move3.txt"); final File src = new File(testFile1.getAbsolutePath()) { private static final long serialVersionUID = 1L; // Force delete failure @Override public boolean delete() { return false; } // Force renameTo to fail, as if destination is on another // filesystem @Override public boolean renameTo(final File f) { return false; } }; assertThrows(IOException.class, () -> FileUtils.moveFile(src, destination)); // expected assertFalse(destination.exists(), "Check Rollback"); assertTrue(src.exists(), "Original exists"); } @Test public void testMoveFile_CopyDelete_WithFileDatePreservation() throws Exception { final File destination = new File(temporaryFolder, "move2.txt"); backDateFile10Minutes(testFile1); // set test file back 10 minutes final File src = new File(testFile1.getAbsolutePath()) { private static final long serialVersionUID = 1L; // Force renameTo to fail, as if destination is on another // filesystem @Override public boolean renameTo(final File f) { return false; } }; final long expected = getLastModifiedMillis(testFile1); FileUtils.moveFile(src, destination, StandardCopyOption.COPY_ATTRIBUTES); assertTrue(destination.exists(), "Check Exist"); assertFalse(src.exists(), "Original deleted"); final long destLastMod = getLastModifiedMillis(destination); final long delta = destLastMod - expected; assertEquals(expected, destLastMod, "Check last modified date same as input, delta " + delta); } @Test public void testMoveFile_CopyDelete_WithoutFileDatePreservation() throws Exception { final File destination = new File(temporaryFolder, "move2.txt"); backDateFile10Minutes(testFile1); // set test file back 10 minutes // destination file time should not be less than this (allowing for granularity) final long nowMillis = System.currentTimeMillis() - 1000L; final File src = new File(testFile1.getAbsolutePath()) { private static final long serialVersionUID = 1L; // Force renameTo to fail, as if destination is on another // filesystem @Override public boolean renameTo(final File f) { return false; } }; final long unexpectedMillis = getLastModifiedMillis(testFile1); FileUtils.moveFile(src, destination, PathUtils.EMPTY_COPY_OPTIONS); assertTrue(destination.exists(), "Check Exist"); assertFalse(src.exists(), "Original deleted"); // On Windows, the last modified time is copied by default. if (!SystemUtils.IS_OS_WINDOWS) { final long destLastModMillis = getLastModifiedMillis(destination); final long deltaMillis = destLastModMillis - unexpectedMillis; assertNotEquals(unexpectedMillis, destLastModMillis, "Check last modified date not same as input, delta " + deltaMillis); assertTrue(destLastModMillis > nowMillis, destLastModMillis + " > " + nowMillis + " (delta " + deltaMillis + ")"); } } @Test public void testMoveFile_Errors() throws Exception { assertThrows(NullPointerException.class, () -> FileUtils.moveFile(null, new File("foo"))); assertThrows(NullPointerException.class, () -> FileUtils.moveFile(new File("foo"), null)); try { FileUtils.moveFile(new File("nonexistant"), new File("foo")); fail("Expected FileNotFoundException for source"); } catch (final FileNotFoundException e) { // expected } assertThrows(IllegalArgumentException.class, () -> FileUtils.moveFile(temporaryFolder, new File("foo"))); final File testSourceFile = new File(temporaryFolder, "testMoveFileSource"); final File testDestFile = new File(temporaryFolder, "testMoveFileSource"); if (!testSourceFile.getParentFile().exists()) { throw new IOException("Cannot create file " + testSourceFile + " as the parent directory does not exist"); } final BufferedOutputStream output1 = new BufferedOutputStream(Files.newOutputStream(testSourceFile.toPath())); try { TestUtils.generateTestData(output1, 0); } finally { IOUtils.closeQuietly(output1); } if (!testDestFile.getParentFile().exists()) { throw new IOException("Cannot create file " + testDestFile + " as the parent directory does not exist"); } final BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(testDestFile.toPath())); try { TestUtils.generateTestData(output, 0); } finally { IOUtils.closeQuietly(output); } try { FileUtils.moveFile(testSourceFile, testDestFile); fail("Expected FileExistsException when dest already exists"); } catch (final FileExistsException e) { // expected } } @Test public void testMoveFile_Rename() throws Exception { final File destination = new File(temporaryFolder, "move1.txt"); FileUtils.moveFile(testFile1, destination); assertTrue(destination.exists(), "Check Exist"); assertFalse(testFile1.exists(), "Original deleted"); } @Test public void testMoveFileToDirectory() throws Exception { final File destDir = new File(temporaryFolder, "moveFileDestDir"); final File movedFile = new File(destDir, testFile1.getName()); assertFalse(destDir.exists(), "Check Exist before"); assertFalse(movedFile.exists(), "Check Exist before"); FileUtils.moveFileToDirectory(testFile1, destDir, true); assertTrue(movedFile.exists(), "Check Exist after"); assertFalse(testFile1.exists(), "Original deleted"); } @Test public void testMoveFileToDirectory_Errors() throws Exception { assertThrows(NullPointerException.class, () -> FileUtils.moveFileToDirectory(null, new File("foo"), true)); assertThrows(NullPointerException.class, () -> FileUtils.moveFileToDirectory(new File("foo"), null, true)); final File testFile1 = new File(temporaryFolder, "testMoveFileFile1"); final File testFile2 = new File(temporaryFolder, "testMoveFileFile2"); if (!testFile1.getParentFile().exists()) { throw new IOException("Cannot create file " + testFile1 + " as the parent directory does not exist"); } final BufferedOutputStream output1 = new BufferedOutputStream(Files.newOutputStream(testFile1.toPath())); try { TestUtils.generateTestData(output1, 0); } finally { IOUtils.closeQuietly(output1); } if (!testFile2.getParentFile().exists()) { throw new IOException("Cannot create file " + testFile2 + " as the parent directory does not exist"); } final BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(testFile2.toPath())); try { TestUtils.generateTestData(output, 0); } finally { IOUtils.closeQuietly(output); } assertThrows(IllegalArgumentException.class, () -> FileUtils.moveFileToDirectory(testFile1, testFile2, true)); final File nonexistant = new File(temporaryFolder, "testMoveFileNonExistant"); try { FileUtils.moveFileToDirectory(testFile1, nonexistant, false); fail("Expected IOException when dest does not exist and create=false"); } catch (final IOException e) { // expected } } @Test public void testMoveToDirectory() throws Exception { final File destDir = new File(temporaryFolder, "testMoveToDirectoryDestDir"); final File testDir = new File(temporaryFolder, "testMoveToDirectoryTestDir"); final File testFile = new File(temporaryFolder, "testMoveToDirectoryTestFile"); testDir.mkdirs(); if (!testFile.getParentFile().exists()) { throw new IOException("Cannot create file " + testFile + " as the parent directory does not exist"); } final BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(testFile.toPath())); try { TestUtils.generateTestData(output, 0); } finally { IOUtils.closeQuietly(output); } final File movedFile = new File(destDir, testFile.getName()); final File movedDir = new File(destDir, testFile.getName()); assertFalse(movedFile.exists(), "Check File Doesnt exist"); assertFalse(movedDir.exists(), "Check Dir Doesnt exist"); // Test moving a file FileUtils.moveToDirectory(testFile, destDir, true); assertTrue(movedFile.exists(), "Check File exists"); assertFalse(testFile.exists(), "Check Original File doesn't exist"); // Test moving a directory FileUtils.moveToDirectory(testDir, destDir, true); assertTrue(movedDir.exists(), "Check Dir exists"); assertFalse(testDir.exists(), "Check Original Dir doesn't exist"); } @Test public void testMoveToDirectory_Errors() throws Exception { try { FileUtils.moveDirectoryToDirectory(null, new File("foo"), true); fail("Expected NullPointerException when source is null"); } catch (final NullPointerException e) { // expected } try { FileUtils.moveDirectoryToDirectory(new File("foo"), null, true); fail("Expected NullPointerException when destination is null"); } catch (final NullPointerException e) { // expected } final File nonexistant = new File(temporaryFolder, "nonexistant"); final File destDir = new File(temporaryFolder, "MoveToDirectoryDestDir"); try { FileUtils.moveToDirectory(nonexistant, destDir, true); fail("Expected IOException when source does not exist"); } catch (final IOException e) { // expected } } @Test public void testReadFileToByteArray() throws Exception { final File file = new File(temporaryFolder, "read.txt"); final OutputStream out = Files.newOutputStream(file.toPath()); out.write(11); out.write(21); out.write(31); out.close(); final byte[] data = FileUtils.readFileToByteArray(file); assertEquals(3, data.length); assertEquals(11, data[0]); assertEquals(21, data[1]); assertEquals(31, data[2]); } @Test public void testReadFileToStringWithDefaultEncoding() throws Exception { final File file = new File(temporaryFolder, "read.obj"); final OutputStream out = Files.newOutputStream(file.toPath()); final byte[] text = "Hello /u1234".getBytes(); out.write(text); out.close(); final String data = FileUtils.readFileToString(file); assertEquals("Hello /u1234", data); } @Test public void testReadFileToStringWithEncoding() throws Exception { final File file = new File(temporaryFolder, "read.obj"); final OutputStream out = Files.newOutputStream(file.toPath()); final byte[] text = "Hello /u1234".getBytes(StandardCharsets.UTF_8); out.write(text); out.close(); final String data = FileUtils.readFileToString(file, "UTF8"); assertEquals("Hello /u1234", data); } @Test public void testReadLines() throws Exception { final File file = TestUtils.newFile(temporaryFolder, "lines.txt"); try { final String[] data = {"hello", "/u1234", "", "this is", "some text"}; TestUtils.createLineBasedFile(file, data); final List lines = FileUtils.readLines(file, "UTF-8"); assertEquals(Arrays.asList(data), lines); } finally { TestUtils.deleteFile(file); } } @Test public void testSizeOf() throws Exception { final File file = new File(temporaryFolder, getName()); // Null argument try { FileUtils.sizeOf(null); fail("Exception expected."); } catch (final NullPointerException ignore) { } // Non-existent file try { FileUtils.sizeOf(file); fail("Exception expected."); } catch (final IllegalArgumentException ignore) { } // Creates file file.createNewFile(); file.deleteOnExit(); // New file assertEquals(0, FileUtils.sizeOf(file)); file.delete(); // Existing file assertEquals(testFile1Size, FileUtils.sizeOf(testFile1), "Unexpected files size"); // Existing directory assertEquals(TEST_DIRECTORY_SIZE, FileUtils.sizeOf(temporaryFolder), "Unexpected directory size"); } @Test public void testSizeOfAsBigInteger() throws Exception { final File file = new File(temporaryFolder, getName()); // Null argument try { FileUtils.sizeOfAsBigInteger(null); fail("Exception expected."); } catch (final NullPointerException ignore) { } // Non-existent file try { FileUtils.sizeOfAsBigInteger(file); fail("Exception expected."); } catch (final IllegalArgumentException ignore) { } // Creates file file.createNewFile(); file.deleteOnExit(); // New file assertEquals(BigInteger.ZERO, FileUtils.sizeOfAsBigInteger(file)); file.delete(); // Existing file assertEquals(BigInteger.valueOf(testFile1Size), FileUtils.sizeOfAsBigInteger(testFile1), "Unexpected files size"); // Existing directory assertEquals(TEST_DIRECTORY_SIZE_BI, FileUtils.sizeOfAsBigInteger(temporaryFolder), "Unexpected directory size"); } @Test public void testSizeOfDirectory() throws Exception { final File file = new File(temporaryFolder, getName()); // Non-existent file try { FileUtils.sizeOfDirectory(file); fail("Exception expected."); } catch (final IllegalArgumentException ignore) { } // Creates file file.createNewFile(); // Existing file try { FileUtils.sizeOfDirectory(file); fail("Exception expected."); } catch (final IllegalArgumentException ignore) { } // Existing directory file.delete(); file.mkdir(); // Create a cyclic symlink this.createCircularSymLink(file); assertEquals(TEST_DIRECTORY_SIZE, FileUtils.sizeOfDirectory(file), "Unexpected directory size"); } @Test public void testSizeOfDirectoryAsBigInteger() throws Exception { final File file = new File(temporaryFolder, getName()); // Non-existent file try { FileUtils.sizeOfDirectoryAsBigInteger(file); fail("Exception expected."); } catch (final IllegalArgumentException ignore) { } // Creates file file.createNewFile(); file.deleteOnExit(); // Existing file try { FileUtils.sizeOfDirectoryAsBigInteger(file); fail("Exception expected."); } catch (final IllegalArgumentException ignore) { } // Existing directory file.delete(); file.mkdir(); this.createCircularSymLink(file); assertEquals(TEST_DIRECTORY_SIZE_BI, FileUtils.sizeOfDirectoryAsBigInteger(file), "Unexpected directory size"); // Existing directory which size is greater than zero file.delete(); file.mkdir(); final File nonEmptyFile = new File(file, "nonEmptyFile" + System.nanoTime()); if (!nonEmptyFile.getParentFile().exists()) { throw new IOException("Cannot create file " + nonEmptyFile + " as the parent directory does not exist"); } final OutputStream output = new BufferedOutputStream(Files.newOutputStream(nonEmptyFile.toPath())); try { TestUtils.generateTestData(output, TEST_DIRECTORY_SIZE_GT_ZERO_BI.longValue()); } finally { IOUtils.closeQuietly(output); } nonEmptyFile.deleteOnExit(); assertEquals(TEST_DIRECTORY_SIZE_GT_ZERO_BI, FileUtils.sizeOfDirectoryAsBigInteger(file), "Unexpected directory size"); nonEmptyFile.delete(); file.delete(); } @Test public void testToFile1() throws Exception { final URL url = new URL("file", null, "a/b/c/file.txt"); final File file = FileUtils.toFile(url); assertTrue(file.toString().contains("file.txt")); } @Test public void testToFile2() throws Exception { final URL url = new URL("file", null, "a/b/c/file%20n%61me%2520.tx%74"); final File file = FileUtils.toFile(url); assertTrue(file.toString().contains("file name%20.txt")); } @Test public void testToFile3() throws Exception { assertNull(FileUtils.toFile(null)); assertNull(FileUtils.toFile(new URL("http://jakarta.apache.org"))); } @Test public void testToFile4() throws Exception { final URL url = new URL("file", null, "a/b/c/file%%20%me.txt%"); final File file = FileUtils.toFile(url); assertTrue(file.toString().contains("file% %me.txt%")); } /* IO-252 */ @Test public void testToFile5() throws Exception { final URL url = new URL("file", null, "both%20are%20100%20%25%20true"); final File file = FileUtils.toFile(url); assertEquals("both are 100 % true", file.toString()); } @Test public void testToFiles1() throws Exception { final URL[] urls = { new URL("file", null, "file1.txt"), new URL("file", null, "file2.txt"), }; final File[] files = FileUtils.toFiles(urls); assertEquals(urls.length, files.length); assertTrue(files[0].toString().contains("file1.txt"), "File: " + files[0]); assertTrue(files[1].toString().contains("file2.txt"), "File: " + files[1]); } @Test public void testToFiles2() throws Exception { final URL[] urls = { new URL("file", null, "file1.txt"), null, }; final File[] files = FileUtils.toFiles(urls); assertEquals(urls.length, files.length); assertTrue(files[0].toString().contains("file1.txt"), "File: " + files[0]); assertNull(files[1], "File: " + files[1]); } @Test public void testToFiles3() throws Exception { final URL[] urls = null; final File[] files = FileUtils.toFiles(urls); assertEquals(0, files.length); } @Test public void testToFiles3a() throws Exception { final URL[] urls = {}; // empty array final File[] files = FileUtils.toFiles(urls); assertEquals(0, files.length); } @Test public void testToFiles4() throws Exception { final URL[] urls = { new URL("file", null, "file1.txt"), new URL("http", "jakarta.apache.org", "file1.txt"), }; try { FileUtils.toFiles(urls); fail(); } catch (final IllegalArgumentException ignore) { } } @Test public void testToFileUtf8() throws Exception { final URL url = new URL("file", null, "/home/%C3%A4%C3%B6%C3%BC%C3%9F"); final File file = FileUtils.toFile(url); assertTrue(file.toString().contains("\u00E4\u00F6\u00FC\u00DF")); } @Test public void testTouch() throws IOException { final File file = new File(temporaryFolder, "touch.txt"); if (file.exists()) { file.delete(); } assertFalse(file.exists(), "Bad test: test file still exists"); FileUtils.touch(file); assertTrue(file.exists(), "FileUtils.touch() created file"); final OutputStream out = Files.newOutputStream(file.toPath()); assertEquals(0, file.length(), "Created empty file."); out.write(0); out.close(); assertEquals(1, file.length(), "Wrote one byte to file"); final long y2k = new GregorianCalendar(2000, 0, 1).getTime().getTime(); final boolean res = setLastModifiedMillis(file, y2k); // 0L fails on Win98 assertTrue(res, "Bad test: set lastModified failed"); assertEquals(y2k, getLastModifiedMillis(file), "Bad test: set lastModified set incorrect value"); final long nowMillis = System.currentTimeMillis(); FileUtils.touch(file); assertEquals(1, file.length(), "FileUtils.touch() didn't empty the file."); assertNotEquals(y2k, getLastModifiedMillis(file), "FileUtils.touch() changed lastModified"); final int delta = 3000; assertTrue(getLastModifiedMillis(file) >= nowMillis - delta, "FileUtils.touch() changed lastModified to more than now-3s"); assertTrue(getLastModifiedMillis(file) <= nowMillis + delta, "FileUtils.touch() changed lastModified to less than now+3s"); } @Test public void testToURLs1() throws Exception { final File[] files = { new File(temporaryFolder, "file1.txt"), new File(temporaryFolder, "file2.txt"), new File(temporaryFolder, "test file.txt"), }; final URL[] urls = FileUtils.toURLs(files); assertEquals(files.length, urls.length); assertTrue(urls[0].toExternalForm().startsWith("file:")); assertTrue(urls[0].toExternalForm().contains("file1.txt")); assertTrue(urls[1].toExternalForm().startsWith("file:")); assertTrue(urls[1].toExternalForm().contains("file2.txt")); // Test escaped char assertTrue(urls[2].toExternalForm().startsWith("file:")); assertTrue(urls[2].toExternalForm().contains("test%20file.txt")); } @Test public void testToURLs3a() throws Exception { final File[] files = {}; // empty array final URL[] urls = FileUtils.toURLs(files); assertEquals(0, urls.length); } @Test public void testWrite_WithAppendOptionFalse_ShouldDeletePreviousFileLines() throws Exception { final File file = TestUtils.newFile(temporaryFolder, "lines.txt"); FileUtils.writeStringToFile(file, "This line was there before you..."); FileUtils.write(file, "this is brand new data", false); final String expected = "this is brand new data"; final String actual = FileUtils.readFileToString(file); assertEquals(expected, actual); } @Test public void testWrite_WithAppendOptionTrue_ShouldNotDeletePreviousFileLines() throws Exception { final File file = TestUtils.newFile(temporaryFolder, "lines.txt"); FileUtils.writeStringToFile(file, "This line was there before you..."); FileUtils.write(file, "this is brand new data", true); final String expected = "This line was there before you..." + "this is brand new data"; final String actual = FileUtils.readFileToString(file); assertEquals(expected, actual); } @Test public void testWriteByteArrayToFile() throws Exception { final File file = new File(temporaryFolder, "write.obj"); final byte[] data = {11, 21, 31}; FileUtils.writeByteArrayToFile(file, data); TestUtils.assertEqualContent(data, file); } @Test public void testWriteByteArrayToFile_WithAppendOptionFalse_ShouldDeletePreviousFileLines() throws Exception { final File file = TestUtils.newFile(temporaryFolder, "lines.txt"); FileUtils.writeStringToFile(file, "This line was there before you..."); FileUtils.writeByteArrayToFile(file, "this is brand new data".getBytes(), false); final String expected = "this is brand new data"; final String actual = FileUtils.readFileToString(file); assertEquals(expected, actual); } @Test public void testWriteByteArrayToFile_WithAppendOptionTrue_ShouldNotDeletePreviousFileLines() throws Exception { final File file = TestUtils.newFile(temporaryFolder, "lines.txt"); FileUtils.writeStringToFile(file, "This line was there before you..."); FileUtils.writeByteArrayToFile(file, "this is brand new data".getBytes(), true); final String expected = "This line was there before you..." + "this is brand new data"; final String actual = FileUtils.readFileToString(file); assertEquals(expected, actual); } @Test public void testWriteByteArrayToFile_WithOffsetAndLength() throws Exception { final File file = new File(temporaryFolder, "write.obj"); final byte[] data = {11, 21, 32, 41, 51}; final byte[] writtenData = new byte[3]; System.arraycopy(data, 1, writtenData, 0, 3); FileUtils.writeByteArrayToFile(file, data, 1, 3); TestUtils.assertEqualContent(writtenData, file); } @Test public void testWriteByteArrayToFile_WithOffsetAndLength_WithAppendOptionTrue_ShouldDeletePreviousFileLines() throws Exception { final File file = TestUtils.newFile(temporaryFolder, "lines.txt"); FileUtils.writeStringToFile(file, "This line was there before you..."); final byte[] data = "SKIP_THIS_this is brand new data_AND_SKIP_THIS".getBytes(StandardCharsets.UTF_8); FileUtils.writeByteArrayToFile(file, data, 10, 22, false); final String expected = "this is brand new data"; final String actual = FileUtils.readFileToString(file, StandardCharsets.UTF_8); assertEquals(expected, actual); } @Test public void testWriteByteArrayToFile_WithOffsetAndLength_WithAppendOptionTrue_ShouldNotDeletePreviousFileLines() throws Exception { final File file = TestUtils.newFile(temporaryFolder, "lines.txt"); FileUtils.writeStringToFile(file, "This line was there before you..."); final byte[] data = "SKIP_THIS_this is brand new data_AND_SKIP_THIS".getBytes(StandardCharsets.UTF_8); FileUtils.writeByteArrayToFile(file, data, 10, 22, true); final String expected = "This line was there before you..." + "this is brand new data"; final String actual = FileUtils.readFileToString(file, StandardCharsets.UTF_8); assertEquals(expected, actual); } @Test public void testWriteCharSequence1() throws Exception { final File file = new File(temporaryFolder, "write.txt"); FileUtils.write(file, "Hello /u1234", "UTF8"); final byte[] text = "Hello /u1234".getBytes(StandardCharsets.UTF_8); TestUtils.assertEqualContent(text, file); } @Test public void testWriteCharSequence2() throws Exception { final File file = new File(temporaryFolder, "write.txt"); FileUtils.write(file, "Hello /u1234", (String) null); final byte[] text = "Hello /u1234".getBytes(); TestUtils.assertEqualContent(text, file); } @Test public void testWriteLines_3arg_nullSeparator() throws Exception { final Object[] data = { "hello", new StringBuffer("world"), "", "this is", null, "some text"}; final List list = Arrays.asList(data); final File file = TestUtils.newFile(temporaryFolder, "lines.txt"); FileUtils.writeLines(file, "US-ASCII", list); final String expected = "hello" + System.lineSeparator() + "world" + System.lineSeparator() + System.lineSeparator() + "this is" + System.lineSeparator() + System.lineSeparator() + "some text" + System.lineSeparator(); final String actual = FileUtils.readFileToString(file, "US-ASCII"); assertEquals(expected, actual); } @Test public void testWriteLines_3argsWithAppendOptionFalse_ShouldDeletePreviousFileLines() throws Exception { final File file = TestUtils.newFile(temporaryFolder, "lines.txt"); FileUtils.writeStringToFile(file, "This line was there before you..."); final List linesToAppend = Arrays.asList("my first line", "The second Line"); FileUtils.writeLines(file, linesToAppend, false); final String expected = "my first line" + System.lineSeparator() + "The second Line" + System.lineSeparator(); final String actual = FileUtils.readFileToString(file); assertEquals(expected, actual); } @Test public void testWriteLines_3argsWithAppendOptionTrue_ShouldNotDeletePreviousFileLines() throws Exception { final File file = TestUtils.newFile(temporaryFolder, "lines.txt"); FileUtils.writeStringToFile(file, "This line was there before you..."); final List linesToAppend = Arrays.asList("my first line", "The second Line"); FileUtils.writeLines(file, linesToAppend, true); final String expected = "This line was there before you..." + "my first line" + System.lineSeparator() + "The second Line" + System.lineSeparator(); final String actual = FileUtils.readFileToString(file); assertEquals(expected, actual); } @Test public void testWriteLines_4arg() throws Exception { final Object[] data = { "hello", new StringBuffer("world"), "", "this is", null, "some text"}; final List list = Arrays.asList(data); final File file = TestUtils.newFile(temporaryFolder, "lines.txt"); FileUtils.writeLines(file, "US-ASCII", list, "*"); final String expected = "hello*world**this is**some text*"; final String actual = FileUtils.readFileToString(file, "US-ASCII"); assertEquals(expected, actual); } @Test public void testWriteLines_4arg_nullSeparator() throws Exception { final Object[] data = { "hello", new StringBuffer("world"), "", "this is", null, "some text"}; final List list = Arrays.asList(data); final File file = TestUtils.newFile(temporaryFolder, "lines.txt"); FileUtils.writeLines(file, "US-ASCII", list, null); final String expected = "hello" + System.lineSeparator() + "world" + System.lineSeparator() + System.lineSeparator() + "this is" + System.lineSeparator() + System.lineSeparator() + "some text" + System.lineSeparator(); final String actual = FileUtils.readFileToString(file, "US-ASCII"); assertEquals(expected, actual); } @Test public void testWriteLines_4arg_Writer_nullData() throws Exception { final File file = TestUtils.newFile(temporaryFolder, "lines.txt"); FileUtils.writeLines(file, "US-ASCII", null, "*"); assertEquals(0, file.length(), "Sizes differ"); } @Test public void testWriteLines_4argsWithAppendOptionFalse_ShouldDeletePreviousFileLines() throws Exception { final File file = TestUtils.newFile(temporaryFolder, "lines.txt"); FileUtils.writeStringToFile(file, "This line was there before you..."); final List linesToAppend = Arrays.asList("my first line", "The second Line"); FileUtils.writeLines(file, linesToAppend, null, false); final String expected = "my first line" + System.lineSeparator() + "The second Line" + System.lineSeparator(); final String actual = FileUtils.readFileToString(file); assertEquals(expected, actual); } @Test public void testWriteLines_4argsWithAppendOptionTrue_ShouldNotDeletePreviousFileLines() throws Exception { final File file = TestUtils.newFile(temporaryFolder, "lines.txt"); FileUtils.writeStringToFile(file, "This line was there before you..."); final List linesToAppend = Arrays.asList("my first line", "The second Line"); FileUtils.writeLines(file, linesToAppend, null, true); final String expected = "This line was there before you..." + "my first line" + System.lineSeparator() + "The second Line" + System.lineSeparator(); final String actual = FileUtils.readFileToString(file); assertEquals(expected, actual); } @Test public void testWriteLines_5argsWithAppendOptionFalse_ShouldDeletePreviousFileLines() throws Exception { final File file = TestUtils.newFile(temporaryFolder, "lines.txt"); FileUtils.writeStringToFile(file, "This line was there before you..."); final List linesToAppend = Arrays.asList("my first line", "The second Line"); FileUtils.writeLines(file, null, linesToAppend, null, false); final String expected = "my first line" + System.lineSeparator() + "The second Line" + System.lineSeparator(); final String actual = FileUtils.readFileToString(file); assertEquals(expected, actual); } @Test public void testWriteLines_5argsWithAppendOptionTrue_ShouldNotDeletePreviousFileLines() throws Exception { final File file = TestUtils.newFile(temporaryFolder, "lines.txt"); FileUtils.writeStringToFile(file, "This line was there before you..."); final List linesToAppend = Arrays.asList("my first line", "The second Line"); FileUtils.writeLines(file, null, linesToAppend, null, true); final String expected = "This line was there before you..." + "my first line" + System.lineSeparator() + "The second Line" + System.lineSeparator(); final String actual = FileUtils.readFileToString(file); assertEquals(expected, actual); } @Test public void testWriteLinesEncoding_WithAppendOptionFalse_ShouldDeletePreviousFileLines() throws Exception { final File file = TestUtils.newFile(temporaryFolder, "lines.txt"); FileUtils.writeStringToFile(file, "This line was there before you..."); final List linesToAppend = Arrays.asList("my first line", "The second Line"); FileUtils.writeLines(file, null, linesToAppend, false); final String expected = "my first line" + System.lineSeparator() + "The second Line" + System.lineSeparator(); final String actual = FileUtils.readFileToString(file); assertEquals(expected, actual); } @Test public void testWriteLinesEncoding_WithAppendOptionTrue_ShouldNotDeletePreviousFileLines() throws Exception { final File file = TestUtils.newFile(temporaryFolder, "lines.txt"); FileUtils.writeStringToFile(file, "This line was there before you..."); final List linesToAppend = Arrays.asList("my first line", "The second Line"); FileUtils.writeLines(file, null, linesToAppend, true); final String expected = "This line was there before you..." + "my first line" + System.lineSeparator() + "The second Line" + System.lineSeparator(); final String actual = FileUtils.readFileToString(file); assertEquals(expected, actual); } @Test public void testWriteStringToFile_WithAppendOptionFalse_ShouldDeletePreviousFileLines() throws Exception { final File file = TestUtils.newFile(temporaryFolder, "lines.txt"); FileUtils.writeStringToFile(file, "This line was there before you..."); FileUtils.writeStringToFile(file, "this is brand new data", false); final String expected = "this is brand new data"; final String actual = FileUtils.readFileToString(file); assertEquals(expected, actual); } @Test public void testWriteStringToFile_WithAppendOptionTrue_ShouldNotDeletePreviousFileLines() throws Exception { final File file = TestUtils.newFile(temporaryFolder, "lines.txt"); FileUtils.writeStringToFile(file, "This line was there before you..."); FileUtils.writeStringToFile(file, "this is brand new data", true); final String expected = "This line was there before you..." + "this is brand new data"; final String actual = FileUtils.readFileToString(file); assertEquals(expected, actual); } @Test public void testWriteStringToFile1() throws Exception { final File file = new File(temporaryFolder, "write.txt"); FileUtils.writeStringToFile(file, "Hello /u1234", "UTF8"); final byte[] text = "Hello /u1234".getBytes(StandardCharsets.UTF_8); TestUtils.assertEqualContent(text, file); } @Test public void testWriteStringToFile2() throws Exception { final File file = new File(temporaryFolder, "write.txt"); FileUtils.writeStringToFile(file, "Hello /u1234", (String) null); final byte[] text = "Hello /u1234".getBytes(); TestUtils.assertEqualContent(text, file); } @Test public void testWriteStringToFile3() throws Exception { final File file = new File(temporaryFolder, "write.txt"); FileUtils.writeStringToFile(file, "Hello /u1234", (Charset) null); final byte[] text = "Hello /u1234".getBytes(); TestUtils.assertEqualContent(text, file); } @Test public void testWriteStringToFileWithEncoding_WithAppendOptionFalse_ShouldDeletePreviousFileLines() throws Exception { final File file = TestUtils.newFile(temporaryFolder, "lines.txt"); FileUtils.writeStringToFile(file, "This line was there before you..."); FileUtils.writeStringToFile(file, "this is brand new data", (String) null, false); final String expected = "this is brand new data"; final String actual = FileUtils.readFileToString(file); assertEquals(expected, actual); } @Test public void testWriteStringToFileWithEncoding_WithAppendOptionTrue_ShouldNotDeletePreviousFileLines() throws Exception { final File file = TestUtils.newFile(temporaryFolder, "lines.txt"); FileUtils.writeStringToFile(file, "This line was there before you..."); FileUtils.writeStringToFile(file, "this is brand new data", (String) null, true); final String expected = "This line was there before you..." + "this is brand new data"; final String actual = FileUtils.readFileToString(file); assertEquals(expected, actual); } @Test public void testWriteWithEncoding_WithAppendOptionFalse_ShouldDeletePreviousFileLines() throws Exception { final File file = TestUtils.newFile(temporaryFolder, "lines.txt"); FileUtils.writeStringToFile(file, "This line was there before you..."); FileUtils.write(file, "this is brand new data", (String) null, false); final String expected = "this is brand new data"; final String actual = FileUtils.readFileToString(file); assertEquals(expected, actual); } @Test public void testWriteWithEncoding_WithAppendOptionTrue_ShouldNotDeletePreviousFileLines() throws Exception { final File file = TestUtils.newFile(temporaryFolder, "lines.txt"); FileUtils.writeStringToFile(file, "This line was there before you..."); FileUtils.write(file, "this is brand new data", (String) null, true); final String expected = "This line was there before you..." + "this is brand new data"; final String actual = FileUtils.readFileToString(file); assertEquals(expected, actual); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/FileUtilsWaitForTestCase.java0100644 0000000 0000000 00000004001 13612062727 031254 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.File; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicBoolean; import org.junit.jupiter.api.Test; /** * This is used to test FileUtils.waitFor() method for correctness. * * @see FileUtils */ public class FileUtilsWaitForTestCase { // This class has been broken out from FileUtilsTestCase // to solve issues as per BZ 38927 @Test public void testWaitFor() { FileUtils.waitFor(new File(""), -1); FileUtils.waitFor(new File(""), 2); } @Test public void testWaitForInterrupted() throws InterruptedException { final AtomicBoolean wasInterrupted = new AtomicBoolean(false); final CountDownLatch started = new CountDownLatch(1); final Runnable thread = () -> { started.countDown(); FileUtils.waitFor(new File(""), 2); wasInterrupted.set( Thread.currentThread().isInterrupted()); }; final Thread thread1 = new Thread(thread); thread1.start(); started.await(); thread1.interrupt(); thread1.join(); assertTrue( wasInterrupted.get() ); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/FilenameUtilsTestCase.java0100644 0000000 0000000 00000206223 13612062727 030633 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import java.io.BufferedOutputStream; import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import org.apache.commons.io.test.TestUtils; import org.apache.commons.lang3.SystemUtils; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; /** * This is used to test FilenameUtils for correctness. * * @see FilenameUtils */ public class FilenameUtilsTestCase { @TempDir public File temporaryFolder; private static final String SEP = "" + File.separatorChar; private static final boolean WINDOWS = File.separatorChar == '\\'; private File testFile1; private File testFile2; private int testFile1Size; private int testFile2Size; @BeforeEach public void setUp() throws Exception { testFile1 = File.createTempFile("test", "1", temporaryFolder); testFile2 = File.createTempFile("test", "2", temporaryFolder); testFile1Size = (int) testFile1.length(); testFile2Size = (int) testFile2.length(); if (!testFile1.getParentFile().exists()) { throw new IOException("Cannot create file " + testFile1 + " as the parent directory does not exist"); } try (final BufferedOutputStream output3 = new BufferedOutputStream(Files.newOutputStream(testFile1.toPath()))) { TestUtils.generateTestData(output3, testFile1Size); } if (!testFile2.getParentFile().exists()) { throw new IOException("Cannot create file " + testFile2 + " as the parent directory does not exist"); } try (final BufferedOutputStream output2 = new BufferedOutputStream(Files.newOutputStream(testFile2.toPath()))) { TestUtils.generateTestData(output2, testFile2Size); } if (!testFile1.getParentFile().exists()) { throw new IOException("Cannot create file " + testFile1 + " as the parent directory does not exist"); } try (final BufferedOutputStream output1 = new BufferedOutputStream(Files.newOutputStream(testFile1.toPath()))) { TestUtils.generateTestData(output1, testFile1Size); } if (!testFile2.getParentFile().exists()) { throw new IOException("Cannot create file " + testFile2 + " as the parent directory does not exist"); } try (final BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(testFile2.toPath()))) { TestUtils.generateTestData(output, testFile2Size); } } @Test public void testNormalize() { assertNull(FilenameUtils.normalize(null)); assertNull(FilenameUtils.normalize(":")); assertNull(FilenameUtils.normalize("1:\\a\\b\\c.txt")); assertNull(FilenameUtils.normalize("1:")); assertNull(FilenameUtils.normalize("1:a")); assertNull(FilenameUtils.normalize("\\\\\\a\\b\\c.txt")); assertNull(FilenameUtils.normalize("\\\\a")); assertEquals("a" + SEP + "b" + SEP + "c.txt", FilenameUtils.normalize("a\\b/c.txt")); assertEquals("" + SEP + "a" + SEP + "b" + SEP + "c.txt", FilenameUtils.normalize("\\a\\b/c.txt")); assertEquals("C:" + SEP + "a" + SEP + "b" + SEP + "c.txt", FilenameUtils.normalize("C:\\a\\b/c.txt")); assertEquals("" + SEP + "" + SEP + "server" + SEP + "a" + SEP + "b" + SEP + "c.txt", FilenameUtils.normalize("\\\\server\\a\\b/c.txt")); assertEquals("~" + SEP + "a" + SEP + "b" + SEP + "c.txt", FilenameUtils.normalize("~\\a\\b/c.txt")); assertEquals("~user" + SEP + "a" + SEP + "b" + SEP + "c.txt", FilenameUtils.normalize("~user\\a\\b/c.txt")); assertEquals("a" + SEP + "c", FilenameUtils.normalize("a/b/../c")); assertEquals("c", FilenameUtils.normalize("a/b/../../c")); assertEquals("c" + SEP, FilenameUtils.normalize("a/b/../../c/")); assertNull(FilenameUtils.normalize("a/b/../../../c")); assertEquals("a" + SEP, FilenameUtils.normalize("a/b/..")); assertEquals("a" + SEP, FilenameUtils.normalize("a/b/../")); assertEquals("", FilenameUtils.normalize("a/b/../..")); assertEquals("", FilenameUtils.normalize("a/b/../../")); assertNull(FilenameUtils.normalize("a/b/../../..")); assertEquals("a" + SEP + "d", FilenameUtils.normalize("a/b/../c/../d")); assertEquals("a" + SEP + "d" + SEP, FilenameUtils.normalize("a/b/../c/../d/")); assertEquals("a" + SEP + "b" + SEP + "d", FilenameUtils.normalize("a/b//d")); assertEquals("a" + SEP + "b" + SEP, FilenameUtils.normalize("a/b/././.")); assertEquals("a" + SEP + "b" + SEP, FilenameUtils.normalize("a/b/./././")); assertEquals("a" + SEP, FilenameUtils.normalize("./a/")); assertEquals("a", FilenameUtils.normalize("./a")); assertEquals("", FilenameUtils.normalize("./")); assertEquals("", FilenameUtils.normalize(".")); assertNull(FilenameUtils.normalize("../a")); assertNull(FilenameUtils.normalize("..")); assertEquals("", FilenameUtils.normalize("")); assertEquals(SEP + "a", FilenameUtils.normalize("/a")); assertEquals(SEP + "a" + SEP, FilenameUtils.normalize("/a/")); assertEquals(SEP + "a" + SEP + "c", FilenameUtils.normalize("/a/b/../c")); assertEquals(SEP + "c", FilenameUtils.normalize("/a/b/../../c")); assertNull(FilenameUtils.normalize("/a/b/../../../c")); assertEquals(SEP + "a" + SEP, FilenameUtils.normalize("/a/b/..")); assertEquals(SEP + "", FilenameUtils.normalize("/a/b/../..")); assertNull(FilenameUtils.normalize("/a/b/../../..")); assertEquals(SEP + "a" + SEP + "d", FilenameUtils.normalize("/a/b/../c/../d")); assertEquals(SEP + "a" + SEP + "b" + SEP + "d", FilenameUtils.normalize("/a/b//d")); assertEquals(SEP + "a" + SEP + "b" + SEP, FilenameUtils.normalize("/a/b/././.")); assertEquals(SEP + "a", FilenameUtils.normalize("/./a")); assertEquals(SEP + "", FilenameUtils.normalize("/./")); assertEquals(SEP + "", FilenameUtils.normalize("/.")); assertNull(FilenameUtils.normalize("/../a")); assertNull(FilenameUtils.normalize("/..")); assertEquals(SEP + "", FilenameUtils.normalize("/")); assertEquals("~" + SEP + "a", FilenameUtils.normalize("~/a")); assertEquals("~" + SEP + "a" + SEP, FilenameUtils.normalize("~/a/")); assertEquals("~" + SEP + "a" + SEP + "c", FilenameUtils.normalize("~/a/b/../c")); assertEquals("~" + SEP + "c", FilenameUtils.normalize("~/a/b/../../c")); assertNull(FilenameUtils.normalize("~/a/b/../../../c")); assertEquals("~" + SEP + "a" + SEP, FilenameUtils.normalize("~/a/b/..")); assertEquals("~" + SEP + "", FilenameUtils.normalize("~/a/b/../..")); assertNull(FilenameUtils.normalize("~/a/b/../../..")); assertEquals("~" + SEP + "a" + SEP + "d", FilenameUtils.normalize("~/a/b/../c/../d")); assertEquals("~" + SEP + "a" + SEP + "b" + SEP + "d", FilenameUtils.normalize("~/a/b//d")); assertEquals("~" + SEP + "a" + SEP + "b" + SEP, FilenameUtils.normalize("~/a/b/././.")); assertEquals("~" + SEP + "a", FilenameUtils.normalize("~/./a")); assertEquals("~" + SEP, FilenameUtils.normalize("~/./")); assertEquals("~" + SEP, FilenameUtils.normalize("~/.")); assertNull(FilenameUtils.normalize("~/../a")); assertNull(FilenameUtils.normalize("~/..")); assertEquals("~" + SEP, FilenameUtils.normalize("~/")); assertEquals("~" + SEP, FilenameUtils.normalize("~")); assertEquals("~user" + SEP + "a", FilenameUtils.normalize("~user/a")); assertEquals("~user" + SEP + "a" + SEP, FilenameUtils.normalize("~user/a/")); assertEquals("~user" + SEP + "a" + SEP + "c", FilenameUtils.normalize("~user/a/b/../c")); assertEquals("~user" + SEP + "c", FilenameUtils.normalize("~user/a/b/../../c")); assertNull(FilenameUtils.normalize("~user/a/b/../../../c")); assertEquals("~user" + SEP + "a" + SEP, FilenameUtils.normalize("~user/a/b/..")); assertEquals("~user" + SEP + "", FilenameUtils.normalize("~user/a/b/../..")); assertNull(FilenameUtils.normalize("~user/a/b/../../..")); assertEquals("~user" + SEP + "a" + SEP + "d", FilenameUtils.normalize("~user/a/b/../c/../d")); assertEquals("~user" + SEP + "a" + SEP + "b" + SEP + "d", FilenameUtils.normalize("~user/a/b//d")); assertEquals("~user" + SEP + "a" + SEP + "b" + SEP, FilenameUtils.normalize("~user/a/b/././.")); assertEquals("~user" + SEP + "a", FilenameUtils.normalize("~user/./a")); assertEquals("~user" + SEP + "", FilenameUtils.normalize("~user/./")); assertEquals("~user" + SEP + "", FilenameUtils.normalize("~user/.")); assertNull(FilenameUtils.normalize("~user/../a")); assertNull(FilenameUtils.normalize("~user/..")); assertEquals("~user" + SEP, FilenameUtils.normalize("~user/")); assertEquals("~user" + SEP, FilenameUtils.normalize("~user")); assertEquals("C:" + SEP + "a", FilenameUtils.normalize("C:/a")); assertEquals("C:" + SEP + "a" + SEP, FilenameUtils.normalize("C:/a/")); assertEquals("C:" + SEP + "a" + SEP + "c", FilenameUtils.normalize("C:/a/b/../c")); assertEquals("C:" + SEP + "c", FilenameUtils.normalize("C:/a/b/../../c")); assertNull(FilenameUtils.normalize("C:/a/b/../../../c")); assertEquals("C:" + SEP + "a" + SEP, FilenameUtils.normalize("C:/a/b/..")); assertEquals("C:" + SEP + "", FilenameUtils.normalize("C:/a/b/../..")); assertNull(FilenameUtils.normalize("C:/a/b/../../..")); assertEquals("C:" + SEP + "a" + SEP + "d", FilenameUtils.normalize("C:/a/b/../c/../d")); assertEquals("C:" + SEP + "a" + SEP + "b" + SEP + "d", FilenameUtils.normalize("C:/a/b//d")); assertEquals("C:" + SEP + "a" + SEP + "b" + SEP, FilenameUtils.normalize("C:/a/b/././.")); assertEquals("C:" + SEP + "a", FilenameUtils.normalize("C:/./a")); assertEquals("C:" + SEP + "", FilenameUtils.normalize("C:/./")); assertEquals("C:" + SEP + "", FilenameUtils.normalize("C:/.")); assertNull(FilenameUtils.normalize("C:/../a")); assertNull(FilenameUtils.normalize("C:/..")); assertEquals("C:" + SEP + "", FilenameUtils.normalize("C:/")); assertEquals("C:" + "a", FilenameUtils.normalize("C:a")); assertEquals("C:" + "a" + SEP, FilenameUtils.normalize("C:a/")); assertEquals("C:" + "a" + SEP + "c", FilenameUtils.normalize("C:a/b/../c")); assertEquals("C:" + "c", FilenameUtils.normalize("C:a/b/../../c")); assertNull(FilenameUtils.normalize("C:a/b/../../../c")); assertEquals("C:" + "a" + SEP, FilenameUtils.normalize("C:a/b/..")); assertEquals("C:" + "", FilenameUtils.normalize("C:a/b/../..")); assertNull(FilenameUtils.normalize("C:a/b/../../..")); assertEquals("C:" + "a" + SEP + "d", FilenameUtils.normalize("C:a/b/../c/../d")); assertEquals("C:" + "a" + SEP + "b" + SEP + "d", FilenameUtils.normalize("C:a/b//d")); assertEquals("C:" + "a" + SEP + "b" + SEP, FilenameUtils.normalize("C:a/b/././.")); assertEquals("C:" + "a", FilenameUtils.normalize("C:./a")); assertEquals("C:" + "", FilenameUtils.normalize("C:./")); assertEquals("C:" + "", FilenameUtils.normalize("C:.")); assertNull(FilenameUtils.normalize("C:../a")); assertNull(FilenameUtils.normalize("C:..")); assertEquals("C:" + "", FilenameUtils.normalize("C:")); assertEquals(SEP + SEP + "server" + SEP + "a", FilenameUtils.normalize("//server/a")); assertEquals(SEP + SEP + "server" + SEP + "a" + SEP, FilenameUtils.normalize("//server/a/")); assertEquals(SEP + SEP + "server" + SEP + "a" + SEP + "c", FilenameUtils.normalize("//server/a/b/../c")); assertEquals(SEP + SEP + "server" + SEP + "c", FilenameUtils.normalize("//server/a/b/../../c")); assertNull(FilenameUtils.normalize("//server/a/b/../../../c")); assertEquals(SEP + SEP + "server" + SEP + "a" + SEP, FilenameUtils.normalize("//server/a/b/..")); assertEquals(SEP + SEP + "server" + SEP + "", FilenameUtils.normalize("//server/a/b/../..")); assertNull(FilenameUtils.normalize("//server/a/b/../../..")); assertEquals(SEP + SEP + "server" + SEP + "a" + SEP + "d", FilenameUtils.normalize("//server/a/b/../c/../d")); assertEquals(SEP + SEP + "server" + SEP + "a" + SEP + "b" + SEP + "d", FilenameUtils.normalize("//server/a/b//d")); assertEquals(SEP + SEP + "server" + SEP + "a" + SEP + "b" + SEP, FilenameUtils.normalize("//server/a/b/././.")); assertEquals(SEP + SEP + "server" + SEP + "a", FilenameUtils.normalize("//server/./a")); assertEquals(SEP + SEP + "server" + SEP + "", FilenameUtils.normalize("//server/./")); assertEquals(SEP + SEP + "server" + SEP + "", FilenameUtils.normalize("//server/.")); assertNull(FilenameUtils.normalize("//server/../a")); assertNull(FilenameUtils.normalize("//server/..")); assertEquals(SEP + SEP + "server" + SEP + "", FilenameUtils.normalize("//server/")); assertEquals(SEP + SEP + "127.0.0.1" + SEP + "a" + SEP + "b" + SEP + "c.txt", FilenameUtils.normalize("\\\\127.0.0.1\\a\\b\\c.txt")); assertEquals(SEP + SEP + "::1" + SEP + "a" + SEP + "b" + SEP + "c.txt", FilenameUtils.normalize("\\\\::1\\a\\b\\c.txt")); assertEquals(SEP + SEP + "1::" + SEP + "a" + SEP + "b" + SEP + "c.txt", FilenameUtils.normalize("\\\\1::\\a\\b\\c.txt")); assertEquals(SEP + SEP + "server.example.org" + SEP + "a" + SEP + "b" + SEP + "c.txt", FilenameUtils.normalize("\\\\server.example.org\\a\\b\\c.txt")); assertEquals(SEP + SEP + "server.sub.example.org" + SEP + "a" + SEP + "b" + SEP + "c.txt", FilenameUtils.normalize("\\\\server.sub.example.org\\a\\b\\c.txt")); assertEquals(SEP + SEP + "server." + SEP + "a" + SEP + "b" + SEP + "c.txt", FilenameUtils.normalize("\\\\server.\\a\\b\\c.txt")); assertEquals(SEP + SEP + "1::127.0.0.1" + SEP + "a" + SEP + "b" + SEP + "c.txt", FilenameUtils.normalize("\\\\1::127.0.0.1\\a\\b\\c.txt")); // not valid IPv4 addresses but technically a valid "reg-name"s according to RFC1034 assertEquals(SEP + SEP + "127.0.0.256" + SEP + "a" + SEP + "b" + SEP + "c.txt", FilenameUtils.normalize("\\\\127.0.0.256\\a\\b\\c.txt")); assertEquals(SEP + SEP + "127.0.0.01" + SEP + "a" + SEP + "b" + SEP + "c.txt", FilenameUtils.normalize("\\\\127.0.0.01\\a\\b\\c.txt")); assertNull(FilenameUtils.normalize("\\\\-server\\a\\b\\c.txt")); assertNull(FilenameUtils.normalize("\\\\.\\a\\b\\c.txt")); assertNull(FilenameUtils.normalize("\\\\..\\a\\b\\c.txt")); assertNull(FilenameUtils.normalize("\\\\127.0..1\\a\\b\\c.txt")); assertNull(FilenameUtils.normalize("\\\\::1::2\\a\\b\\c.txt")); assertNull(FilenameUtils.normalize("\\\\:1\\a\\b\\c.txt")); assertNull(FilenameUtils.normalize("\\\\1:\\a\\b\\c.txt")); assertNull(FilenameUtils.normalize("\\\\1:2:3:4:5:6:7:8:9\\a\\b\\c.txt")); assertNull(FilenameUtils.normalize("\\\\g:2:3:4:5:6:7:8\\a\\b\\c.txt")); assertNull(FilenameUtils.normalize("\\\\1ffff:2:3:4:5:6:7:8\\a\\b\\c.txt")); assertNull(FilenameUtils.normalize("\\\\1:2\\a\\b\\c.txt")); // IO-556 assertNull(FilenameUtils.normalize("//../foo")); assertNull(FilenameUtils.normalize("\\\\..\\foo")); } /** */ @Test public void testNormalize_with_nullbytes() { try { assertEquals("a" + SEP + "b" + SEP + "c.txt", FilenameUtils.normalize("a\\b/c\u0000.txt")); } catch (final IllegalArgumentException ignore) { } try { assertEquals("a" + SEP + "b" + SEP + "c.txt", FilenameUtils.normalize("\u0000a\\b/c.txt")); } catch (final IllegalArgumentException ignore) { } } @Test public void testNormalizeUnixWin() { // Normalize (Unix Separator) assertEquals("/a/c/", FilenameUtils.normalize("/a/b/../c/", true)); assertEquals("/a/c/", FilenameUtils.normalize("\\a\\b\\..\\c\\", true)); // Normalize (Windows Separator) assertEquals("\\a\\c\\", FilenameUtils.normalize("/a/b/../c/", false)); assertEquals("\\a\\c\\", FilenameUtils.normalize("\\a\\b\\..\\c\\", false)); } @Test public void testNormalizeNoEndSeparator() { assertNull(FilenameUtils.normalizeNoEndSeparator(null)); assertNull(FilenameUtils.normalizeNoEndSeparator(":")); assertNull(FilenameUtils.normalizeNoEndSeparator("1:\\a\\b\\c.txt")); assertNull(FilenameUtils.normalizeNoEndSeparator("1:")); assertNull(FilenameUtils.normalizeNoEndSeparator("1:a")); assertNull(FilenameUtils.normalizeNoEndSeparator("\\\\\\a\\b\\c.txt")); assertNull(FilenameUtils.normalizeNoEndSeparator("\\\\a")); assertEquals("a" + SEP + "b" + SEP + "c.txt", FilenameUtils.normalizeNoEndSeparator("a\\b/c.txt")); assertEquals("" + SEP + "a" + SEP + "b" + SEP + "c.txt", FilenameUtils.normalizeNoEndSeparator("\\a\\b/c.txt")); assertEquals("C:" + SEP + "a" + SEP + "b" + SEP + "c.txt", FilenameUtils.normalizeNoEndSeparator("C:\\a\\b/c.txt")); assertEquals("" + SEP + "" + SEP + "server" + SEP + "a" + SEP + "b" + SEP + "c.txt", FilenameUtils.normalizeNoEndSeparator("\\\\server\\a\\b/c.txt")); assertEquals("~" + SEP + "a" + SEP + "b" + SEP + "c.txt", FilenameUtils.normalizeNoEndSeparator("~\\a\\b/c.txt")); assertEquals("~user" + SEP + "a" + SEP + "b" + SEP + "c.txt", FilenameUtils.normalizeNoEndSeparator("~user\\a\\b/c.txt")); assertEquals("C:" + SEP + "a" + SEP + "b" + SEP + "c.txt", FilenameUtils.normalizeNoEndSeparator("C:\\\\a\\\\b\\\\c.txt")); assertEquals("a" + SEP + "c", FilenameUtils.normalizeNoEndSeparator("a/b/../c")); assertEquals("c", FilenameUtils.normalizeNoEndSeparator("a/b/../../c")); assertEquals("c", FilenameUtils.normalizeNoEndSeparator("a/b/../../c/")); assertNull(FilenameUtils.normalizeNoEndSeparator("a/b/../../../c")); assertEquals("a", FilenameUtils.normalizeNoEndSeparator("a/b/..")); assertEquals("a", FilenameUtils.normalizeNoEndSeparator("a/b/../")); assertEquals("", FilenameUtils.normalizeNoEndSeparator("a/b/../..")); assertEquals("", FilenameUtils.normalizeNoEndSeparator("a/b/../../")); assertNull(FilenameUtils.normalizeNoEndSeparator("a/b/../../..")); assertEquals("a" + SEP + "d", FilenameUtils.normalizeNoEndSeparator("a/b/../c/../d")); assertEquals("a" + SEP + "d", FilenameUtils.normalizeNoEndSeparator("a/b/../c/../d/")); assertEquals("a" + SEP + "b" + SEP + "d", FilenameUtils.normalizeNoEndSeparator("a/b//d")); assertEquals("a" + SEP + "b", FilenameUtils.normalizeNoEndSeparator("a/b/././.")); assertEquals("a" + SEP + "b", FilenameUtils.normalizeNoEndSeparator("a/b/./././")); assertEquals("a", FilenameUtils.normalizeNoEndSeparator("./a/")); assertEquals("a", FilenameUtils.normalizeNoEndSeparator("./a")); assertEquals("", FilenameUtils.normalizeNoEndSeparator("./")); assertEquals("", FilenameUtils.normalizeNoEndSeparator(".")); assertNull(FilenameUtils.normalizeNoEndSeparator("../a")); assertNull(FilenameUtils.normalizeNoEndSeparator("..")); assertEquals("", FilenameUtils.normalizeNoEndSeparator("")); assertEquals(SEP + "a", FilenameUtils.normalizeNoEndSeparator("/a")); assertEquals(SEP + "a", FilenameUtils.normalizeNoEndSeparator("/a/")); assertEquals(SEP + "a" + SEP + "c", FilenameUtils.normalizeNoEndSeparator("/a/b/../c")); assertEquals(SEP + "c", FilenameUtils.normalizeNoEndSeparator("/a/b/../../c")); assertNull(FilenameUtils.normalizeNoEndSeparator("/a/b/../../../c")); assertEquals(SEP + "a", FilenameUtils.normalizeNoEndSeparator("/a/b/..")); assertEquals(SEP + "", FilenameUtils.normalizeNoEndSeparator("/a/b/../..")); assertNull(FilenameUtils.normalizeNoEndSeparator("/a/b/../../..")); assertEquals(SEP + "a" + SEP + "d", FilenameUtils.normalizeNoEndSeparator("/a/b/../c/../d")); assertEquals(SEP + "a" + SEP + "b" + SEP + "d", FilenameUtils.normalizeNoEndSeparator("/a/b//d")); assertEquals(SEP + "a" + SEP + "b", FilenameUtils.normalizeNoEndSeparator("/a/b/././.")); assertEquals(SEP + "a", FilenameUtils.normalizeNoEndSeparator("/./a")); assertEquals(SEP + "", FilenameUtils.normalizeNoEndSeparator("/./")); assertEquals(SEP + "", FilenameUtils.normalizeNoEndSeparator("/.")); assertNull(FilenameUtils.normalizeNoEndSeparator("/../a")); assertNull(FilenameUtils.normalizeNoEndSeparator("/..")); assertEquals(SEP + "", FilenameUtils.normalizeNoEndSeparator("/")); assertEquals("~" + SEP + "a", FilenameUtils.normalizeNoEndSeparator("~/a")); assertEquals("~" + SEP + "a", FilenameUtils.normalizeNoEndSeparator("~/a/")); assertEquals("~" + SEP + "a" + SEP + "c", FilenameUtils.normalizeNoEndSeparator("~/a/b/../c")); assertEquals("~" + SEP + "c", FilenameUtils.normalizeNoEndSeparator("~/a/b/../../c")); assertNull(FilenameUtils.normalizeNoEndSeparator("~/a/b/../../../c")); assertEquals("~" + SEP + "a", FilenameUtils.normalizeNoEndSeparator("~/a/b/..")); assertEquals("~" + SEP + "", FilenameUtils.normalizeNoEndSeparator("~/a/b/../..")); assertNull(FilenameUtils.normalizeNoEndSeparator("~/a/b/../../..")); assertEquals("~" + SEP + "a" + SEP + "d", FilenameUtils.normalizeNoEndSeparator("~/a/b/../c/../d")); assertEquals("~" + SEP + "a" + SEP + "b" + SEP + "d", FilenameUtils.normalizeNoEndSeparator("~/a/b//d")); assertEquals("~" + SEP + "a" + SEP + "b", FilenameUtils.normalizeNoEndSeparator("~/a/b/././.")); assertEquals("~" + SEP + "a", FilenameUtils.normalizeNoEndSeparator("~/./a")); assertEquals("~" + SEP, FilenameUtils.normalizeNoEndSeparator("~/./")); assertEquals("~" + SEP, FilenameUtils.normalizeNoEndSeparator("~/.")); assertNull(FilenameUtils.normalizeNoEndSeparator("~/../a")); assertNull(FilenameUtils.normalizeNoEndSeparator("~/..")); assertEquals("~" + SEP, FilenameUtils.normalizeNoEndSeparator("~/")); assertEquals("~" + SEP, FilenameUtils.normalizeNoEndSeparator("~")); assertEquals("~user" + SEP + "a", FilenameUtils.normalizeNoEndSeparator("~user/a")); assertEquals("~user" + SEP + "a", FilenameUtils.normalizeNoEndSeparator("~user/a/")); assertEquals("~user" + SEP + "a" + SEP + "c", FilenameUtils.normalizeNoEndSeparator("~user/a/b/../c")); assertEquals("~user" + SEP + "c", FilenameUtils.normalizeNoEndSeparator("~user/a/b/../../c")); assertNull(FilenameUtils.normalizeNoEndSeparator("~user/a/b/../../../c")); assertEquals("~user" + SEP + "a", FilenameUtils.normalizeNoEndSeparator("~user/a/b/..")); assertEquals("~user" + SEP + "", FilenameUtils.normalizeNoEndSeparator("~user/a/b/../..")); assertNull(FilenameUtils.normalizeNoEndSeparator("~user/a/b/../../..")); assertEquals("~user" + SEP + "a" + SEP + "d", FilenameUtils.normalizeNoEndSeparator("~user/a/b/../c/../d")); assertEquals("~user" + SEP + "a" + SEP + "b" + SEP + "d", FilenameUtils.normalizeNoEndSeparator("~user/a/b//d")); assertEquals("~user" + SEP + "a" + SEP + "b", FilenameUtils.normalizeNoEndSeparator("~user/a/b/././.")); assertEquals("~user" + SEP + "a", FilenameUtils.normalizeNoEndSeparator("~user/./a")); assertEquals("~user" + SEP + "", FilenameUtils.normalizeNoEndSeparator("~user/./")); assertEquals("~user" + SEP + "", FilenameUtils.normalizeNoEndSeparator("~user/.")); assertNull(FilenameUtils.normalizeNoEndSeparator("~user/../a")); assertNull(FilenameUtils.normalizeNoEndSeparator("~user/..")); assertEquals("~user" + SEP, FilenameUtils.normalizeNoEndSeparator("~user/")); assertEquals("~user" + SEP, FilenameUtils.normalizeNoEndSeparator("~user")); assertEquals("C:" + SEP + "a", FilenameUtils.normalizeNoEndSeparator("C:/a")); assertEquals("C:" + SEP + "a", FilenameUtils.normalizeNoEndSeparator("C:/a/")); assertEquals("C:" + SEP + "a" + SEP + "c", FilenameUtils.normalizeNoEndSeparator("C:/a/b/../c")); assertEquals("C:" + SEP + "c", FilenameUtils.normalizeNoEndSeparator("C:/a/b/../../c")); assertNull(FilenameUtils.normalizeNoEndSeparator("C:/a/b/../../../c")); assertEquals("C:" + SEP + "a", FilenameUtils.normalizeNoEndSeparator("C:/a/b/..")); assertEquals("C:" + SEP + "", FilenameUtils.normalizeNoEndSeparator("C:/a/b/../..")); assertNull(FilenameUtils.normalizeNoEndSeparator("C:/a/b/../../..")); assertEquals("C:" + SEP + "a" + SEP + "d", FilenameUtils.normalizeNoEndSeparator("C:/a/b/../c/../d")); assertEquals("C:" + SEP + "a" + SEP + "b" + SEP + "d", FilenameUtils.normalizeNoEndSeparator("C:/a/b//d")); assertEquals("C:" + SEP + "a" + SEP + "b", FilenameUtils.normalizeNoEndSeparator("C:/a/b/././.")); assertEquals("C:" + SEP + "a", FilenameUtils.normalizeNoEndSeparator("C:/./a")); assertEquals("C:" + SEP + "", FilenameUtils.normalizeNoEndSeparator("C:/./")); assertEquals("C:" + SEP + "", FilenameUtils.normalizeNoEndSeparator("C:/.")); assertNull(FilenameUtils.normalizeNoEndSeparator("C:/../a")); assertNull(FilenameUtils.normalizeNoEndSeparator("C:/..")); assertEquals("C:" + SEP + "", FilenameUtils.normalizeNoEndSeparator("C:/")); assertEquals("C:" + "a", FilenameUtils.normalizeNoEndSeparator("C:a")); assertEquals("C:" + "a", FilenameUtils.normalizeNoEndSeparator("C:a/")); assertEquals("C:" + "a" + SEP + "c", FilenameUtils.normalizeNoEndSeparator("C:a/b/../c")); assertEquals("C:" + "c", FilenameUtils.normalizeNoEndSeparator("C:a/b/../../c")); assertNull(FilenameUtils.normalizeNoEndSeparator("C:a/b/../../../c")); assertEquals("C:" + "a", FilenameUtils.normalizeNoEndSeparator("C:a/b/..")); assertEquals("C:" + "", FilenameUtils.normalizeNoEndSeparator("C:a/b/../..")); assertNull(FilenameUtils.normalizeNoEndSeparator("C:a/b/../../..")); assertEquals("C:" + "a" + SEP + "d", FilenameUtils.normalizeNoEndSeparator("C:a/b/../c/../d")); assertEquals("C:" + "a" + SEP + "b" + SEP + "d", FilenameUtils.normalizeNoEndSeparator("C:a/b//d")); assertEquals("C:" + "a" + SEP + "b", FilenameUtils.normalizeNoEndSeparator("C:a/b/././.")); assertEquals("C:" + "a", FilenameUtils.normalizeNoEndSeparator("C:./a")); assertEquals("C:" + "", FilenameUtils.normalizeNoEndSeparator("C:./")); assertEquals("C:" + "", FilenameUtils.normalizeNoEndSeparator("C:.")); assertNull(FilenameUtils.normalizeNoEndSeparator("C:../a")); assertNull(FilenameUtils.normalizeNoEndSeparator("C:..")); assertEquals("C:" + "", FilenameUtils.normalizeNoEndSeparator("C:")); assertEquals(SEP + SEP + "server" + SEP + "a", FilenameUtils.normalizeNoEndSeparator("//server/a")); assertEquals(SEP + SEP + "server" + SEP + "a", FilenameUtils.normalizeNoEndSeparator("//server/a/")); assertEquals(SEP + SEP + "server" + SEP + "a" + SEP + "c", FilenameUtils.normalizeNoEndSeparator("//server/a/b/../c")); assertEquals(SEP + SEP + "server" + SEP + "c", FilenameUtils.normalizeNoEndSeparator("//server/a/b/../../c")); assertNull(FilenameUtils.normalizeNoEndSeparator("//server/a/b/../../../c")); assertEquals(SEP + SEP + "server" + SEP + "a", FilenameUtils.normalizeNoEndSeparator("//server/a/b/..")); assertEquals(SEP + SEP + "server" + SEP + "", FilenameUtils.normalizeNoEndSeparator("//server/a/b/../..")); assertNull(FilenameUtils.normalizeNoEndSeparator("//server/a/b/../../..")); assertEquals(SEP + SEP + "server" + SEP + "a" + SEP + "d", FilenameUtils.normalizeNoEndSeparator("//server/a/b/../c/../d")); assertEquals(SEP + SEP + "server" + SEP + "a" + SEP + "b" + SEP + "d", FilenameUtils.normalizeNoEndSeparator("//server/a/b//d")); assertEquals(SEP + SEP + "server" + SEP + "a" + SEP + "b", FilenameUtils.normalizeNoEndSeparator("//server/a/b/././.")); assertEquals(SEP + SEP + "server" + SEP + "a", FilenameUtils.normalizeNoEndSeparator("//server/./a")); assertEquals(SEP + SEP + "server" + SEP + "", FilenameUtils.normalizeNoEndSeparator("//server/./")); assertEquals(SEP + SEP + "server" + SEP + "", FilenameUtils.normalizeNoEndSeparator("//server/.")); assertNull(FilenameUtils.normalizeNoEndSeparator("//server/../a")); assertNull(FilenameUtils.normalizeNoEndSeparator("//server/..")); assertEquals(SEP + SEP + "server" + SEP + "", FilenameUtils.normalizeNoEndSeparator("//server/")); } @Test public void testNormalizeNoEndSeparatorUnixWin() { // Normalize (Unix Separator) assertEquals("/a/c", FilenameUtils.normalizeNoEndSeparator("/a/b/../c/", true)); assertEquals("/a/c", FilenameUtils.normalizeNoEndSeparator("\\a\\b\\..\\c\\", true)); // Normalize (Windows Separator) assertEquals("\\a\\c", FilenameUtils.normalizeNoEndSeparator("/a/b/../c/", false)); assertEquals("\\a\\c", FilenameUtils.normalizeNoEndSeparator("\\a\\b\\..\\c\\", false)); } @Test public void testConcat() { assertNull(FilenameUtils.concat("", null)); assertNull(FilenameUtils.concat(null, null)); assertNull(FilenameUtils.concat(null, "")); assertNull(FilenameUtils.concat(null, "a")); assertEquals(SEP + "a", FilenameUtils.concat(null, "/a")); assertNull(FilenameUtils.concat("", ":")); // invalid prefix assertNull(FilenameUtils.concat(":", "")); // invalid prefix assertEquals("f" + SEP, FilenameUtils.concat("", "f/")); assertEquals("f", FilenameUtils.concat("", "f")); assertEquals("a" + SEP + "f" + SEP, FilenameUtils.concat("a/", "f/")); assertEquals("a" + SEP + "f", FilenameUtils.concat("a", "f")); assertEquals("a" + SEP + "b" + SEP + "f" + SEP, FilenameUtils.concat("a/b/", "f/")); assertEquals("a" + SEP + "b" + SEP + "f", FilenameUtils.concat("a/b", "f")); assertEquals("a" + SEP + "f" + SEP, FilenameUtils.concat("a/b/", "../f/")); assertEquals("a" + SEP + "f", FilenameUtils.concat("a/b", "../f")); assertEquals("a" + SEP + "c" + SEP + "g" + SEP, FilenameUtils.concat("a/b/../c/", "f/../g/")); assertEquals("a" + SEP + "c" + SEP + "g", FilenameUtils.concat("a/b/../c", "f/../g")); assertEquals("a" + SEP + "c.txt" + SEP + "f", FilenameUtils.concat("a/c.txt", "f")); assertEquals(SEP + "f" + SEP, FilenameUtils.concat("", "/f/")); assertEquals(SEP + "f", FilenameUtils.concat("", "/f")); assertEquals(SEP + "f" + SEP, FilenameUtils.concat("a/", "/f/")); assertEquals(SEP + "f", FilenameUtils.concat("a", "/f")); assertEquals(SEP + "c" + SEP + "d", FilenameUtils.concat("a/b/", "/c/d")); assertEquals("C:c" + SEP + "d", FilenameUtils.concat("a/b/", "C:c/d")); assertEquals("C:" + SEP + "c" + SEP + "d", FilenameUtils.concat("a/b/", "C:/c/d")); assertEquals("~" + SEP + "c" + SEP + "d", FilenameUtils.concat("a/b/", "~/c/d")); assertEquals("~user" + SEP + "c" + SEP + "d", FilenameUtils.concat("a/b/", "~user/c/d")); assertEquals("~" + SEP, FilenameUtils.concat("a/b/", "~")); assertEquals("~user" + SEP, FilenameUtils.concat("a/b/", "~user")); } @Test public void testSeparatorsToUnix() { assertNull(FilenameUtils.separatorsToUnix(null)); assertEquals("/a/b/c", FilenameUtils.separatorsToUnix("/a/b/c")); assertEquals("/a/b/c.txt", FilenameUtils.separatorsToUnix("/a/b/c.txt")); assertEquals("/a/b/c", FilenameUtils.separatorsToUnix("/a/b\\c")); assertEquals("/a/b/c", FilenameUtils.separatorsToUnix("\\a\\b\\c")); assertEquals("D:/a/b/c", FilenameUtils.separatorsToUnix("D:\\a\\b\\c")); } @Test public void testSeparatorsToWindows() { assertNull(FilenameUtils.separatorsToWindows(null)); assertEquals("\\a\\b\\c", FilenameUtils.separatorsToWindows("\\a\\b\\c")); assertEquals("\\a\\b\\c.txt", FilenameUtils.separatorsToWindows("\\a\\b\\c.txt")); assertEquals("\\a\\b\\c", FilenameUtils.separatorsToWindows("\\a\\b/c")); assertEquals("\\a\\b\\c", FilenameUtils.separatorsToWindows("/a/b/c")); assertEquals("D:\\a\\b\\c", FilenameUtils.separatorsToWindows("D:/a/b/c")); } @Test public void testSeparatorsToSystem() { if (WINDOWS) { assertNull(FilenameUtils.separatorsToSystem(null)); assertEquals("\\a\\b\\c", FilenameUtils.separatorsToSystem("\\a\\b\\c")); assertEquals("\\a\\b\\c.txt", FilenameUtils.separatorsToSystem("\\a\\b\\c.txt")); assertEquals("\\a\\b\\c", FilenameUtils.separatorsToSystem("\\a\\b/c")); assertEquals("\\a\\b\\c", FilenameUtils.separatorsToSystem("/a/b/c")); assertEquals("D:\\a\\b\\c", FilenameUtils.separatorsToSystem("D:/a/b/c")); } else { assertNull(FilenameUtils.separatorsToSystem(null)); assertEquals("/a/b/c", FilenameUtils.separatorsToSystem("/a/b/c")); assertEquals("/a/b/c.txt", FilenameUtils.separatorsToSystem("/a/b/c.txt")); assertEquals("/a/b/c", FilenameUtils.separatorsToSystem("/a/b\\c")); assertEquals("/a/b/c", FilenameUtils.separatorsToSystem("\\a\\b\\c")); assertEquals("D:/a/b/c", FilenameUtils.separatorsToSystem("D:\\a\\b\\c")); } } @Test public void testGetPrefixLength() { assertEquals(-1, FilenameUtils.getPrefixLength(null)); assertEquals(-1, FilenameUtils.getPrefixLength(":")); assertEquals(-1, FilenameUtils.getPrefixLength("1:\\a\\b\\c.txt")); assertEquals(-1, FilenameUtils.getPrefixLength("1:")); assertEquals(-1, FilenameUtils.getPrefixLength("1:a")); assertEquals(-1, FilenameUtils.getPrefixLength("\\\\\\a\\b\\c.txt")); assertEquals(-1, FilenameUtils.getPrefixLength("\\\\a")); assertEquals(0, FilenameUtils.getPrefixLength("")); assertEquals(1, FilenameUtils.getPrefixLength("\\")); if (SystemUtils.IS_OS_WINDOWS) { assertEquals(2, FilenameUtils.getPrefixLength("C:")); } if (SystemUtils.IS_OS_LINUX) { assertEquals(0, FilenameUtils.getPrefixLength("C:")); } assertEquals(3, FilenameUtils.getPrefixLength("C:\\")); assertEquals(9, FilenameUtils.getPrefixLength("//server/")); assertEquals(2, FilenameUtils.getPrefixLength("~")); assertEquals(2, FilenameUtils.getPrefixLength("~/")); assertEquals(6, FilenameUtils.getPrefixLength("~user")); assertEquals(6, FilenameUtils.getPrefixLength("~user/")); assertEquals(0, FilenameUtils.getPrefixLength("a\\b\\c.txt")); assertEquals(1, FilenameUtils.getPrefixLength("\\a\\b\\c.txt")); assertEquals(2, FilenameUtils.getPrefixLength("C:a\\b\\c.txt")); assertEquals(3, FilenameUtils.getPrefixLength("C:\\a\\b\\c.txt")); assertEquals(9, FilenameUtils.getPrefixLength("\\\\server\\a\\b\\c.txt")); assertEquals(0, FilenameUtils.getPrefixLength("a/b/c.txt")); assertEquals(1, FilenameUtils.getPrefixLength("/a/b/c.txt")); assertEquals(3, FilenameUtils.getPrefixLength("C:/a/b/c.txt")); assertEquals(9, FilenameUtils.getPrefixLength("//server/a/b/c.txt")); assertEquals(2, FilenameUtils.getPrefixLength("~/a/b/c.txt")); assertEquals(6, FilenameUtils.getPrefixLength("~user/a/b/c.txt")); assertEquals(0, FilenameUtils.getPrefixLength("a\\b\\c.txt")); assertEquals(1, FilenameUtils.getPrefixLength("\\a\\b\\c.txt")); assertEquals(2, FilenameUtils.getPrefixLength("~\\a\\b\\c.txt")); assertEquals(6, FilenameUtils.getPrefixLength("~user\\a\\b\\c.txt")); assertEquals(9, FilenameUtils.getPrefixLength("//server/a/b/c.txt")); assertEquals(-1, FilenameUtils.getPrefixLength("\\\\\\a\\b\\c.txt")); assertEquals(-1, FilenameUtils.getPrefixLength("///a/b/c.txt")); assertEquals(1, FilenameUtils.getPrefixLength("/:foo")); assertEquals(1, FilenameUtils.getPrefixLength("/:/")); assertEquals(1, FilenameUtils.getPrefixLength("/:::::::.txt")); assertEquals(12, FilenameUtils.getPrefixLength("\\\\127.0.0.1\\a\\b\\c.txt")); assertEquals(6, FilenameUtils.getPrefixLength("\\\\::1\\a\\b\\c.txt")); assertEquals(21, FilenameUtils.getPrefixLength("\\\\server.example.org\\a\\b\\c.txt")); assertEquals(10, FilenameUtils.getPrefixLength("\\\\server.\\a\\b\\c.txt")); assertEquals(-1, FilenameUtils.getPrefixLength("\\\\-server\\a\\b\\c.txt")); assertEquals(-1, FilenameUtils.getPrefixLength("\\\\.\\a\\b\\c.txt")); assertEquals(-1, FilenameUtils.getPrefixLength("\\\\..\\a\\b\\c.txt")); } @Test public void testIndexOfLastSeparator() { assertEquals(-1, FilenameUtils.indexOfLastSeparator(null)); assertEquals(-1, FilenameUtils.indexOfLastSeparator("noseperator.inthispath")); assertEquals(3, FilenameUtils.indexOfLastSeparator("a/b/c")); assertEquals(3, FilenameUtils.indexOfLastSeparator("a\\b\\c")); } @Test public void testIndexOfExtension() { assertEquals(-1, FilenameUtils.indexOfExtension(null)); assertEquals(-1, FilenameUtils.indexOfExtension("file")); assertEquals(4, FilenameUtils.indexOfExtension("file.txt")); assertEquals(13, FilenameUtils.indexOfExtension("a.txt/b.txt/c.txt")); assertEquals(-1, FilenameUtils.indexOfExtension("a/b/c")); assertEquals(-1, FilenameUtils.indexOfExtension("a\\b\\c")); assertEquals(-1, FilenameUtils.indexOfExtension("a/b.notextension/c")); assertEquals(-1, FilenameUtils.indexOfExtension("a\\b.notextension\\c")); if (FilenameUtils.isSystemWindows()) { // Special case handling for NTFS ADS names try { FilenameUtils.indexOfExtension("foo.exe:bar.txt"); throw new AssertionError("Expected Exception"); } catch (final IllegalArgumentException e) { assertEquals("NTFS ADS separator (':') in file name is forbidden.", e.getMessage()); } } else { // Upwards compatibility on other systems assertEquals(11, FilenameUtils.indexOfExtension("foo.exe:bar.txt")); } } @Test public void testGetPrefix() { assertNull(FilenameUtils.getPrefix(null)); assertNull(FilenameUtils.getPrefix(":")); assertNull(FilenameUtils.getPrefix("1:\\a\\b\\c.txt")); assertNull(FilenameUtils.getPrefix("1:")); assertNull(FilenameUtils.getPrefix("1:a")); assertNull(FilenameUtils.getPrefix("\\\\\\a\\b\\c.txt")); assertNull(FilenameUtils.getPrefix("\\\\a")); assertEquals("", FilenameUtils.getPrefix("")); assertEquals("\\", FilenameUtils.getPrefix("\\")); if (SystemUtils.IS_OS_WINDOWS) { assertEquals("C:", FilenameUtils.getPrefix("C:")); } if (SystemUtils.IS_OS_LINUX) { assertEquals("", FilenameUtils.getPrefix("C:")); } assertEquals("C:\\", FilenameUtils.getPrefix("C:\\")); assertEquals("//server/", FilenameUtils.getPrefix("//server/")); assertEquals("~/", FilenameUtils.getPrefix("~")); assertEquals("~/", FilenameUtils.getPrefix("~/")); assertEquals("~user/", FilenameUtils.getPrefix("~user")); assertEquals("~user/", FilenameUtils.getPrefix("~user/")); assertEquals("", FilenameUtils.getPrefix("a\\b\\c.txt")); assertEquals("\\", FilenameUtils.getPrefix("\\a\\b\\c.txt")); assertEquals("C:\\", FilenameUtils.getPrefix("C:\\a\\b\\c.txt")); assertEquals("\\\\server\\", FilenameUtils.getPrefix("\\\\server\\a\\b\\c.txt")); assertEquals("", FilenameUtils.getPrefix("a/b/c.txt")); assertEquals("/", FilenameUtils.getPrefix("/a/b/c.txt")); assertEquals("C:/", FilenameUtils.getPrefix("C:/a/b/c.txt")); assertEquals("//server/", FilenameUtils.getPrefix("//server/a/b/c.txt")); assertEquals("~/", FilenameUtils.getPrefix("~/a/b/c.txt")); assertEquals("~user/", FilenameUtils.getPrefix("~user/a/b/c.txt")); assertEquals("", FilenameUtils.getPrefix("a\\b\\c.txt")); assertEquals("\\", FilenameUtils.getPrefix("\\a\\b\\c.txt")); assertEquals("~\\", FilenameUtils.getPrefix("~\\a\\b\\c.txt")); assertEquals("~user\\", FilenameUtils.getPrefix("~user\\a\\b\\c.txt")); } @Test public void testGetPrefix_with_nullbyte() { try { assertEquals("~user\\", FilenameUtils.getPrefix("~u\u0000ser\\a\\b\\c.txt")); } catch (final IllegalArgumentException ignore) { } } @Test public void testGetPath() { assertNull(FilenameUtils.getPath(null)); assertEquals("", FilenameUtils.getPath("noseperator.inthispath")); assertEquals("", FilenameUtils.getPath("/noseperator.inthispath")); assertEquals("", FilenameUtils.getPath("\\noseperator.inthispath")); assertEquals("a/b/", FilenameUtils.getPath("a/b/c.txt")); assertEquals("a/b/", FilenameUtils.getPath("a/b/c")); assertEquals("a/b/c/", FilenameUtils.getPath("a/b/c/")); assertEquals("a\\b\\", FilenameUtils.getPath("a\\b\\c")); assertNull(FilenameUtils.getPath(":")); assertNull(FilenameUtils.getPath("1:/a/b/c.txt")); assertNull(FilenameUtils.getPath("1:")); assertNull(FilenameUtils.getPath("1:a")); assertNull(FilenameUtils.getPath("///a/b/c.txt")); assertNull(FilenameUtils.getPath("//a")); assertEquals("", FilenameUtils.getPath("")); assertEquals("", FilenameUtils.getPath("C:")); assertEquals("", FilenameUtils.getPath("C:/")); assertEquals("", FilenameUtils.getPath("//server/")); assertEquals("", FilenameUtils.getPath("~")); assertEquals("", FilenameUtils.getPath("~/")); assertEquals("", FilenameUtils.getPath("~user")); assertEquals("", FilenameUtils.getPath("~user/")); assertEquals("a/b/", FilenameUtils.getPath("a/b/c.txt")); assertEquals("a/b/", FilenameUtils.getPath("/a/b/c.txt")); assertEquals("", FilenameUtils.getPath("C:a")); assertEquals("a/b/", FilenameUtils.getPath("C:a/b/c.txt")); assertEquals("a/b/", FilenameUtils.getPath("C:/a/b/c.txt")); assertEquals("a/b/", FilenameUtils.getPath("//server/a/b/c.txt")); assertEquals("a/b/", FilenameUtils.getPath("~/a/b/c.txt")); assertEquals("a/b/", FilenameUtils.getPath("~user/a/b/c.txt")); } @Test public void testGetPath_with_nullbyte() { assertThrows(IllegalArgumentException.class, () -> FilenameUtils.getPath("~user/a/\u0000b/c.txt")); } @Test public void testGetPathNoEndSeparator() { assertNull(FilenameUtils.getPath(null)); assertEquals("", FilenameUtils.getPath("noseperator.inthispath")); assertEquals("", FilenameUtils.getPathNoEndSeparator("/noseperator.inthispath")); assertEquals("", FilenameUtils.getPathNoEndSeparator("\\noseperator.inthispath")); assertEquals("a/b", FilenameUtils.getPathNoEndSeparator("a/b/c.txt")); assertEquals("a/b", FilenameUtils.getPathNoEndSeparator("a/b/c")); assertEquals("a/b/c", FilenameUtils.getPathNoEndSeparator("a/b/c/")); assertEquals("a\\b", FilenameUtils.getPathNoEndSeparator("a\\b\\c")); assertNull(FilenameUtils.getPathNoEndSeparator(":")); assertNull(FilenameUtils.getPathNoEndSeparator("1:/a/b/c.txt")); assertNull(FilenameUtils.getPathNoEndSeparator("1:")); assertNull(FilenameUtils.getPathNoEndSeparator("1:a")); assertNull(FilenameUtils.getPathNoEndSeparator("///a/b/c.txt")); assertNull(FilenameUtils.getPathNoEndSeparator("//a")); assertEquals("", FilenameUtils.getPathNoEndSeparator("")); assertEquals("", FilenameUtils.getPathNoEndSeparator("C:")); assertEquals("", FilenameUtils.getPathNoEndSeparator("C:/")); assertEquals("", FilenameUtils.getPathNoEndSeparator("//server/")); assertEquals("", FilenameUtils.getPathNoEndSeparator("~")); assertEquals("", FilenameUtils.getPathNoEndSeparator("~/")); assertEquals("", FilenameUtils.getPathNoEndSeparator("~user")); assertEquals("", FilenameUtils.getPathNoEndSeparator("~user/")); assertEquals("a/b", FilenameUtils.getPathNoEndSeparator("a/b/c.txt")); assertEquals("a/b", FilenameUtils.getPathNoEndSeparator("/a/b/c.txt")); assertEquals("", FilenameUtils.getPathNoEndSeparator("C:a")); assertEquals("a/b", FilenameUtils.getPathNoEndSeparator("C:a/b/c.txt")); assertEquals("a/b", FilenameUtils.getPathNoEndSeparator("C:/a/b/c.txt")); assertEquals("a/b", FilenameUtils.getPathNoEndSeparator("//server/a/b/c.txt")); assertEquals("a/b", FilenameUtils.getPathNoEndSeparator("~/a/b/c.txt")); assertEquals("a/b", FilenameUtils.getPathNoEndSeparator("~user/a/b/c.txt")); } @Test public void testGetPathNoEndSeparator_with_null_byte() { try { assertEquals("a/b", FilenameUtils.getPathNoEndSeparator("~user/a\u0000/b/c.txt")); } catch (final IllegalArgumentException ignore) { } } @Test public void testGetFullPath() { assertNull(FilenameUtils.getFullPath(null)); assertEquals("", FilenameUtils.getFullPath("noseperator.inthispath")); assertEquals("a/b/", FilenameUtils.getFullPath("a/b/c.txt")); assertEquals("a/b/", FilenameUtils.getFullPath("a/b/c")); assertEquals("a/b/c/", FilenameUtils.getFullPath("a/b/c/")); assertEquals("a\\b\\", FilenameUtils.getFullPath("a\\b\\c")); assertNull(FilenameUtils.getFullPath(":")); assertNull(FilenameUtils.getFullPath("1:/a/b/c.txt")); assertNull(FilenameUtils.getFullPath("1:")); assertNull(FilenameUtils.getFullPath("1:a")); assertNull(FilenameUtils.getFullPath("///a/b/c.txt")); assertNull(FilenameUtils.getFullPath("//a")); assertEquals("", FilenameUtils.getFullPath("")); if (SystemUtils.IS_OS_WINDOWS) { assertEquals("C:", FilenameUtils.getFullPath("C:")); } if (SystemUtils.IS_OS_LINUX) { assertEquals("", FilenameUtils.getFullPath("C:")); } assertEquals("C:/", FilenameUtils.getFullPath("C:/")); assertEquals("//server/", FilenameUtils.getFullPath("//server/")); assertEquals("~/", FilenameUtils.getFullPath("~")); assertEquals("~/", FilenameUtils.getFullPath("~/")); assertEquals("~user/", FilenameUtils.getFullPath("~user")); assertEquals("~user/", FilenameUtils.getFullPath("~user/")); assertEquals("a/b/", FilenameUtils.getFullPath("a/b/c.txt")); assertEquals("/a/b/", FilenameUtils.getFullPath("/a/b/c.txt")); assertEquals("C:", FilenameUtils.getFullPath("C:a")); assertEquals("C:a/b/", FilenameUtils.getFullPath("C:a/b/c.txt")); assertEquals("C:/a/b/", FilenameUtils.getFullPath("C:/a/b/c.txt")); assertEquals("//server/a/b/", FilenameUtils.getFullPath("//server/a/b/c.txt")); assertEquals("~/a/b/", FilenameUtils.getFullPath("~/a/b/c.txt")); assertEquals("~user/a/b/", FilenameUtils.getFullPath("~user/a/b/c.txt")); } @Test public void testGetFullPathNoEndSeparator() { assertNull(FilenameUtils.getFullPathNoEndSeparator(null)); assertEquals("", FilenameUtils.getFullPathNoEndSeparator("noseperator.inthispath")); assertEquals("a/b", FilenameUtils.getFullPathNoEndSeparator("a/b/c.txt")); assertEquals("a/b", FilenameUtils.getFullPathNoEndSeparator("a/b/c")); assertEquals("a/b/c", FilenameUtils.getFullPathNoEndSeparator("a/b/c/")); assertEquals("a\\b", FilenameUtils.getFullPathNoEndSeparator("a\\b\\c")); assertNull(FilenameUtils.getFullPathNoEndSeparator(":")); assertNull(FilenameUtils.getFullPathNoEndSeparator("1:/a/b/c.txt")); assertNull(FilenameUtils.getFullPathNoEndSeparator("1:")); assertNull(FilenameUtils.getFullPathNoEndSeparator("1:a")); assertNull(FilenameUtils.getFullPathNoEndSeparator("///a/b/c.txt")); assertNull(FilenameUtils.getFullPathNoEndSeparator("//a")); assertEquals("", FilenameUtils.getFullPathNoEndSeparator("")); if (SystemUtils.IS_OS_WINDOWS) { assertEquals("C:", FilenameUtils.getFullPathNoEndSeparator("C:")); } if (SystemUtils.IS_OS_LINUX) { assertEquals("", FilenameUtils.getFullPathNoEndSeparator("C:")); } assertEquals("C:/", FilenameUtils.getFullPathNoEndSeparator("C:/")); assertEquals("//server/", FilenameUtils.getFullPathNoEndSeparator("//server/")); assertEquals("~", FilenameUtils.getFullPathNoEndSeparator("~")); assertEquals("~/", FilenameUtils.getFullPathNoEndSeparator("~/")); assertEquals("~user", FilenameUtils.getFullPathNoEndSeparator("~user")); assertEquals("~user/", FilenameUtils.getFullPathNoEndSeparator("~user/")); assertEquals("a/b", FilenameUtils.getFullPathNoEndSeparator("a/b/c.txt")); assertEquals("/a/b", FilenameUtils.getFullPathNoEndSeparator("/a/b/c.txt")); assertEquals("C:", FilenameUtils.getFullPathNoEndSeparator("C:a")); assertEquals("C:a/b", FilenameUtils.getFullPathNoEndSeparator("C:a/b/c.txt")); assertEquals("C:/a/b", FilenameUtils.getFullPathNoEndSeparator("C:/a/b/c.txt")); assertEquals("//server/a/b", FilenameUtils.getFullPathNoEndSeparator("//server/a/b/c.txt")); assertEquals("~/a/b", FilenameUtils.getFullPathNoEndSeparator("~/a/b/c.txt")); assertEquals("~user/a/b", FilenameUtils.getFullPathNoEndSeparator("~user/a/b/c.txt")); } /** * Test for https://issues.apache.org/jira/browse/IO-248 */ @Test public void testGetFullPathNoEndSeparator_IO_248() { // Test single separator assertEquals("/", FilenameUtils.getFullPathNoEndSeparator("/")); assertEquals("\\", FilenameUtils.getFullPathNoEndSeparator("\\")); // Test one level directory assertEquals("/", FilenameUtils.getFullPathNoEndSeparator("/abc")); assertEquals("\\", FilenameUtils.getFullPathNoEndSeparator("\\abc")); // Test one level directory assertEquals("/abc", FilenameUtils.getFullPathNoEndSeparator("/abc/xyz")); assertEquals("\\abc", FilenameUtils.getFullPathNoEndSeparator("\\abc\\xyz")); } @Test public void testGetName() { assertNull(FilenameUtils.getName(null)); assertEquals("noseperator.inthispath", FilenameUtils.getName("noseperator.inthispath")); assertEquals("c.txt", FilenameUtils.getName("a/b/c.txt")); assertEquals("c", FilenameUtils.getName("a/b/c")); assertEquals("", FilenameUtils.getName("a/b/c/")); assertEquals("c", FilenameUtils.getName("a\\b\\c")); } @Test public void testInjectionFailure() { try { assertEquals("c", FilenameUtils.getName("a\\b\\\u0000c")); } catch (final IllegalArgumentException ignore) { } } @Test public void testGetBaseName() { assertNull(FilenameUtils.getBaseName(null)); assertEquals("noseperator", FilenameUtils.getBaseName("noseperator.inthispath")); assertEquals("c", FilenameUtils.getBaseName("a/b/c.txt")); assertEquals("c", FilenameUtils.getBaseName("a/b/c")); assertEquals("", FilenameUtils.getBaseName("a/b/c/")); assertEquals("c", FilenameUtils.getBaseName("a\\b\\c")); assertEquals("file.txt", FilenameUtils.getBaseName("file.txt.bak")); } @Test public void testGetBaseName_with_nullByte() { try { assertEquals("file.txt", FilenameUtils.getBaseName("fil\u0000e.txt.bak")); } catch (final IllegalArgumentException ignore) { } } @Test public void testGetExtension() { assertNull(FilenameUtils.getExtension(null)); assertEquals("ext", FilenameUtils.getExtension("file.ext")); assertEquals("", FilenameUtils.getExtension("README")); assertEquals("com", FilenameUtils.getExtension("domain.dot.com")); assertEquals("jpeg", FilenameUtils.getExtension("image.jpeg")); assertEquals("", FilenameUtils.getExtension("a.b/c")); assertEquals("txt", FilenameUtils.getExtension("a.b/c.txt")); assertEquals("", FilenameUtils.getExtension("a/b/c")); assertEquals("", FilenameUtils.getExtension("a.b\\c")); assertEquals("txt", FilenameUtils.getExtension("a.b\\c.txt")); assertEquals("", FilenameUtils.getExtension("a\\b\\c")); assertEquals("", FilenameUtils.getExtension("C:\\temp\\foo.bar\\README")); assertEquals("ext", FilenameUtils.getExtension("../filename.ext")); if (FilenameUtils.isSystemWindows()) { // Special case handling for NTFS ADS names try { FilenameUtils.getExtension("foo.exe:bar.txt"); throw new AssertionError("Expected Exception"); } catch (final IllegalArgumentException e) { assertEquals("NTFS ADS separator (':') in file name is forbidden.", e.getMessage()); } } else { // Upwards compatibility: assertEquals("txt", FilenameUtils.getExtension("foo.exe:bar.txt")); } } @Test public void testRemoveExtension() { assertNull(FilenameUtils.removeExtension(null)); assertEquals("file", FilenameUtils.removeExtension("file.ext")); assertEquals("README", FilenameUtils.removeExtension("README")); assertEquals("domain.dot", FilenameUtils.removeExtension("domain.dot.com")); assertEquals("image", FilenameUtils.removeExtension("image.jpeg")); assertEquals("a.b/c", FilenameUtils.removeExtension("a.b/c")); assertEquals("a.b/c", FilenameUtils.removeExtension("a.b/c.txt")); assertEquals("a/b/c", FilenameUtils.removeExtension("a/b/c")); assertEquals("a.b\\c", FilenameUtils.removeExtension("a.b\\c")); assertEquals("a.b\\c", FilenameUtils.removeExtension("a.b\\c.txt")); assertEquals("a\\b\\c", FilenameUtils.removeExtension("a\\b\\c")); assertEquals("C:\\temp\\foo.bar\\README", FilenameUtils.removeExtension("C:\\temp\\foo.bar\\README")); assertEquals("../filename", FilenameUtils.removeExtension("../filename.ext")); } @Test public void testEquals() { assertTrue(FilenameUtils.equals(null, null)); assertFalse(FilenameUtils.equals(null, "")); assertFalse(FilenameUtils.equals("", null)); assertTrue(FilenameUtils.equals("", "")); assertTrue(FilenameUtils.equals("file.txt", "file.txt")); assertFalse(FilenameUtils.equals("file.txt", "FILE.TXT")); assertFalse(FilenameUtils.equals("a\\b\\file.txt", "a/b/file.txt")); } @Test public void testEqualsOnSystem() { assertTrue(FilenameUtils.equalsOnSystem(null, null)); assertFalse(FilenameUtils.equalsOnSystem(null, "")); assertFalse(FilenameUtils.equalsOnSystem("", null)); assertTrue(FilenameUtils.equalsOnSystem("", "")); assertTrue(FilenameUtils.equalsOnSystem("file.txt", "file.txt")); assertEquals(WINDOWS, FilenameUtils.equalsOnSystem("file.txt", "FILE.TXT")); assertFalse(FilenameUtils.equalsOnSystem("a\\b\\file.txt", "a/b/file.txt")); } @Test public void testEqualsNormalized() { assertTrue(FilenameUtils.equalsNormalized(null, null)); assertFalse(FilenameUtils.equalsNormalized(null, "")); assertFalse(FilenameUtils.equalsNormalized("", null)); assertTrue(FilenameUtils.equalsNormalized("", "")); assertTrue(FilenameUtils.equalsNormalized("file.txt", "file.txt")); assertFalse(FilenameUtils.equalsNormalized("file.txt", "FILE.TXT")); assertTrue(FilenameUtils.equalsNormalized("a\\b\\file.txt", "a/b/file.txt")); assertFalse(FilenameUtils.equalsNormalized("a/b/", "a/b")); } @Test public void testEqualsNormalizedOnSystem() { assertTrue(FilenameUtils.equalsNormalizedOnSystem(null, null)); assertFalse(FilenameUtils.equalsNormalizedOnSystem(null, "")); assertFalse(FilenameUtils.equalsNormalizedOnSystem("", null)); assertTrue(FilenameUtils.equalsNormalizedOnSystem("", "")); assertTrue(FilenameUtils.equalsNormalizedOnSystem("file.txt", "file.txt")); assertEquals(WINDOWS, FilenameUtils.equalsNormalizedOnSystem("file.txt", "FILE.TXT")); assertTrue(FilenameUtils.equalsNormalizedOnSystem("a\\b\\file.txt", "a/b/file.txt")); assertFalse(FilenameUtils.equalsNormalizedOnSystem("a/b/", "a/b")); } /** * Test for https://issues.apache.org/jira/browse/IO-128 */ @Test public void testEqualsNormalizedError_IO_128() { assertFalse(FilenameUtils.equalsNormalizedOnSystem("//file.txt", "file.txt")); assertFalse(FilenameUtils.equalsNormalizedOnSystem("file.txt", "//file.txt")); assertFalse(FilenameUtils.equalsNormalizedOnSystem("//file.txt", "//file.txt")); } @Test public void testEquals_fullControl() { assertFalse(FilenameUtils.equals("file.txt", "FILE.TXT", true, IOCase.SENSITIVE)); assertTrue(FilenameUtils.equals("file.txt", "FILE.TXT", true, IOCase.INSENSITIVE)); assertEquals(WINDOWS, FilenameUtils.equals("file.txt", "FILE.TXT", true, IOCase.SYSTEM)); assertFalse(FilenameUtils.equals("file.txt", "FILE.TXT", true, null)); } @Test public void testIsExtension() { assertFalse(FilenameUtils.isExtension(null, (String) null)); assertFalse(FilenameUtils.isExtension("file.txt", (String) null)); assertTrue(FilenameUtils.isExtension("file", (String) null)); assertFalse(FilenameUtils.isExtension("file.txt", "")); assertTrue(FilenameUtils.isExtension("file", "")); assertTrue(FilenameUtils.isExtension("file.txt", "txt")); assertFalse(FilenameUtils.isExtension("file.txt", "rtf")); assertFalse(FilenameUtils.isExtension("a/b/file.txt", (String) null)); assertFalse(FilenameUtils.isExtension("a/b/file.txt", "")); assertTrue(FilenameUtils.isExtension("a/b/file.txt", "txt")); assertFalse(FilenameUtils.isExtension("a/b/file.txt", "rtf")); assertFalse(FilenameUtils.isExtension("a.b/file.txt", (String) null)); assertFalse(FilenameUtils.isExtension("a.b/file.txt", "")); assertTrue(FilenameUtils.isExtension("a.b/file.txt", "txt")); assertFalse(FilenameUtils.isExtension("a.b/file.txt", "rtf")); assertFalse(FilenameUtils.isExtension("a\\b\\file.txt", (String) null)); assertFalse(FilenameUtils.isExtension("a\\b\\file.txt", "")); assertTrue(FilenameUtils.isExtension("a\\b\\file.txt", "txt")); assertFalse(FilenameUtils.isExtension("a\\b\\file.txt", "rtf")); assertFalse(FilenameUtils.isExtension("a.b\\file.txt", (String) null)); assertFalse(FilenameUtils.isExtension("a.b\\file.txt", "")); assertTrue(FilenameUtils.isExtension("a.b\\file.txt", "txt")); assertFalse(FilenameUtils.isExtension("a.b\\file.txt", "rtf")); assertFalse(FilenameUtils.isExtension("a.b\\file.txt", "TXT")); } @Test public void testIsExtension_injection() { try { FilenameUtils.isExtension("a.b\\fi\u0000le.txt", "TXT"); fail("Should throw IAE"); } catch (final IllegalArgumentException ignore) { } } @Test public void testIsExtensionArray() { assertFalse(FilenameUtils.isExtension(null, (String[]) null)); assertFalse(FilenameUtils.isExtension("file.txt", (String[]) null)); assertTrue(FilenameUtils.isExtension("file", (String[]) null)); assertFalse(FilenameUtils.isExtension("file.txt")); assertTrue(FilenameUtils.isExtension("file.txt", new String[]{"txt"})); assertFalse(FilenameUtils.isExtension("file.txt", new String[]{"rtf"})); assertTrue(FilenameUtils.isExtension("file", "rtf", "")); assertTrue(FilenameUtils.isExtension("file.txt", "rtf", "txt")); assertFalse(FilenameUtils.isExtension("a/b/file.txt", (String[]) null)); assertFalse(FilenameUtils.isExtension("a/b/file.txt")); assertTrue(FilenameUtils.isExtension("a/b/file.txt", new String[]{"txt"})); assertFalse(FilenameUtils.isExtension("a/b/file.txt", new String[]{"rtf"})); assertTrue(FilenameUtils.isExtension("a/b/file.txt", "rtf", "txt")); assertFalse(FilenameUtils.isExtension("a.b/file.txt", (String[]) null)); assertFalse(FilenameUtils.isExtension("a.b/file.txt")); assertTrue(FilenameUtils.isExtension("a.b/file.txt", new String[]{"txt"})); assertFalse(FilenameUtils.isExtension("a.b/file.txt", new String[]{"rtf"})); assertTrue(FilenameUtils.isExtension("a.b/file.txt", "rtf", "txt")); assertFalse(FilenameUtils.isExtension("a\\b\\file.txt", (String[]) null)); assertFalse(FilenameUtils.isExtension("a\\b\\file.txt")); assertTrue(FilenameUtils.isExtension("a\\b\\file.txt", new String[]{"txt"})); assertFalse(FilenameUtils.isExtension("a\\b\\file.txt", new String[]{"rtf"})); assertTrue(FilenameUtils.isExtension("a\\b\\file.txt", "rtf", "txt")); assertFalse(FilenameUtils.isExtension("a.b\\file.txt", (String[]) null)); assertFalse(FilenameUtils.isExtension("a.b\\file.txt")); assertTrue(FilenameUtils.isExtension("a.b\\file.txt", new String[]{"txt"})); assertFalse(FilenameUtils.isExtension("a.b\\file.txt", new String[]{"rtf"})); assertTrue(FilenameUtils.isExtension("a.b\\file.txt", "rtf", "txt")); assertFalse(FilenameUtils.isExtension("a.b\\file.txt", new String[]{"TXT"})); assertFalse(FilenameUtils.isExtension("a.b\\file.txt", "TXT", "RTF")); } @Test public void testIsExtensionVarArgs() { assertTrue(FilenameUtils.isExtension("file.txt", "txt")); assertFalse(FilenameUtils.isExtension("file.txt", "rtf")); assertTrue(FilenameUtils.isExtension("file", "rtf", "")); assertTrue(FilenameUtils.isExtension("file.txt", "rtf", "txt")); assertTrue(FilenameUtils.isExtension("a/b/file.txt", "txt")); assertFalse(FilenameUtils.isExtension("a/b/file.txt", "rtf")); assertTrue(FilenameUtils.isExtension("a/b/file.txt", "rtf", "txt")); assertTrue(FilenameUtils.isExtension("a.b/file.txt", "txt")); assertFalse(FilenameUtils.isExtension("a.b/file.txt", "rtf")); assertTrue(FilenameUtils.isExtension("a.b/file.txt", "rtf", "txt")); assertTrue(FilenameUtils.isExtension("a\\b\\file.txt", "txt")); assertFalse(FilenameUtils.isExtension("a\\b\\file.txt", "rtf")); assertTrue(FilenameUtils.isExtension("a\\b\\file.txt", "rtf", "txt")); assertTrue(FilenameUtils.isExtension("a.b\\file.txt", "txt")); assertFalse(FilenameUtils.isExtension("a.b\\file.txt", "rtf")); assertTrue(FilenameUtils.isExtension("a.b\\file.txt", "rtf", "txt")); assertFalse(FilenameUtils.isExtension("a.b\\file.txt", "TXT")); assertFalse(FilenameUtils.isExtension("a.b\\file.txt", "TXT", "RTF")); } @Test public void testIsExtensionCollection() { assertFalse(FilenameUtils.isExtension(null, (Collection) null)); assertFalse(FilenameUtils.isExtension("file.txt", (Collection) null)); assertTrue(FilenameUtils.isExtension("file", (Collection) null)); assertFalse(FilenameUtils.isExtension("file.txt", new ArrayList())); assertTrue(FilenameUtils.isExtension("file.txt", new ArrayList<>(Arrays.asList("txt")))); assertFalse(FilenameUtils.isExtension("file.txt", new ArrayList<>(Arrays.asList("rtf")))); assertTrue(FilenameUtils.isExtension("file", new ArrayList<>(Arrays.asList("rtf", "")))); assertTrue(FilenameUtils.isExtension("file.txt", new ArrayList<>(Arrays.asList("rtf", "txt")))); assertFalse(FilenameUtils.isExtension("a/b/file.txt", (Collection) null)); assertFalse(FilenameUtils.isExtension("a/b/file.txt", new ArrayList())); assertTrue(FilenameUtils.isExtension("a/b/file.txt", new ArrayList<>(Arrays.asList("txt")))); assertFalse(FilenameUtils.isExtension("a/b/file.txt", new ArrayList<>(Arrays.asList("rtf")))); assertTrue(FilenameUtils.isExtension("a/b/file.txt", new ArrayList<>(Arrays.asList("rtf", "txt")))); assertFalse(FilenameUtils.isExtension("a.b/file.txt", (Collection) null)); assertFalse(FilenameUtils.isExtension("a.b/file.txt", new ArrayList())); assertTrue(FilenameUtils.isExtension("a.b/file.txt", new ArrayList<>(Arrays.asList("txt")))); assertFalse(FilenameUtils.isExtension("a.b/file.txt", new ArrayList<>(Arrays.asList("rtf")))); assertTrue(FilenameUtils.isExtension("a.b/file.txt", new ArrayList<>(Arrays.asList("rtf", "txt")))); assertFalse(FilenameUtils.isExtension("a\\b\\file.txt", (Collection) null)); assertFalse(FilenameUtils.isExtension("a\\b\\file.txt", new ArrayList())); assertTrue(FilenameUtils.isExtension("a\\b\\file.txt", new ArrayList<>(Arrays.asList("txt")))); assertFalse(FilenameUtils.isExtension("a\\b\\file.txt", new ArrayList<>(Arrays.asList("rtf")))); assertTrue(FilenameUtils.isExtension("a\\b\\file.txt", new ArrayList<>(Arrays.asList("rtf", "txt")))); assertFalse(FilenameUtils.isExtension("a.b\\file.txt", (Collection) null)); assertFalse(FilenameUtils.isExtension("a.b\\file.txt", new ArrayList())); assertTrue(FilenameUtils.isExtension("a.b\\file.txt", new ArrayList<>(Arrays.asList("txt")))); assertFalse(FilenameUtils.isExtension("a.b\\file.txt", new ArrayList<>(Arrays.asList("rtf")))); assertTrue(FilenameUtils.isExtension("a.b\\file.txt", new ArrayList<>(Arrays.asList("rtf", "txt")))); assertFalse(FilenameUtils.isExtension("a.b\\file.txt", new ArrayList<>(Arrays.asList("TXT")))); assertFalse(FilenameUtils.isExtension("a.b\\file.txt", new ArrayList<>(Arrays.asList("TXT", "RTF")))); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/FilenameUtilsWildcardTestCase.java0100644 0000000 0000000 00000027361 13612062727 032311 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.File; import java.util.Locale; import org.junit.jupiter.api.Test; public class FilenameUtilsWildcardTestCase { private static final boolean WINDOWS = File.separatorChar == '\\'; // Testing: // FilenameUtils.wildcardMatch(String,String) @Test public void testMatch() { assertFalse(FilenameUtils.wildcardMatch(null, "Foo")); assertFalse(FilenameUtils.wildcardMatch("Foo", null)); assertTrue(FilenameUtils.wildcardMatch(null, null)); assertTrue(FilenameUtils.wildcardMatch("Foo", "Foo")); assertTrue(FilenameUtils.wildcardMatch("", "")); assertTrue(FilenameUtils.wildcardMatch("", "*")); assertFalse(FilenameUtils.wildcardMatch("", "?")); assertTrue(FilenameUtils.wildcardMatch("Foo", "Fo*")); assertTrue(FilenameUtils.wildcardMatch("Foo", "Fo?")); assertTrue(FilenameUtils.wildcardMatch("Foo Bar and Catflap", "Fo*")); assertTrue(FilenameUtils.wildcardMatch("New Bookmarks", "N?w ?o?k??r?s")); assertFalse(FilenameUtils.wildcardMatch("Foo", "Bar")); assertTrue(FilenameUtils.wildcardMatch("Foo Bar Foo", "F*o Bar*")); assertTrue(FilenameUtils.wildcardMatch("Adobe Acrobat Installer", "Ad*er")); assertTrue(FilenameUtils.wildcardMatch("Foo", "*Foo")); assertTrue(FilenameUtils.wildcardMatch("BarFoo", "*Foo")); assertTrue(FilenameUtils.wildcardMatch("Foo", "Foo*")); assertTrue(FilenameUtils.wildcardMatch("FooBar", "Foo*")); assertFalse(FilenameUtils.wildcardMatch("FOO", "*Foo")); assertFalse(FilenameUtils.wildcardMatch("BARFOO", "*Foo")); assertFalse(FilenameUtils.wildcardMatch("FOO", "Foo*")); assertFalse(FilenameUtils.wildcardMatch("FOOBAR", "Foo*")); } @Test public void testMatchOnSystem() { assertFalse(FilenameUtils.wildcardMatchOnSystem(null, "Foo")); assertFalse(FilenameUtils.wildcardMatchOnSystem("Foo", null)); assertTrue(FilenameUtils.wildcardMatchOnSystem(null, null)); assertTrue(FilenameUtils.wildcardMatchOnSystem("Foo", "Foo")); assertTrue(FilenameUtils.wildcardMatchOnSystem("", "")); assertTrue(FilenameUtils.wildcardMatchOnSystem("Foo", "Fo*")); assertTrue(FilenameUtils.wildcardMatchOnSystem("Foo", "Fo?")); assertTrue(FilenameUtils.wildcardMatchOnSystem("Foo Bar and Catflap", "Fo*")); assertTrue(FilenameUtils.wildcardMatchOnSystem("New Bookmarks", "N?w ?o?k??r?s")); assertFalse(FilenameUtils.wildcardMatchOnSystem("Foo", "Bar")); assertTrue(FilenameUtils.wildcardMatchOnSystem("Foo Bar Foo", "F*o Bar*")); assertTrue(FilenameUtils.wildcardMatchOnSystem("Adobe Acrobat Installer", "Ad*er")); assertTrue(FilenameUtils.wildcardMatchOnSystem("Foo", "*Foo")); assertTrue(FilenameUtils.wildcardMatchOnSystem("BarFoo", "*Foo")); assertTrue(FilenameUtils.wildcardMatchOnSystem("Foo", "Foo*")); assertTrue(FilenameUtils.wildcardMatchOnSystem("FooBar", "Foo*")); assertEquals(WINDOWS, FilenameUtils.wildcardMatchOnSystem("FOO", "*Foo")); assertEquals(WINDOWS, FilenameUtils.wildcardMatchOnSystem("BARFOO", "*Foo")); assertEquals(WINDOWS, FilenameUtils.wildcardMatchOnSystem("FOO", "Foo*")); assertEquals(WINDOWS, FilenameUtils.wildcardMatchOnSystem("FOOBAR", "Foo*")); } @Test public void testMatchCaseSpecified() { assertFalse(FilenameUtils.wildcardMatch(null, "Foo", IOCase.SENSITIVE)); assertFalse(FilenameUtils.wildcardMatch("Foo", null, IOCase.SENSITIVE)); assertTrue(FilenameUtils.wildcardMatch(null, null, IOCase.SENSITIVE)); assertTrue(FilenameUtils.wildcardMatch("Foo", "Foo", IOCase.SENSITIVE)); assertTrue(FilenameUtils.wildcardMatch("", "", IOCase.SENSITIVE)); assertTrue(FilenameUtils.wildcardMatch("Foo", "Fo*", IOCase.SENSITIVE)); assertTrue(FilenameUtils.wildcardMatch("Foo", "Fo?", IOCase.SENSITIVE)); assertTrue(FilenameUtils.wildcardMatch("Foo Bar and Catflap", "Fo*", IOCase.SENSITIVE)); assertTrue(FilenameUtils.wildcardMatch("New Bookmarks", "N?w ?o?k??r?s", IOCase.SENSITIVE)); assertFalse(FilenameUtils.wildcardMatch("Foo", "Bar", IOCase.SENSITIVE)); assertTrue(FilenameUtils.wildcardMatch("Foo Bar Foo", "F*o Bar*", IOCase.SENSITIVE)); assertTrue(FilenameUtils.wildcardMatch("Adobe Acrobat Installer", "Ad*er", IOCase.SENSITIVE)); assertTrue(FilenameUtils.wildcardMatch("Foo", "*Foo", IOCase.SENSITIVE)); assertTrue(FilenameUtils.wildcardMatch("Foo", "Foo*", IOCase.SENSITIVE)); assertTrue(FilenameUtils.wildcardMatch("Foo", "*Foo", IOCase.SENSITIVE)); assertTrue(FilenameUtils.wildcardMatch("BarFoo", "*Foo", IOCase.SENSITIVE)); assertTrue(FilenameUtils.wildcardMatch("Foo", "Foo*", IOCase.SENSITIVE)); assertTrue(FilenameUtils.wildcardMatch("FooBar", "Foo*", IOCase.SENSITIVE)); assertFalse(FilenameUtils.wildcardMatch("FOO", "*Foo", IOCase.SENSITIVE)); assertFalse(FilenameUtils.wildcardMatch("BARFOO", "*Foo", IOCase.SENSITIVE)); assertFalse(FilenameUtils.wildcardMatch("FOO", "Foo*", IOCase.SENSITIVE)); assertFalse(FilenameUtils.wildcardMatch("FOOBAR", "Foo*", IOCase.SENSITIVE)); assertTrue(FilenameUtils.wildcardMatch("FOO", "*Foo", IOCase.INSENSITIVE)); assertTrue(FilenameUtils.wildcardMatch("BARFOO", "*Foo", IOCase.INSENSITIVE)); assertTrue(FilenameUtils.wildcardMatch("FOO", "Foo*", IOCase.INSENSITIVE)); assertTrue(FilenameUtils.wildcardMatch("FOOBAR", "Foo*", IOCase.INSENSITIVE)); assertEquals(WINDOWS, FilenameUtils.wildcardMatch("FOO", "*Foo", IOCase.SYSTEM)); assertEquals(WINDOWS, FilenameUtils.wildcardMatch("BARFOO", "*Foo", IOCase.SYSTEM)); assertEquals(WINDOWS, FilenameUtils.wildcardMatch("FOO", "Foo*", IOCase.SYSTEM)); assertEquals(WINDOWS, FilenameUtils.wildcardMatch("FOOBAR", "Foo*", IOCase.SYSTEM)); } @Test public void testSplitOnTokens() { assertArrayEquals(new String[] { "Ad", "*", "er" }, FilenameUtils.splitOnTokens("Ad*er")); assertArrayEquals(new String[] { "Ad", "?", "er" }, FilenameUtils.splitOnTokens("Ad?er")); assertArrayEquals(new String[] { "Test", "*", "?", "One" }, FilenameUtils.splitOnTokens("Test*?One")); assertArrayEquals(new String[] { "Test", "?", "*", "One" }, FilenameUtils.splitOnTokens("Test?*One")); assertArrayEquals(new String[] { "*" }, FilenameUtils.splitOnTokens("****")); assertArrayEquals(new String[] { "*", "?", "?", "*" }, FilenameUtils.splitOnTokens("*??*")); assertArrayEquals(new String[] { "*", "?", "*", "?", "*" }, FilenameUtils.splitOnTokens("*?**?*")); assertArrayEquals(new String[] { "*", "?", "*", "?", "*" }, FilenameUtils.splitOnTokens("*?***?*")); assertArrayEquals(new String[] { "h", "?", "?", "*" }, FilenameUtils.splitOnTokens("h??*")); assertArrayEquals(new String[] { "" }, FilenameUtils.splitOnTokens("")); } private void assertMatch(final String text, final String wildcard, final boolean expected) { assertEquals(expected, FilenameUtils.wildcardMatch(text, wildcard), text + " " + wildcard); } // A separate set of tests, added to this batch @Test public void testMatch2() { assertMatch("log.txt", "log.txt", true); assertMatch("log.txt1", "log.txt", false); assertMatch("log.txt", "log.txt*", true); assertMatch("log.txt", "log.txt*1", false); assertMatch("log.txt", "*log.txt*", true); assertMatch("log.txt", "*.txt", true); assertMatch("txt.log", "*.txt", false); assertMatch("config.ini", "*.ini", true); assertMatch("config.txt.bak", "con*.txt", false); assertMatch("log.txt9", "*.txt?", true); assertMatch("log.txt", "*.txt?", false); assertMatch("progtestcase.java~5~", "*test*.java~*~", true); assertMatch("progtestcase.java;5~", "*test*.java~*~", false); assertMatch("progtestcase.java~5", "*test*.java~*~", false); assertMatch("log.txt", "log.*", true); assertMatch("log.txt", "log?*", true); assertMatch("log.txt12", "log.txt??", true); assertMatch("log.log", "log**log", true); assertMatch("log.log", "log**", true); assertMatch("log.log", "log.**", true); assertMatch("log.log", "**.log", true); assertMatch("log.log", "**log", true); assertMatch("log.log", "log*log", true); assertMatch("log.log", "log*", true); assertMatch("log.log", "log.*", true); assertMatch("log.log", "*.log", true); assertMatch("log.log", "*log", true); assertMatch("log.log", "*log?", false); assertMatch("log.log", "*log?*", true); assertMatch("log.log.abc", "*log?abc", true); assertMatch("log.log.abc.log.abc", "*log?abc", true); assertMatch("log.log.abc.log.abc.d", "*log?abc?d", true); } /** * See https://issues.apache.org/jira/browse/IO-246 */ @Test public void test_IO_246() { // Tests for "*?" assertMatch("aaa", "aa*?", true); // these ought to work as well, but "*?" does not work properly at present // assertMatch("aaa", "a*?", true); // assertMatch("aaa", "*?", true); // Tests for "?*" assertMatch("", "?*", false); assertMatch("a", "a?*", false); assertMatch("aa", "aa?*", false); assertMatch("a", "?*", true); assertMatch("aa", "?*", true); assertMatch("aaa", "?*", true); // Test ending on "?" assertMatch("", "?", false); assertMatch("a", "a?", false); assertMatch("aa", "aa?", false); assertMatch("aab", "aa?", true); assertMatch("aaa", "*a", true); } @Test public void testLocaleIndependence() { final Locale orig = Locale.getDefault(); final Locale[] locales = Locale.getAvailableLocales(); final String[][] data = { { "I", "i"}, { "i", "I"}, { "i", "\u0130"}, { "i", "\u0131"}, { "\u03A3", "\u03C2"}, { "\u03A3", "\u03C3"}, { "\u03C2", "\u03C3"}, }; try { for (int i = 0; i < data.length; i++) { for (final Locale locale : locales) { Locale.setDefault(locale); assertTrue(data[i][0].equalsIgnoreCase(data[i][1]), "Test data corrupt: " + i); final boolean match = FilenameUtils.wildcardMatch(data[i][0], data[i][1], IOCase.INSENSITIVE); assertTrue(match, Locale.getDefault().toString() + ": " + i); } } } finally { Locale.setDefault(orig); } } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/HexDumpTest.java0100644 0000000 0000000 00000022174 13612062727 026651 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; import java.io.IOException; import org.apache.commons.io.output.ByteArrayOutputStream; import org.junit.jupiter.api.Test; /** * */ public class HexDumpTest { private char toHex(final int n) { final char[] hexChars = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; return hexChars[n % 16]; } @Test public void testDump() throws IOException { final byte[] testArray = new byte[256]; for (int j = 0; j < 256; j++) { testArray[j] = (byte) j; } ByteArrayOutputStream stream = new ByteArrayOutputStream(); HexDump.dump(testArray, 0, stream, 0); byte[] outputArray = new byte[16 * (73 + HexDump.EOL.length())]; for (int j = 0; j < 16; j++) { int offset = (73 + HexDump.EOL.length()) * j; outputArray[offset++] = (byte) '0'; outputArray[offset++] = (byte) '0'; outputArray[offset++] = (byte) '0'; outputArray[offset++] = (byte) '0'; outputArray[offset++] = (byte) '0'; outputArray[offset++] = (byte) '0'; outputArray[offset++] = (byte) toHex(j); outputArray[offset++] = (byte) '0'; outputArray[offset++] = (byte) ' '; for (int k = 0; k < 16; k++) { outputArray[offset++] = (byte) toHex(j); outputArray[offset++] = (byte) toHex(k); outputArray[offset++] = (byte) ' '; } for (int k = 0; k < 16; k++) { outputArray[offset++] = (byte) toAscii((j * 16) + k); } System.arraycopy(HexDump.EOL.getBytes(), 0, outputArray, offset, HexDump.EOL.getBytes().length); } byte[] actualOutput = stream.toByteArray(); assertEquals(outputArray.length, actualOutput.length, "array size mismatch"); for (int j = 0; j < outputArray.length; j++) { assertEquals(outputArray[j], actualOutput[j], "array[ " + j + "] mismatch"); } // verify proper behavior with non-zero offset stream = new ByteArrayOutputStream(); HexDump.dump(testArray, 0x10000000, stream, 0); outputArray = new byte[16 * (73 + HexDump.EOL.length())]; for (int j = 0; j < 16; j++) { int offset = (73 + HexDump.EOL.length()) * j; outputArray[offset++] = (byte) '1'; outputArray[offset++] = (byte) '0'; outputArray[offset++] = (byte) '0'; outputArray[offset++] = (byte) '0'; outputArray[offset++] = (byte) '0'; outputArray[offset++] = (byte) '0'; outputArray[offset++] = (byte) toHex(j); outputArray[offset++] = (byte) '0'; outputArray[offset++] = (byte) ' '; for (int k = 0; k < 16; k++) { outputArray[offset++] = (byte) toHex(j); outputArray[offset++] = (byte) toHex(k); outputArray[offset++] = (byte) ' '; } for (int k = 0; k < 16; k++) { outputArray[offset++] = (byte) toAscii((j * 16) + k); } System.arraycopy(HexDump.EOL.getBytes(), 0, outputArray, offset, HexDump.EOL.getBytes().length); } actualOutput = stream.toByteArray(); assertEquals(outputArray.length, actualOutput.length, "array size mismatch"); for (int j = 0; j < outputArray.length; j++) { assertEquals(outputArray[j], actualOutput[j], "array[ " + j + "] mismatch"); } // verify proper behavior with negative offset stream = new ByteArrayOutputStream(); HexDump.dump(testArray, 0xFF000000, stream, 0); outputArray = new byte[16 * (73 + HexDump.EOL.length())]; for (int j = 0; j < 16; j++) { int offset = (73 + HexDump.EOL.length()) * j; outputArray[offset++] = (byte) 'F'; outputArray[offset++] = (byte) 'F'; outputArray[offset++] = (byte) '0'; outputArray[offset++] = (byte) '0'; outputArray[offset++] = (byte) '0'; outputArray[offset++] = (byte) '0'; outputArray[offset++] = (byte) toHex(j); outputArray[offset++] = (byte) '0'; outputArray[offset++] = (byte) ' '; for (int k = 0; k < 16; k++) { outputArray[offset++] = (byte) toHex(j); outputArray[offset++] = (byte) toHex(k); outputArray[offset++] = (byte) ' '; } for (int k = 0; k < 16; k++) { outputArray[offset++] = (byte) toAscii((j * 16) + k); } System.arraycopy(HexDump.EOL.getBytes(), 0, outputArray, offset, HexDump.EOL.getBytes().length); } actualOutput = stream.toByteArray(); assertEquals(outputArray.length, actualOutput.length, "array size mismatch"); for (int j = 0; j < outputArray.length; j++) { assertEquals(outputArray[j], actualOutput[j], "array[ " + j + "] mismatch"); } // verify proper behavior with non-zero index stream = new ByteArrayOutputStream(); HexDump.dump(testArray, 0x10000000, stream, 0x81); outputArray = new byte[(8 * (73 + HexDump.EOL.length())) - 1]; for (int j = 0; j < 8; j++) { int offset = (73 + HexDump.EOL.length()) * j; outputArray[offset++] = (byte) '1'; outputArray[offset++] = (byte) '0'; outputArray[offset++] = (byte) '0'; outputArray[offset++] = (byte) '0'; outputArray[offset++] = (byte) '0'; outputArray[offset++] = (byte) '0'; outputArray[offset++] = (byte) toHex(j + 8); outputArray[offset++] = (byte) '1'; outputArray[offset++] = (byte) ' '; for (int k = 0; k < 16; k++) { final int index = 0x81 + (j * 16) + k; if (index < 0x100) { outputArray[offset++] = (byte) toHex(index / 16); outputArray[offset++] = (byte) toHex(index); } else { outputArray[offset++] = (byte) ' '; outputArray[offset++] = (byte) ' '; } outputArray[offset++] = (byte) ' '; } for (int k = 0; k < 16; k++) { final int index = 0x81 + (j * 16) + k; if (index < 0x100) { outputArray[offset++] = (byte) toAscii(index); } } System.arraycopy(HexDump.EOL.getBytes(), 0, outputArray, offset, HexDump.EOL.getBytes().length); } actualOutput = stream.toByteArray(); assertEquals(outputArray.length, actualOutput.length, "array size mismatch"); for (int j = 0; j < outputArray.length; j++) { assertEquals(outputArray[j], actualOutput[j], "array[ " + j + "] mismatch"); } // verify proper behavior with negative index try { HexDump.dump(testArray, 0x10000000, new ByteArrayOutputStream(), -1); fail("should have caught ArrayIndexOutOfBoundsException on negative index"); } catch (final ArrayIndexOutOfBoundsException ignored_exception) { // as expected } // verify proper behavior with index that is too large try { HexDump.dump(testArray, 0x10000000, new ByteArrayOutputStream(), testArray.length); fail("should have caught ArrayIndexOutOfBoundsException on large index"); } catch (final ArrayIndexOutOfBoundsException ignored_exception) { // as expected } // verify proper behavior with null stream try { HexDump.dump(testArray, 0x10000000, null, 0); fail("should have caught IllegalArgumentException on negative index"); } catch (final IllegalArgumentException ignored_exception) { // as expected } } private char toAscii(final int c) { char rval = '.'; if ((c >= 32) && (c <= 126)) { rval = (char) c; } return rval; } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/IOCaseTestCase.java0100644 0000000 0000000 00000036010 13612062727 027170 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import org.junit.jupiter.api.Test; /** * This is used to test IOCase for correctness. * */ public class IOCaseTestCase { private static final boolean WINDOWS = File.separatorChar == '\\'; @Test public void test_forName() { assertEquals(IOCase.SENSITIVE, IOCase.forName("Sensitive")); assertEquals(IOCase.INSENSITIVE, IOCase.forName("Insensitive")); assertEquals(IOCase.SYSTEM, IOCase.forName("System")); try { IOCase.forName("Blah"); fail(); } catch (final IllegalArgumentException ignore) {} try { IOCase.forName(null); fail(); } catch (final IllegalArgumentException ignore) {} } @Test public void test_serialization() throws Exception { assertSame(IOCase.SENSITIVE, serialize(IOCase.SENSITIVE)); assertSame(IOCase.INSENSITIVE, serialize(IOCase.INSENSITIVE)); assertSame(IOCase.SYSTEM, serialize(IOCase.SYSTEM)); } @Test public void test_getName() { assertEquals("Sensitive", IOCase.SENSITIVE.getName()); assertEquals("Insensitive", IOCase.INSENSITIVE.getName()); assertEquals("System", IOCase.SYSTEM.getName()); } @Test public void test_toString() { assertEquals("Sensitive", IOCase.SENSITIVE.toString()); assertEquals("Insensitive", IOCase.INSENSITIVE.toString()); assertEquals("System", IOCase.SYSTEM.toString()); } @Test public void test_isCaseSensitive() { assertTrue(IOCase.SENSITIVE.isCaseSensitive()); assertFalse(IOCase.INSENSITIVE.isCaseSensitive()); assertEquals(!WINDOWS, IOCase.SYSTEM.isCaseSensitive()); } @Test public void test_checkCompare_functionality() { assertTrue(IOCase.SENSITIVE.checkCompareTo("ABC", "") > 0); assertTrue(IOCase.SENSITIVE.checkCompareTo("", "ABC") < 0); assertTrue(IOCase.SENSITIVE.checkCompareTo("ABC", "DEF") < 0); assertTrue(IOCase.SENSITIVE.checkCompareTo("DEF", "ABC") > 0); assertEquals(0, IOCase.SENSITIVE.checkCompareTo("ABC", "ABC")); assertEquals(0, IOCase.SENSITIVE.checkCompareTo("", "")); try { IOCase.SENSITIVE.checkCompareTo("ABC", null); fail(); } catch (final NullPointerException ignore) {} try { IOCase.SENSITIVE.checkCompareTo(null, "ABC"); fail(); } catch (final NullPointerException ignore) {} try { IOCase.SENSITIVE.checkCompareTo(null, null); fail(); } catch (final NullPointerException ignore) {} } @Test public void test_checkCompare_case() { assertEquals(0, IOCase.SENSITIVE.checkCompareTo("ABC", "ABC")); assertTrue(IOCase.SENSITIVE.checkCompareTo("ABC", "abc") < 0); assertTrue(IOCase.SENSITIVE.checkCompareTo("abc", "ABC") > 0); assertEquals(0, IOCase.INSENSITIVE.checkCompareTo("ABC", "ABC")); assertEquals(0, IOCase.INSENSITIVE.checkCompareTo("ABC", "abc")); assertEquals(0, IOCase.INSENSITIVE.checkCompareTo("abc", "ABC")); assertEquals(0, IOCase.SYSTEM.checkCompareTo("ABC", "ABC")); assertEquals(WINDOWS, IOCase.SYSTEM.checkCompareTo("ABC", "abc") == 0); assertEquals(WINDOWS, IOCase.SYSTEM.checkCompareTo("abc", "ABC") == 0); } @Test public void test_checkEquals_functionality() { assertFalse(IOCase.SENSITIVE.checkEquals("ABC", "")); assertFalse(IOCase.SENSITIVE.checkEquals("ABC", "A")); assertFalse(IOCase.SENSITIVE.checkEquals("ABC", "AB")); assertTrue(IOCase.SENSITIVE.checkEquals("ABC", "ABC")); assertFalse(IOCase.SENSITIVE.checkEquals("ABC", "BC")); assertFalse(IOCase.SENSITIVE.checkEquals("ABC", "C")); assertFalse(IOCase.SENSITIVE.checkEquals("ABC", "ABCD")); assertFalse(IOCase.SENSITIVE.checkEquals("", "ABC")); assertTrue(IOCase.SENSITIVE.checkEquals("", "")); try { IOCase.SENSITIVE.checkEquals("ABC", null); fail(); } catch (final NullPointerException ignore) {} try { IOCase.SENSITIVE.checkEquals(null, "ABC"); fail(); } catch (final NullPointerException ignore) {} try { IOCase.SENSITIVE.checkEquals(null, null); fail(); } catch (final NullPointerException ignore) {} } @Test public void test_checkEquals_case() { assertTrue(IOCase.SENSITIVE.checkEquals("ABC", "ABC")); assertFalse(IOCase.SENSITIVE.checkEquals("ABC", "Abc")); assertTrue(IOCase.INSENSITIVE.checkEquals("ABC", "ABC")); assertTrue(IOCase.INSENSITIVE.checkEquals("ABC", "Abc")); assertTrue(IOCase.SYSTEM.checkEquals("ABC", "ABC")); assertEquals(WINDOWS, IOCase.SYSTEM.checkEquals("ABC", "Abc")); } @Test public void test_checkStartsWith_functionality() { assertTrue(IOCase.SENSITIVE.checkStartsWith("ABC", "")); assertTrue(IOCase.SENSITIVE.checkStartsWith("ABC", "A")); assertTrue(IOCase.SENSITIVE.checkStartsWith("ABC", "AB")); assertTrue(IOCase.SENSITIVE.checkStartsWith("ABC", "ABC")); assertFalse(IOCase.SENSITIVE.checkStartsWith("ABC", "BC")); assertFalse(IOCase.SENSITIVE.checkStartsWith("ABC", "C")); assertFalse(IOCase.SENSITIVE.checkStartsWith("ABC", "ABCD")); assertFalse(IOCase.SENSITIVE.checkStartsWith("", "ABC")); assertTrue(IOCase.SENSITIVE.checkStartsWith("", "")); assertFalse(IOCase.SENSITIVE.checkStartsWith("ABC", null)); assertFalse(IOCase.SENSITIVE.checkStartsWith(null, "ABC")); assertFalse(IOCase.SENSITIVE.checkStartsWith(null, null)); } @Test public void test_checkStartsWith_case() { assertTrue(IOCase.SENSITIVE.checkStartsWith("ABC", "AB")); assertFalse(IOCase.SENSITIVE.checkStartsWith("ABC", "Ab")); assertTrue(IOCase.INSENSITIVE.checkStartsWith("ABC", "AB")); assertTrue(IOCase.INSENSITIVE.checkStartsWith("ABC", "Ab")); assertTrue(IOCase.SYSTEM.checkStartsWith("ABC", "AB")); assertEquals(WINDOWS, IOCase.SYSTEM.checkStartsWith("ABC", "Ab")); } @Test public void test_checkEndsWith_functionality() { assertTrue(IOCase.SENSITIVE.checkEndsWith("ABC", "")); assertFalse(IOCase.SENSITIVE.checkEndsWith("ABC", "A")); assertFalse(IOCase.SENSITIVE.checkEndsWith("ABC", "AB")); assertTrue(IOCase.SENSITIVE.checkEndsWith("ABC", "ABC")); assertTrue(IOCase.SENSITIVE.checkEndsWith("ABC", "BC")); assertTrue(IOCase.SENSITIVE.checkEndsWith("ABC", "C")); assertFalse(IOCase.SENSITIVE.checkEndsWith("ABC", "ABCD")); assertFalse(IOCase.SENSITIVE.checkEndsWith("", "ABC")); assertTrue(IOCase.SENSITIVE.checkEndsWith("", "")); assertFalse(IOCase.SENSITIVE.checkEndsWith("ABC", null)); assertFalse(IOCase.SENSITIVE.checkEndsWith(null, "ABC")); assertFalse(IOCase.SENSITIVE.checkEndsWith(null, null)); } @Test public void test_checkEndsWith_case() { assertTrue(IOCase.SENSITIVE.checkEndsWith("ABC", "BC")); assertFalse(IOCase.SENSITIVE.checkEndsWith("ABC", "Bc")); assertTrue(IOCase.INSENSITIVE.checkEndsWith("ABC", "BC")); assertTrue(IOCase.INSENSITIVE.checkEndsWith("ABC", "Bc")); assertTrue(IOCase.SYSTEM.checkEndsWith("ABC", "BC")); assertEquals(WINDOWS, IOCase.SYSTEM.checkEndsWith("ABC", "Bc")); } @Test public void test_checkIndexOf_functionality() { // start assertEquals(0, IOCase.SENSITIVE.checkIndexOf("ABCDEFGHIJ", 0, "A")); assertEquals(-1, IOCase.SENSITIVE.checkIndexOf("ABCDEFGHIJ", 1, "A")); assertEquals(0, IOCase.SENSITIVE.checkIndexOf("ABCDEFGHIJ", 0, "AB")); assertEquals(-1, IOCase.SENSITIVE.checkIndexOf("ABCDEFGHIJ", 1, "AB")); assertEquals(0, IOCase.SENSITIVE.checkIndexOf("ABCDEFGHIJ", 0, "ABC")); assertEquals(-1, IOCase.SENSITIVE.checkIndexOf("ABCDEFGHIJ", 1, "ABC")); // middle assertEquals(3, IOCase.SENSITIVE.checkIndexOf("ABCDEFGHIJ", 0, "D")); assertEquals(3, IOCase.SENSITIVE.checkIndexOf("ABCDEFGHIJ", 3, "D")); assertEquals(-1, IOCase.SENSITIVE.checkIndexOf("ABCDEFGHIJ", 4, "D")); assertEquals(3, IOCase.SENSITIVE.checkIndexOf("ABCDEFGHIJ", 0, "DE")); assertEquals(3, IOCase.SENSITIVE.checkIndexOf("ABCDEFGHIJ", 3, "DE")); assertEquals(-1, IOCase.SENSITIVE.checkIndexOf("ABCDEFGHIJ", 4, "DE")); assertEquals(3, IOCase.SENSITIVE.checkIndexOf("ABCDEFGHIJ", 0, "DEF")); assertEquals(3, IOCase.SENSITIVE.checkIndexOf("ABCDEFGHIJ", 3, "DEF")); assertEquals(-1, IOCase.SENSITIVE.checkIndexOf("ABCDEFGHIJ", 4, "DEF")); // end assertEquals(9, IOCase.SENSITIVE.checkIndexOf("ABCDEFGHIJ", 0, "J")); assertEquals(9, IOCase.SENSITIVE.checkIndexOf("ABCDEFGHIJ", 8, "J")); assertEquals(9, IOCase.SENSITIVE.checkIndexOf("ABCDEFGHIJ", 9, "J")); assertEquals(8, IOCase.SENSITIVE.checkIndexOf("ABCDEFGHIJ", 0, "IJ")); assertEquals(8, IOCase.SENSITIVE.checkIndexOf("ABCDEFGHIJ", 8, "IJ")); assertEquals(-1, IOCase.SENSITIVE.checkIndexOf("ABCDEFGHIJ", 9, "IJ")); assertEquals(7, IOCase.SENSITIVE.checkIndexOf("ABCDEFGHIJ", 6, "HIJ")); assertEquals(7, IOCase.SENSITIVE.checkIndexOf("ABCDEFGHIJ", 7, "HIJ")); assertEquals(-1, IOCase.SENSITIVE.checkIndexOf("ABCDEFGHIJ", 8, "HIJ")); // not found assertEquals(-1, IOCase.SENSITIVE.checkIndexOf("ABCDEFGHIJ", 0, "DED")); // too long assertEquals(-1, IOCase.SENSITIVE.checkIndexOf("DEF", 0, "ABCDEFGHIJ")); try { IOCase.SENSITIVE.checkIndexOf("ABC", 0, null); fail(); } catch (final NullPointerException ignore) {} try { IOCase.SENSITIVE.checkIndexOf(null, 0, "ABC"); fail(); } catch (final NullPointerException ignore) {} try { IOCase.SENSITIVE.checkIndexOf(null, 0, null); fail(); } catch (final NullPointerException ignore) {} } @Test public void test_checkIndexOf_case() { assertEquals(1, IOCase.SENSITIVE.checkIndexOf("ABC", 0, "BC")); assertEquals(-1, IOCase.SENSITIVE.checkIndexOf("ABC", 0, "Bc")); assertEquals(1, IOCase.INSENSITIVE.checkIndexOf("ABC", 0, "BC")); assertEquals(1, IOCase.INSENSITIVE.checkIndexOf("ABC", 0, "Bc")); assertEquals(1, IOCase.SYSTEM.checkIndexOf("ABC", 0, "BC")); assertEquals(WINDOWS ? 1 : -1, IOCase.SYSTEM.checkIndexOf("ABC", 0, "Bc")); } @Test public void test_checkRegionMatches_functionality() { assertTrue(IOCase.SENSITIVE.checkRegionMatches("ABC", 0, "")); assertTrue(IOCase.SENSITIVE.checkRegionMatches("ABC", 0, "A")); assertTrue(IOCase.SENSITIVE.checkRegionMatches("ABC", 0, "AB")); assertTrue(IOCase.SENSITIVE.checkRegionMatches("ABC", 0, "ABC")); assertFalse(IOCase.SENSITIVE.checkRegionMatches("ABC", 0, "BC")); assertFalse(IOCase.SENSITIVE.checkRegionMatches("ABC", 0, "C")); assertFalse(IOCase.SENSITIVE.checkRegionMatches("ABC", 0, "ABCD")); assertFalse(IOCase.SENSITIVE.checkRegionMatches("", 0, "ABC")); assertTrue(IOCase.SENSITIVE.checkRegionMatches("", 0, "")); assertTrue(IOCase.SENSITIVE.checkRegionMatches("ABC", 1, "")); assertFalse(IOCase.SENSITIVE.checkRegionMatches("ABC", 1, "A")); assertFalse(IOCase.SENSITIVE.checkRegionMatches("ABC", 1, "AB")); assertFalse(IOCase.SENSITIVE.checkRegionMatches("ABC", 1, "ABC")); assertTrue(IOCase.SENSITIVE.checkRegionMatches("ABC", 1, "BC")); assertFalse(IOCase.SENSITIVE.checkRegionMatches("ABC", 1, "C")); assertFalse(IOCase.SENSITIVE.checkRegionMatches("ABC", 1, "ABCD")); assertFalse(IOCase.SENSITIVE.checkRegionMatches("", 1, "ABC")); assertFalse(IOCase.SENSITIVE.checkRegionMatches("", 1, "")); try { IOCase.SENSITIVE.checkRegionMatches("ABC", 0, null); fail(); } catch (final NullPointerException ignore) {} try { IOCase.SENSITIVE.checkRegionMatches(null, 0, "ABC"); fail(); } catch (final NullPointerException ignore) {} try { IOCase.SENSITIVE.checkRegionMatches(null, 0, null); fail(); } catch (final NullPointerException ignore) {} try { IOCase.SENSITIVE.checkRegionMatches("ABC", 1, null); fail(); } catch (final NullPointerException ignore) {} try { IOCase.SENSITIVE.checkRegionMatches(null, 1, "ABC"); fail(); } catch (final NullPointerException ignore) {} try { IOCase.SENSITIVE.checkRegionMatches(null, 1, null); fail(); } catch (final NullPointerException ignore) {} } @Test public void test_checkRegionMatches_case() { assertTrue(IOCase.SENSITIVE.checkRegionMatches("ABC", 0, "AB")); assertFalse(IOCase.SENSITIVE.checkRegionMatches("ABC", 0, "Ab")); assertTrue(IOCase.INSENSITIVE.checkRegionMatches("ABC", 0, "AB")); assertTrue(IOCase.INSENSITIVE.checkRegionMatches("ABC", 0, "Ab")); assertTrue(IOCase.SYSTEM.checkRegionMatches("ABC", 0, "AB")); assertEquals(WINDOWS, IOCase.SYSTEM.checkRegionMatches("ABC", 0, "Ab")); } private IOCase serialize(final IOCase value) throws Exception { final ByteArrayOutputStream buf = new ByteArrayOutputStream(); final ObjectOutputStream out = new ObjectOutputStream(buf); out.writeObject(value); out.flush(); out.close(); final ByteArrayInputStream bufin = new ByteArrayInputStream(buf.toByteArray()); final ObjectInputStream in = new ObjectInputStream(bufin); return (IOCase) in.readObject(); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/IOExceptionListTestCase.java0100644 0000000 0000000 00000007414 13612062727 031115 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.EOFException; import java.io.PrintWriter; import java.io.StringWriter; import java.util.Collections; import java.util.List; import org.junit.jupiter.api.Test; /** * Tests {@link IOExceptionList}. */ public class IOExceptionListTestCase { @Test public void testCause() { final EOFException cause = new EOFException(); final List list = Collections.singletonList(cause); final IOExceptionList sqlExceptionList = new IOExceptionList(list); assertEquals(cause, sqlExceptionList.getCause()); assertEquals(cause, sqlExceptionList.getCause(0)); assertEquals(list, sqlExceptionList.getCauseList()); assertEquals(list, sqlExceptionList.getCauseList(EOFException.class)); assertEquals(cause, sqlExceptionList.getCause(0, EOFException.class)); // No CCE: final List causeList = sqlExceptionList.getCauseList(); assertEquals(list, causeList); } @Test public void testEmptyList() { new IOExceptionList(Collections.emptyList()); new IOExceptionList("foo", Collections.emptyList()); } @Test public void testMessageCause() { final EOFException cause = new EOFException(); final List list = Collections.singletonList(cause); final IOExceptionList sqlExceptionList = new IOExceptionList("Hello", list); assertEquals("Hello", sqlExceptionList.getMessage()); // assertEquals(cause, sqlExceptionList.getCause()); assertEquals(cause, sqlExceptionList.getCause(0)); assertEquals(list, sqlExceptionList.getCauseList()); assertEquals(list, sqlExceptionList.getCauseList(EOFException.class)); assertEquals(cause, sqlExceptionList.getCause(0, EOFException.class)); // No CCE: final List causeList = sqlExceptionList.getCauseList(); assertEquals(list, causeList); } @Test public void testNullCause() { final IOExceptionList sqlExceptionList = new IOExceptionList(null); assertNull(sqlExceptionList.getCause()); assertTrue(sqlExceptionList.getCauseList().isEmpty()); } @Test public void testPrintStackTrace() { final EOFException cause = new EOFException(); final List list = Collections.singletonList(cause); final IOExceptionList sqlExceptionList = new IOExceptionList(list); final StringWriter sw = new StringWriter(); final PrintWriter pw = new PrintWriter(sw); sqlExceptionList.printStackTrace(pw); final String st = sw.toString(); assertTrue(st.startsWith("org.apache.commons.io.IOExceptionList: 1 exceptions: [java.io.EOFException]")); assertTrue(st.contains("Caused by: java.io.EOFException")); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/IOExceptionWithCauseTestCase.java0100644 0000000 0000000 00000004171 13612062727 032073 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertSame; import java.io.IOException; import org.junit.jupiter.api.Test; /** * Tests IOExceptionWithCause * */ public class IOExceptionWithCauseTestCase { /** * Tests the {@link IOExceptionWithCause#IOExceptionWithCause(String,Throwable)} constructor. */ @Test public void testIOExceptionStringThrowable() { final Throwable cause = new IllegalArgumentException("cause"); final IOException exception = new IOException("message", cause); this.validate(exception, cause, "message"); } /** * Tests the {@link IOExceptionWithCause#IOExceptionWithCause(Throwable)} constructor. */ @Test public void testIOExceptionThrowable() { final Throwable cause = new IllegalArgumentException("cause"); final IOException exception = new IOException(cause); this.validate(exception, cause, "java.lang.IllegalArgumentException: cause"); } void validate(final Throwable throwable, final Throwable expectedCause, final String expectedMessage) { assertEquals(expectedMessage, throwable.getMessage()); assertEquals(expectedCause, throwable.getCause()); assertSame(expectedCause, throwable.getCause()); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/IOIndexedExceptionTestCase.java0100644 0000000 0000000 00000003354 13612062727 031561 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import java.io.EOFException; import org.junit.jupiter.api.Test; /** * Tests {@link IOIndexedException}. * * @since 2.7 */ public class IOIndexedExceptionTestCase { @Test public void testEdge() { final IOIndexedException exception = new IOIndexedException(-1, null); assertEquals(-1, exception.getIndex()); assertNull(exception.getCause()); assertNotNull(exception.getMessage()); } @Test public void testPlain() { final EOFException e = new EOFException("end"); final IOIndexedException exception = new IOIndexedException(0, e); assertEquals(0, exception.getIndex()); assertEquals(e, exception.getCause()); assertNotNull(exception.getMessage()); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/IOUtilsCopyTestCase.java0100644 0000000 0000000 00000047506 13612062727 030264 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Reader; import java.io.Writer; import java.net.URL; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import org.apache.commons.io.input.NullInputStream; import org.apache.commons.io.input.NullReader; import org.apache.commons.io.output.ByteArrayOutputStream; import org.apache.commons.io.output.NullOutputStream; import org.apache.commons.io.output.NullWriter; import org.apache.commons.io.test.TestUtils; import org.apache.commons.io.test.ThrowOnCloseInputStream; import org.apache.commons.io.test.ThrowOnFlushAndCloseOutputStream; import org.junit.jupiter.api.Test; /** * JUnit tests for IOUtils copy methods. * * @see IOUtils */ public class IOUtilsCopyTestCase { /* * NOTE this is not particularly beautiful code. A better way to check for * flush and close status would be to implement "trojan horse" wrapper * implementations of the various stream classes, which set a flag when * relevant methods are called. (JT) */ private static final int FILE_SIZE = 1024 * 4 + 1; private final byte[] inData = TestUtils.generateTestData(FILE_SIZE); @SuppressWarnings("resource") // 'in' is deliberately not closed @Test public void testCopy_inputStreamToOutputStream() throws Exception { InputStream in = new ByteArrayInputStream(inData); in = new ThrowOnCloseInputStream(in); final ByteArrayOutputStream baout = new ByteArrayOutputStream(); final OutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, false, true); final int count = IOUtils.copy(in, out); assertEquals(0, in.available(), "Not all bytes were read"); assertEquals(inData.length, baout.size(), "Sizes differ"); assertArrayEquals(inData, baout.toByteArray(), "Content differs"); assertEquals(inData.length,count); } /** * Test Copying file > 2GB - see issue# IO-84 */ @Test public void testCopy_inputStreamToOutputStream_IO84() throws Exception { final long size = (long)Integer.MAX_VALUE + (long)1; final InputStream in = new NullInputStream(size); final OutputStream out = NullOutputStream.NULL_OUTPUT_STREAM; // Test copy() method assertEquals(-1, IOUtils.copy(in, out)); // reset the input in.close(); // Test copyLarge() method assertEquals(size, IOUtils.copyLarge(in, out), "copyLarge()"); } @Test public void testCopy_inputStreamToOutputStream_nullIn() { final OutputStream out = new ByteArrayOutputStream(); assertThrows(NullPointerException.class, () -> IOUtils.copy((InputStream) null, out)); } @Test public void testCopy_inputStreamToOutputStream_nullOut() { final InputStream in = new ByteArrayInputStream(inData); assertThrows(NullPointerException.class, () -> IOUtils.copy(in, (OutputStream) null)); } @Test public void testCopy_inputStreamToOutputStreamWithBufferSize() throws Exception { testCopy_inputStreamToOutputStreamWithBufferSize(1); testCopy_inputStreamToOutputStreamWithBufferSize(2); testCopy_inputStreamToOutputStreamWithBufferSize(4); testCopy_inputStreamToOutputStreamWithBufferSize(8); testCopy_inputStreamToOutputStreamWithBufferSize(16); testCopy_inputStreamToOutputStreamWithBufferSize(32); testCopy_inputStreamToOutputStreamWithBufferSize(64); testCopy_inputStreamToOutputStreamWithBufferSize(128); testCopy_inputStreamToOutputStreamWithBufferSize(256); testCopy_inputStreamToOutputStreamWithBufferSize(512); testCopy_inputStreamToOutputStreamWithBufferSize(1024); testCopy_inputStreamToOutputStreamWithBufferSize(2048); testCopy_inputStreamToOutputStreamWithBufferSize(4096); testCopy_inputStreamToOutputStreamWithBufferSize(8192); testCopy_inputStreamToOutputStreamWithBufferSize(16384); } @SuppressWarnings("resource") // 'in' is deliberately not closed private void testCopy_inputStreamToOutputStreamWithBufferSize(final int bufferSize) throws Exception { InputStream in = new ByteArrayInputStream(inData); in = new ThrowOnCloseInputStream(in); final ByteArrayOutputStream baout = new ByteArrayOutputStream(); final OutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, false, true); final long count = IOUtils.copy(in, out, bufferSize); assertEquals(0, in.available(), "Not all bytes were read"); assertEquals(inData.length, baout.size(), "Sizes differ"); assertArrayEquals(inData, baout.toByteArray(), "Content differs"); assertEquals(inData.length,count); } @SuppressWarnings({ "resource", "deprecation" }) // 'in' is deliberately not closed @Test public void testCopy_inputStreamToWriter() throws Exception { InputStream in = new ByteArrayInputStream(inData); in = new ThrowOnCloseInputStream(in); final ByteArrayOutputStream baout = new ByteArrayOutputStream(); final ThrowOnFlushAndCloseOutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, true, true); final Writer writer = new OutputStreamWriter(baout, StandardCharsets.US_ASCII); IOUtils.copy(in, writer); // deliberately testing deprecated method out.off(); writer.flush(); assertEquals(0, in.available(), "Not all bytes were read"); assertEquals(inData.length, baout.size(), "Sizes differ"); assertArrayEquals(inData, baout.toByteArray(), "Content differs"); } @SuppressWarnings("resource") // 'in' is deliberately not closed @Test public void testCopy_inputStreamToWriter_Encoding() throws Exception { InputStream in = new ByteArrayInputStream(inData); in = new ThrowOnCloseInputStream(in); final ByteArrayOutputStream baout = new ByteArrayOutputStream(); final ThrowOnFlushAndCloseOutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, true, true); final Writer writer = new OutputStreamWriter(baout, StandardCharsets.US_ASCII); IOUtils.copy(in, writer, "UTF8"); out.off(); writer.flush(); assertEquals(0, in.available(), "Not all bytes were read"); byte[] bytes = baout.toByteArray(); bytes = new String(bytes, StandardCharsets.UTF_8).getBytes(StandardCharsets.US_ASCII); assertArrayEquals(inData, bytes, "Content differs"); } @SuppressWarnings("resource") // 'in' is deliberately not closed @Test public void testCopy_inputStreamToWriter_Encoding_nullEncoding() throws Exception { InputStream in = new ByteArrayInputStream(inData); in = new ThrowOnCloseInputStream(in); final ByteArrayOutputStream baout = new ByteArrayOutputStream(); final ThrowOnFlushAndCloseOutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, true, true); final Writer writer = new OutputStreamWriter(baout, StandardCharsets.US_ASCII); IOUtils.copy(in, writer, (String) null); out.off(); writer.flush(); assertEquals(0, in.available(), "Not all bytes were read"); assertEquals(inData.length, baout.size(), "Sizes differ"); assertArrayEquals(inData, baout.toByteArray(), "Content differs"); } @Test public void testCopy_inputStreamToWriter_Encoding_nullIn() { final ByteArrayOutputStream baout = new ByteArrayOutputStream(); final OutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, true, true); final Writer writer = new OutputStreamWriter(out, StandardCharsets.US_ASCII); assertThrows(NullPointerException.class, () -> IOUtils.copy(null, writer, "UTF8")); } @Test public void testCopy_inputStreamToWriter_Encoding_nullOut() { final InputStream in = new ByteArrayInputStream(inData); assertThrows(NullPointerException.class, () -> IOUtils.copy(in, null, "UTF8")); } @SuppressWarnings("deprecation") // deliberately testing deprecated method @Test public void testCopy_inputStreamToWriter_nullIn() { final ByteArrayOutputStream baout = new ByteArrayOutputStream(); final OutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, true, true); final Writer writer = new OutputStreamWriter(out, StandardCharsets.US_ASCII); assertThrows(NullPointerException.class, () -> IOUtils.copy((InputStream) null, writer)); } @SuppressWarnings("deprecation") // deliberately testing deprecated method @Test public void testCopy_inputStreamToWriter_nullOut() { final InputStream in = new ByteArrayInputStream(inData); assertThrows(NullPointerException.class, () -> IOUtils.copy(in, (Writer) null)); // deliberately testing deprecated method } @SuppressWarnings("resource") // 'in' is deliberately not closed @Test public void testCopy_readerToAppendable() throws Exception { InputStream in = new ByteArrayInputStream(inData); in = new ThrowOnCloseInputStream(in); final Reader reader = new InputStreamReader(in, StandardCharsets.US_ASCII); final ByteArrayOutputStream baout = new ByteArrayOutputStream(); final ThrowOnFlushAndCloseOutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, true, true); final Writer writer = new OutputStreamWriter(baout, StandardCharsets.US_ASCII); final long count = IOUtils.copy(reader, (Appendable) writer); out.off(); writer.flush(); assertEquals(inData.length, count, "The number of characters returned by copy is wrong"); assertEquals(inData.length, baout.size(), "Sizes differ"); assertArrayEquals(inData, baout.toByteArray(), "Content differs"); } @Test public void testCopy_readerToAppendable_IO84() throws Exception { final long size = (long) Integer.MAX_VALUE + (long) 1; final Reader reader = new NullReader(size); final NullWriter writer = new NullWriter(); // Test copy() method assertEquals(size, IOUtils.copy(reader, (Appendable) writer)); // reset the input reader.close(); // Test copyLarge() method assertEquals(size, IOUtils.copyLarge(reader, writer), "copy()"); } @Test public void testCopy_readerToAppendable_nullIn() { final ByteArrayOutputStream baout = new ByteArrayOutputStream(); final OutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, true, true); final Appendable writer = new OutputStreamWriter(out, StandardCharsets.US_ASCII); assertThrows(NullPointerException.class, () -> IOUtils.copy((Reader) null, writer)); } @SuppressWarnings("resource") // 'in' is deliberately not closed @Test public void testCopy_readerToAppendable_nullOut() { InputStream in = new ByteArrayInputStream(inData); in = new ThrowOnCloseInputStream(in); final Reader reader = new InputStreamReader(in, StandardCharsets.US_ASCII); assertThrows(NullPointerException.class, () -> IOUtils.copy(reader, (Appendable) null)); } @SuppressWarnings({ "resource", "deprecation" }) // 'in' is deliberately not closed @Test public void testCopy_readerToOutputStream() throws Exception { InputStream in = new ByteArrayInputStream(inData); in = new ThrowOnCloseInputStream(in); final Reader reader = new InputStreamReader(in, StandardCharsets.US_ASCII); final ByteArrayOutputStream baout = new ByteArrayOutputStream(); final OutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, false, true); IOUtils.copy(reader, out); // deliberately testing deprecated method //Note: this method *does* flush. It is equivalent to: // OutputStreamWriter _out = new OutputStreamWriter(fout); // IOUtils.copy( fin, _out, 4096 ); // copy( Reader, Writer, int ); // _out.flush(); // out = fout; // Note: rely on the method to flush assertEquals(inData.length, baout.size(), "Sizes differ"); assertArrayEquals(inData, baout.toByteArray(), "Content differs"); } @SuppressWarnings("resource") // 'in' is deliberately not closed @Test public void testCopy_readerToOutputStream_Encoding() throws Exception { InputStream in = new ByteArrayInputStream(inData); in = new ThrowOnCloseInputStream(in); final Reader reader = new InputStreamReader(in, StandardCharsets.US_ASCII); final ByteArrayOutputStream baout = new ByteArrayOutputStream(); final OutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, false, true); IOUtils.copy(reader, out, "UTF16"); // note: this method *does* flush. // note: we don't flush here; this IOUtils method does it for us byte[] bytes = baout.toByteArray(); bytes = new String(bytes, StandardCharsets.UTF_16).getBytes(StandardCharsets.US_ASCII); assertArrayEquals(inData, bytes, "Content differs"); } @SuppressWarnings("resource") // 'in' is deliberately not closed @Test public void testCopy_readerToOutputStream_Encoding_nullEncoding() throws Exception { InputStream in = new ByteArrayInputStream(inData); in = new ThrowOnCloseInputStream(in); final Reader reader = new InputStreamReader(in, StandardCharsets.US_ASCII); final ByteArrayOutputStream baout = new ByteArrayOutputStream(); final OutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, false, true); IOUtils.copy(reader, out, (String) null); // note: this method *does* flush. // note: we don't flush here; this IOUtils method does it for us assertEquals(inData.length, baout.size(), "Sizes differ"); assertArrayEquals(inData, baout.toByteArray(), "Content differs"); } @Test public void testCopy_readerToOutputStream_Encoding_nullIn() { final ByteArrayOutputStream baout = new ByteArrayOutputStream(); final OutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, true, true); assertThrows(NullPointerException.class, () -> IOUtils.copy(null, out, "UTF16")); } @SuppressWarnings("resource") // 'in' is deliberately not closed @Test public void testCopy_readerToOutputStream_Encoding_nullOut() { InputStream in = new ByteArrayInputStream(inData); in = new ThrowOnCloseInputStream(in); final Reader reader = new InputStreamReader(in, StandardCharsets.US_ASCII); assertThrows(NullPointerException.class, () -> IOUtils.copy(reader, null, "UTF16")); } @SuppressWarnings("deprecation") @Test public void testCopy_readerToOutputStream_nullIn() { // deliberately testing deprecated method final ByteArrayOutputStream baout = new ByteArrayOutputStream(); final OutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, true, true); assertThrows(NullPointerException.class, () -> IOUtils.copy((Reader) null, out)); } @SuppressWarnings({ "resource", "deprecation" }) // 'in' is deliberately not closed @Test public void testCopy_readerToOutputStream_nullOut() { InputStream in = new ByteArrayInputStream(inData); in = new ThrowOnCloseInputStream(in); final Reader reader = new InputStreamReader(in, StandardCharsets.US_ASCII); assertThrows(NullPointerException.class, () -> IOUtils.copy(reader, (OutputStream) null)); // deliberately testing deprecated method } @SuppressWarnings("resource") // 'in' is deliberately not closed @Test public void testCopy_readerToWriter() throws Exception { InputStream in = new ByteArrayInputStream(inData); in = new ThrowOnCloseInputStream(in); final Reader reader = new InputStreamReader(in, StandardCharsets.US_ASCII); final ByteArrayOutputStream baout = new ByteArrayOutputStream(); final ThrowOnFlushAndCloseOutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, true, true); final Writer writer = new OutputStreamWriter(baout, StandardCharsets.US_ASCII); final int count = IOUtils.copy(reader, writer); out.off(); writer.flush(); assertEquals(inData.length, count, "The number of characters returned by copy is wrong"); assertEquals(inData.length, baout.size(), "Sizes differ"); assertArrayEquals(inData, baout.toByteArray(), "Content differs"); } /* * Test Copying file > 2GB - see issue# IO-84 */ @Test public void testCopy_readerToWriter_IO84() throws Exception { final long size = (long)Integer.MAX_VALUE + (long)1; final Reader reader = new NullReader(size); final Writer writer = new NullWriter(); // Test copy() method assertEquals(-1, IOUtils.copy(reader, writer)); // reset the input reader.close(); // Test copyLarge() method assertEquals(size, IOUtils.copyLarge(reader, writer), "copyLarge()"); } @Test public void testCopy_readerToWriter_nullIn() { final ByteArrayOutputStream baout = new ByteArrayOutputStream(); final OutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, true, true); final Writer writer = new OutputStreamWriter(out, StandardCharsets.US_ASCII); assertThrows(NullPointerException.class, () -> IOUtils.copy((Reader) null, writer)); } @SuppressWarnings("resource") // 'in' is deliberately not closed @Test public void testCopy_readerToWriter_nullOut() { InputStream in = new ByteArrayInputStream(inData); in = new ThrowOnCloseInputStream(in); final Reader reader = new InputStreamReader(in, StandardCharsets.US_ASCII); assertThrows(NullPointerException.class, () -> IOUtils.copy(reader, (Writer) null)); } @Test public void testCopy_URLToFile() throws Exception { final String name = "/org/apache/commons/io/abitmorethan16k.txt"; final URL in = getClass().getResource(name); assertNotNull(in, name); final Path path = Files.createTempFile("testCopy_URLToFile", ".txt"); try { IOUtils.copy(in, path.toFile()); assertArrayEquals(Files.readAllBytes(Paths.get("src/test/resources" + name)), Files.readAllBytes(path)); } finally { Files.delete(path); } } @Test public void testCopy_URLToOutputStream() throws Exception { final String name = "/org/apache/commons/io/abitmorethan16k.txt"; final URL in = getClass().getResource(name); assertNotNull(in, name); final ByteArrayOutputStream baout = new ByteArrayOutputStream(); IOUtils.copy(in, baout); assertArrayEquals(Files.readAllBytes(Paths.get("src/test/resources" + name)), baout.toByteArray()); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/IOUtilsTestCase.java0100644 0000000 0000000 00000200110 13612062727 027407 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNotSame; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.CharArrayReader; import java.io.CharArrayWriter; import java.io.Closeable; import java.io.EOFException; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.Reader; import java.io.StringReader; import java.io.Writer; import java.net.ServerSocket; import java.net.Socket; import java.net.URI; import java.net.URL; import java.net.URLConnection; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.nio.channels.Selector; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.Arrays; import java.util.List; import org.apache.commons.io.function.IOConsumer; import org.apache.commons.io.input.CircularInputStream; import org.apache.commons.io.input.NullInputStream; import org.apache.commons.io.output.AppendableWriter; import org.apache.commons.io.output.NullOutputStream; import org.apache.commons.io.output.StringBuilderWriter; import org.apache.commons.io.test.TestUtils; import org.apache.commons.io.test.ThrowOnCloseReader; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; /** * This is used to test IOUtils for correctness. The following checks are performed: *
    *
  • The return must not be null, must be the same type and equals() to the method's second arg
  • *
  • All bytes must have been read from the source (available() == 0)
  • *
  • The source and destination content must be identical (byte-wise comparison check)
  • *
  • The output stream must not have been closed (a byte/char is written to test this, and subsequent size * checked)
  • *
* Due to interdependencies in IOUtils and IOUtilsTestlet, one bug may cause multiple tests to fail. */ @SuppressWarnings("deprecation") // deliberately testing deprecated code public class IOUtilsTestCase { private static final int FILE_SIZE = 1024 * 4 + 1; /** Determine if this is windows. */ private static final boolean WINDOWS = File.separatorChar == '\\'; /* * Note: this is not particularly beautiful code. A better way to check for flush and close status would be to * implement "trojan horse" wrapper implementations of the various stream classes, which set a flag when relevant * methods are called. (JT) */ @TempDir public File temporaryFolder; private char[] carr; private byte[] iarr; private File testFile; /** * Path constructed from {@code testFile}. */ private Path testFilePath; /** Assert that the contents of two byte arrays are the same. */ private void assertEqualContent(final byte[] b0, final byte[] b1) { assertArrayEquals(b0, b1, "Content not equal according to java.util.Arrays#equals()"); } @BeforeEach public void setUp() { try { testFile = new File(temporaryFolder, "file2-test.txt"); testFilePath = testFile.toPath(); if (!testFile.getParentFile().exists()) { throw new IOException("Cannot create file " + testFile + " as the parent directory does not exist"); } final BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(testFilePath)); try { TestUtils.generateTestData(output, FILE_SIZE); } finally { IOUtils.closeQuietly(output); } } catch (final IOException ioe) { throw new RuntimeException( "Can't run this test because the environment could not be built: " + ioe.getMessage()); } // Create and init a byte array as input data iarr = new byte[200]; Arrays.fill(iarr, (byte) -1); for (int i = 0; i < 80; i++) { iarr[i] = (byte) i; } carr = new char[200]; Arrays.fill(carr, (char) -1); for (int i = 0; i < 80; i++) { carr[i] = (char) i; } } @Test public void testAsBufferedInputStream() { final InputStream is = new InputStream() { @Override public int read() throws IOException { return 0; } }; final BufferedInputStream bis = IOUtils.buffer(is); assertNotSame(is, bis); assertSame(bis, IOUtils.buffer(bis)); } @Test public void testAsBufferedInputStreamWithBufferSize() { final InputStream is = new InputStream() { @Override public int read() throws IOException { return 0; } }; final BufferedInputStream bis = IOUtils.buffer(is, 2048); assertNotSame(is, bis); assertSame(bis, IOUtils.buffer(bis)); assertSame(bis, IOUtils.buffer(bis, 1024)); } @Test public void testAsBufferedNull() { try { IOUtils.buffer((InputStream) null); fail("Expected NullPointerException"); } catch (final NullPointerException npe) { // expected } try { IOUtils.buffer((OutputStream) null); fail("Expected NullPointerException"); } catch (final NullPointerException npe) { // expected } try { IOUtils.buffer((Reader) null); fail("Expected NullPointerException"); } catch (final NullPointerException npe) { // expected } try { IOUtils.buffer((Writer) null); fail("Expected NullPointerException"); } catch (final NullPointerException npe) { // expected } } @Test public void testAsBufferedOutputStream() { final OutputStream is = new OutputStream() { @Override public void write(final int b) throws IOException { } }; final BufferedOutputStream bis = IOUtils.buffer(is); assertNotSame(is, bis); assertSame(bis, IOUtils.buffer(bis)); } @Test public void testAsBufferedOutputStreamWithBufferSize() { final OutputStream os = new OutputStream() { @Override public void write(final int b) throws IOException { } }; final BufferedOutputStream bos = IOUtils.buffer(os, 2048); assertNotSame(os, bos); assertSame(bos, IOUtils.buffer(bos)); assertSame(bos, IOUtils.buffer(bos, 1024)); } @Test public void testAsBufferedReader() { final Reader is = new Reader() { @Override public void close() throws IOException { } @Override public int read(final char[] cbuf, final int off, final int len) throws IOException { return 0; } }; final BufferedReader bis = IOUtils.buffer(is); assertNotSame(is, bis); assertSame(bis, IOUtils.buffer(bis)); } @Test public void testAsBufferedReaderWithBufferSize() { final Reader r = new Reader() { @Override public void close() throws IOException { } @Override public int read(final char[] cbuf, final int off, final int len) throws IOException { return 0; } }; final BufferedReader br = IOUtils.buffer(r, 2048); assertNotSame(r, br); assertSame(br, IOUtils.buffer(br)); assertSame(br, IOUtils.buffer(br, 1024)); } @Test public void testAsBufferedWriter() { final Writer is = new Writer() { @Override public void close() throws IOException { } @Override public void flush() throws IOException { } @Override public void write(final char[] cbuf, final int off, final int len) throws IOException { } @Override public void write(final int b) throws IOException { } }; final BufferedWriter bis = IOUtils.buffer(is); assertNotSame(is, bis); assertSame(bis, IOUtils.buffer(bis)); } @Test public void testAsBufferedWriterWithBufferSize() { final Writer w = new Writer() { @Override public void close() throws IOException { } @Override public void flush() throws IOException { } @Override public void write(final char[] cbuf, final int off, final int len) throws IOException { } @Override public void write(final int b) throws IOException { } }; final BufferedWriter bw = IOUtils.buffer(w, 2024); assertNotSame(w, bw); assertSame(bw, IOUtils.buffer(bw)); assertSame(bw, IOUtils.buffer(bw, 1024)); } @Test public void testAsWriterAppendable() { final Appendable a = new StringBuffer(); final Writer w = IOUtils.writer(a); assertNotSame(w, a); assertEquals(AppendableWriter.class, w.getClass()); assertSame(w, IOUtils.writer(w)); } @Test public void testAsWriterNull() { assertThrows(NullPointerException.class, () -> IOUtils.writer(null)); } @Test public void testAsWriterStringBuilder() { final Appendable a = new StringBuilder(); final Writer w = IOUtils.writer(a); assertNotSame(w, a); assertEquals(StringBuilderWriter.class, w.getClass()); assertSame(w, IOUtils.writer(w)); } @Test public void testClose() { assertDoesNotThrow(() -> IOUtils.close((Closeable) null)); assertDoesNotThrow(() -> IOUtils.close(new StringReader("s"))); assertThrows(IOException.class, () -> IOUtils.close(new ThrowOnCloseReader(new StringReader("s")))); } @Test public void testCloseConsumer() { final Closeable nullCloseable = null; assertDoesNotThrow(() -> IOUtils.close(nullCloseable, null)); // null consumer assertDoesNotThrow(() -> IOUtils.close(new StringReader("s"), null)); // null consumer assertDoesNotThrow(() -> IOUtils.close(new ThrowOnCloseReader(new StringReader("s")), null)); // null consumer final IOConsumer nullConsumer = null; // null consumer doesn't throw assertDoesNotThrow(() -> IOUtils.close(nullCloseable, nullConsumer)); assertDoesNotThrow(() -> IOUtils.close(new StringReader("s"), nullConsumer)); assertDoesNotThrow(() -> IOUtils.close(new ThrowOnCloseReader(new StringReader("s")), nullConsumer)); final IOConsumer silentConsumer = IOConsumer.noop(); // noop consumer doesn't throw assertDoesNotThrow(() -> IOUtils.close(nullCloseable, silentConsumer)); assertDoesNotThrow(() -> IOUtils.close(new StringReader("s"), silentConsumer)); assertDoesNotThrow(() -> IOUtils.close(new ThrowOnCloseReader(new StringReader("s")), silentConsumer)); final IOConsumer noisyConsumer = i -> { throw i; }; // consumer passes on the throw assertDoesNotThrow(() -> IOUtils.close(nullCloseable, noisyConsumer)); // no throw assertDoesNotThrow(() -> IOUtils.close(new StringReader("s"), noisyConsumer)); // no throw assertThrows(IOException.class, () -> IOUtils.close(new ThrowOnCloseReader(new StringReader("s")), noisyConsumer)); // closeable throws } @Test public void testCloseMulti() { final Closeable nullCloseable = null; final Closeable[] closeables = {null, null}; assertDoesNotThrow(() -> IOUtils.close(nullCloseable, nullCloseable)); assertDoesNotThrow(() -> IOUtils.close(closeables)); assertDoesNotThrow(() -> IOUtils.close((Closeable[]) null)); assertDoesNotThrow(() -> IOUtils.close(new StringReader("s"), nullCloseable)); assertThrows(IOException.class, () -> IOUtils.close(nullCloseable, new ThrowOnCloseReader(new StringReader("s")))); } @Test public void testCloseQuietly_AllCloseableIOException() { final Closeable closeable = () -> { throw new IOException(); }; assertDoesNotThrow(() -> IOUtils.closeQuietly(closeable, null, closeable)); } @Test public void testCloseQuietly_CloseableIOException() { assertDoesNotThrow(() -> { IOUtils.closeQuietly((Closeable) () -> { throw new IOException(); }); }); } @SuppressWarnings("squid:S2699") // Suppress "Add at least one assertion to this test case" @Test public void testCloseQuietly_Selector() { Selector selector = null; try { selector = Selector.open(); } catch (final IOException ignore) { } finally { IOUtils.closeQuietly(selector); } } @SuppressWarnings("squid:S2699") // Suppress "Add at least one assertion to this test case" @Test public void testCloseQuietly_SelectorIOException() { final Selector selector = new SelectorAdapter() { @Override public void close() throws IOException { throw new IOException(); } }; IOUtils.closeQuietly(selector); } @SuppressWarnings("squid:S2699") // Suppress "Add at least one assertion to this test case" @Test public void testCloseQuietly_SelectorNull() { final Selector selector = null; IOUtils.closeQuietly(selector); } @SuppressWarnings("squid:S2699") // Suppress "Add at least one assertion to this test case" @Test public void testCloseQuietly_SelectorTwice() { Selector selector = null; try { selector = Selector.open(); } catch (final IOException ignore) { } finally { IOUtils.closeQuietly(selector); IOUtils.closeQuietly(selector); } } @Test public void testCloseQuietly_ServerSocket() { assertDoesNotThrow(() -> IOUtils.closeQuietly((ServerSocket) null)); assertDoesNotThrow(() -> IOUtils.closeQuietly(new ServerSocket())); } @Test public void testCloseQuietly_ServerSocketIOException() { assertDoesNotThrow(() -> { IOUtils.closeQuietly(new ServerSocket() { @Override public void close() throws IOException { throw new IOException(); } }); }); } @Test public void testCloseQuietly_Socket() { assertDoesNotThrow(() -> IOUtils.closeQuietly((Socket) null)); assertDoesNotThrow(() -> IOUtils.closeQuietly(new Socket())); } @Test public void testCloseQuietly_SocketIOException() { assertDoesNotThrow(() -> { IOUtils.closeQuietly(new Socket() { @Override public synchronized void close() throws IOException { throw new IOException(); } }); }); } @Test public void testConstants() { assertEquals('/', IOUtils.DIR_SEPARATOR_UNIX); assertEquals('\\', IOUtils.DIR_SEPARATOR_WINDOWS); assertEquals("\n", IOUtils.LINE_SEPARATOR_UNIX); assertEquals("\r\n", IOUtils.LINE_SEPARATOR_WINDOWS); if (WINDOWS) { assertEquals('\\', IOUtils.DIR_SEPARATOR); assertEquals("\r\n", IOUtils.LINE_SEPARATOR); } else { assertEquals('/', IOUtils.DIR_SEPARATOR); assertEquals("\n", IOUtils.LINE_SEPARATOR); } assertEquals('\r', IOUtils.CR); assertEquals('\n', IOUtils.LF); assertEquals(-1, IOUtils.EOF); } @Test public void testConsume() throws Exception { final long size = (long) Integer.MAX_VALUE + (long) 1; final InputStream in = new NullInputStream(size); final OutputStream out = NullOutputStream.NULL_OUTPUT_STREAM; // Test copy() method assertEquals(-1, IOUtils.copy(in, out)); // reset the input in.close(); // Test consume() method assertEquals(size, IOUtils.consume(in), "consume()"); } @Test public void testContentEquals_InputStream_InputStream() throws Exception { { assertTrue(IOUtils.contentEquals((InputStream) null, null)); } final byte[] dataEmpty = "".getBytes(StandardCharsets.UTF_8); final byte[] dataAbc = "ABC".getBytes(StandardCharsets.UTF_8); final byte[] dataAbcd = "ABCD".getBytes(StandardCharsets.UTF_8); { final ByteArrayInputStream input1 = new ByteArrayInputStream(dataEmpty); assertFalse(IOUtils.contentEquals(input1, null)); } { final ByteArrayInputStream input1 = new ByteArrayInputStream(dataEmpty); assertFalse(IOUtils.contentEquals(null, input1)); } { final ByteArrayInputStream input1 = new ByteArrayInputStream(dataEmpty); assertTrue(IOUtils.contentEquals(input1, input1)); } { final ByteArrayInputStream input1 = new ByteArrayInputStream(dataAbc); assertTrue(IOUtils.contentEquals(input1, input1)); } assertTrue(IOUtils.contentEquals(new ByteArrayInputStream(dataEmpty), new ByteArrayInputStream(dataEmpty))); assertTrue(IOUtils.contentEquals(new BufferedInputStream(new ByteArrayInputStream(dataEmpty)), new BufferedInputStream(new ByteArrayInputStream(dataEmpty)))); assertTrue(IOUtils.contentEquals(new ByteArrayInputStream(dataAbc), new ByteArrayInputStream(dataAbc))); assertFalse(IOUtils.contentEquals(new ByteArrayInputStream(dataAbcd), new ByteArrayInputStream(dataAbc))); assertFalse(IOUtils.contentEquals(new ByteArrayInputStream(dataAbc), new ByteArrayInputStream(dataAbcd))); // Tests with larger inputs that DEFAULT_BUFFER_SIZE in case internal buffers are used. final byte[] bytes2XDefaultA = new byte[IOUtils.DEFAULT_BUFFER_SIZE * 2]; final byte[] bytes2XDefaultB = new byte[IOUtils.DEFAULT_BUFFER_SIZE * 2]; final byte[] bytes2XDefaultA2 = new byte[IOUtils.DEFAULT_BUFFER_SIZE * 2]; Arrays.fill(bytes2XDefaultA, (byte) 'a'); Arrays.fill(bytes2XDefaultB, (byte) 'b'); Arrays.fill(bytes2XDefaultA2, (byte) 'a'); bytes2XDefaultA2[bytes2XDefaultA2.length - 1] = 'd'; assertFalse(IOUtils.contentEquals(new ByteArrayInputStream(bytes2XDefaultA), new ByteArrayInputStream(bytes2XDefaultB))); assertFalse(IOUtils.contentEquals(new ByteArrayInputStream(bytes2XDefaultA), new ByteArrayInputStream(bytes2XDefaultA2))); assertTrue(IOUtils.contentEquals(new ByteArrayInputStream(bytes2XDefaultA), new ByteArrayInputStream(bytes2XDefaultA))); // FileInputStream a bit more than 16 k. try ( final FileInputStream input1 = new FileInputStream( "src/test/resources/org/apache/commons/io/abitmorethan16k.txt"); final FileInputStream input2 = new FileInputStream( "src/test/resources/org/apache/commons/io/abitmorethan16kcopy.txt")) { assertTrue(IOUtils.contentEquals(input1, input1)); } } @Test public void testContentEquals_Reader_Reader() throws Exception { { assertTrue(IOUtils.contentEquals((Reader) null, null)); } { final StringReader input1 = new StringReader(""); assertFalse(IOUtils.contentEquals(null, input1)); } { final StringReader input1 = new StringReader(""); assertFalse(IOUtils.contentEquals(input1, null)); } { final StringReader input1 = new StringReader(""); assertTrue(IOUtils.contentEquals(input1, input1)); } { final StringReader input1 = new StringReader("ABC"); assertTrue(IOUtils.contentEquals(input1, input1)); } assertTrue(IOUtils.contentEquals(new StringReader(""), new StringReader(""))); assertTrue( IOUtils.contentEquals(new BufferedReader(new StringReader("")), new BufferedReader(new StringReader("")))); assertTrue(IOUtils.contentEquals(new StringReader("ABC"), new StringReader("ABC"))); assertFalse(IOUtils.contentEquals(new StringReader("ABCD"), new StringReader("ABC"))); assertFalse(IOUtils.contentEquals(new StringReader("ABC"), new StringReader("ABCD"))); } @Test public void testContentEqualsIgnoreEOL() throws Exception { { assertTrue(IOUtils.contentEqualsIgnoreEOL((Reader) null, null)); } { final Reader input1 = new CharArrayReader("".toCharArray()); assertFalse(IOUtils.contentEqualsIgnoreEOL(null, input1)); } { final Reader input1 = new CharArrayReader("".toCharArray()); assertFalse(IOUtils.contentEqualsIgnoreEOL(input1, null)); } { final Reader input1 = new CharArrayReader("".toCharArray()); assertTrue(IOUtils.contentEqualsIgnoreEOL(input1, input1)); } { final Reader input1 = new CharArrayReader("321\r\n".toCharArray()); assertTrue(IOUtils.contentEqualsIgnoreEOL(input1, input1)); } Reader r1; Reader r2; r1 = new CharArrayReader("".toCharArray()); r2 = new CharArrayReader("".toCharArray()); assertTrue(IOUtils.contentEqualsIgnoreEOL(r1, r2)); r1 = new CharArrayReader("1".toCharArray()); r2 = new CharArrayReader("1".toCharArray()); assertTrue(IOUtils.contentEqualsIgnoreEOL(r1, r2)); r1 = new CharArrayReader("1".toCharArray()); r2 = new CharArrayReader("2".toCharArray()); assertFalse(IOUtils.contentEqualsIgnoreEOL(r1, r2)); r1 = new CharArrayReader("123\rabc".toCharArray()); r2 = new CharArrayReader("123\nabc".toCharArray()); assertTrue(IOUtils.contentEqualsIgnoreEOL(r1, r2)); r1 = new CharArrayReader("321".toCharArray()); r2 = new CharArrayReader("321\r\n".toCharArray()); assertTrue(IOUtils.contentEqualsIgnoreEOL(r1, r2)); } @Test public void testCopy_ByteArray_OutputStream() throws Exception { final File destination = TestUtils.newFile(temporaryFolder, "copy8.txt"); byte[] in; try (InputStream fin = Files.newInputStream(testFilePath)) { // Create our byte[]. Rely on testInputStreamToByteArray() to make sure this is valid. in = IOUtils.toByteArray(fin); } try (OutputStream fout = Files.newOutputStream(destination.toPath())) { CopyUtils.copy(in, fout); fout.flush(); TestUtils.checkFile(destination, testFile); TestUtils.checkWrite(fout); } TestUtils.deleteFile(destination); } @Test public void testCopy_ByteArray_Writer() throws Exception { final File destination = TestUtils.newFile(temporaryFolder, "copy7.txt"); byte[] in; try (InputStream fin = Files.newInputStream(testFilePath)) { // Create our byte[]. Rely on testInputStreamToByteArray() to make sure this is valid. in = IOUtils.toByteArray(fin); } try (Writer fout = Files.newBufferedWriter(destination.toPath())) { CopyUtils.copy(in, fout); fout.flush(); TestUtils.checkFile(destination, testFile); TestUtils.checkWrite(fout); } TestUtils.deleteFile(destination); } @Test public void testCopy_String_Writer() throws Exception { final File destination = TestUtils.newFile(temporaryFolder, "copy6.txt"); String str; try (Reader fin = Files.newBufferedReader(testFilePath)) { // Create our String. Rely on testReaderToString() to make sure this is valid. str = IOUtils.toString(fin); } try (Writer fout = Files.newBufferedWriter(destination.toPath())) { CopyUtils.copy(str, fout); fout.flush(); TestUtils.checkFile(destination, testFile); TestUtils.checkWrite(fout); } TestUtils.deleteFile(destination); } @Test public void testCopyLarge_CharExtraLength() throws IOException { CharArrayReader is = null; CharArrayWriter os = null; try { // Create streams is = new CharArrayReader(carr); os = new CharArrayWriter(); // Test our copy method // for extra length, it reads till EOF assertEquals(200, IOUtils.copyLarge(is, os, 0, 2000)); final char[] oarr = os.toCharArray(); // check that output length is correct assertEquals(200, oarr.length); // check that output data corresponds to input data assertEquals(1, oarr[1]); assertEquals(79, oarr[79]); assertEquals((char) -1, oarr[80]); } finally { IOUtils.closeQuietly(is); IOUtils.closeQuietly(os); } } @Test public void testCopyLarge_CharFullLength() throws IOException { CharArrayReader is = null; CharArrayWriter os = null; try { // Create streams is = new CharArrayReader(carr); os = new CharArrayWriter(); // Test our copy method assertEquals(200, IOUtils.copyLarge(is, os, 0, -1)); final char[] oarr = os.toCharArray(); // check that output length is correct assertEquals(200, oarr.length); // check that output data corresponds to input data assertEquals(1, oarr[1]); assertEquals(79, oarr[79]); assertEquals((char) -1, oarr[80]); } finally { IOUtils.closeQuietly(is); IOUtils.closeQuietly(os); } } @Test public void testCopyLarge_CharNoSkip() throws IOException { CharArrayReader is = null; CharArrayWriter os = null; try { // Create streams is = new CharArrayReader(carr); os = new CharArrayWriter(); // Test our copy method assertEquals(100, IOUtils.copyLarge(is, os, 0, 100)); final char[] oarr = os.toCharArray(); // check that output length is correct assertEquals(100, oarr.length); // check that output data corresponds to input data assertEquals(1, oarr[1]); assertEquals(79, oarr[79]); assertEquals((char) -1, oarr[80]); } finally { IOUtils.closeQuietly(is); IOUtils.closeQuietly(os); } } @Test public void testCopyLarge_CharSkip() throws IOException { CharArrayReader is = null; CharArrayWriter os = null; try { // Create streams is = new CharArrayReader(carr); os = new CharArrayWriter(); // Test our copy method assertEquals(100, IOUtils.copyLarge(is, os, 10, 100)); final char[] oarr = os.toCharArray(); // check that output length is correct assertEquals(100, oarr.length); // check that output data corresponds to input data assertEquals(11, oarr[1]); assertEquals(79, oarr[69]); assertEquals((char) -1, oarr[70]); } finally { IOUtils.closeQuietly(is); IOUtils.closeQuietly(os); } } @Test public void testCopyLarge_CharSkipInvalid() { try (CharArrayReader is = new CharArrayReader(carr); CharArrayWriter os = new CharArrayWriter()) { assertThrows(EOFException.class, () -> IOUtils.copyLarge(is, os, 1000, 100)); } } @Test public void testCopyLarge_ExtraLength() throws IOException { try (ByteArrayInputStream is = new ByteArrayInputStream(iarr); ByteArrayOutputStream os = new ByteArrayOutputStream()) { // Create streams // Test our copy method // for extra length, it reads till EOF assertEquals(200, IOUtils.copyLarge(is, os, 0, 2000)); final byte[] oarr = os.toByteArray(); // check that output length is correct assertEquals(200, oarr.length); // check that output data corresponds to input data assertEquals(1, oarr[1]); assertEquals(79, oarr[79]); assertEquals(-1, oarr[80]); } } @Test public void testCopyLarge_FullLength() throws IOException { try (ByteArrayInputStream is = new ByteArrayInputStream(iarr); ByteArrayOutputStream os = new ByteArrayOutputStream()) { // Test our copy method assertEquals(200, IOUtils.copyLarge(is, os, 0, -1)); final byte[] oarr = os.toByteArray(); // check that output length is correct assertEquals(200, oarr.length); // check that output data corresponds to input data assertEquals(1, oarr[1]); assertEquals(79, oarr[79]); assertEquals(-1, oarr[80]); } } @Test public void testCopyLarge_NoSkip() throws IOException { try (ByteArrayInputStream is = new ByteArrayInputStream(iarr); ByteArrayOutputStream os = new ByteArrayOutputStream()) { // Test our copy method assertEquals(100, IOUtils.copyLarge(is, os, 0, 100)); final byte[] oarr = os.toByteArray(); // check that output length is correct assertEquals(100, oarr.length); // check that output data corresponds to input data assertEquals(1, oarr[1]); assertEquals(79, oarr[79]); assertEquals(-1, oarr[80]); } } @Test public void testCopyLarge_Skip() throws IOException { try (ByteArrayInputStream is = new ByteArrayInputStream(iarr); ByteArrayOutputStream os = new ByteArrayOutputStream()) { // Test our copy method assertEquals(100, IOUtils.copyLarge(is, os, 10, 100)); final byte[] oarr = os.toByteArray(); // check that output length is correct assertEquals(100, oarr.length); // check that output data corresponds to input data assertEquals(11, oarr[1]); assertEquals(79, oarr[69]); assertEquals(-1, oarr[70]); } } @Test public void testCopyLarge_SkipInvalid() throws IOException { try (ByteArrayInputStream is = new ByteArrayInputStream(iarr); ByteArrayOutputStream os = new ByteArrayOutputStream()) { // Test our copy method assertThrows(EOFException.class, () -> IOUtils.copyLarge(is, os, 1000, 100)); } } @Test public void testCopyLarge_SkipWithInvalidOffset() throws IOException { ByteArrayInputStream is = null; ByteArrayOutputStream os = null; try { // Create streams is = new ByteArrayInputStream(iarr); os = new ByteArrayOutputStream(); // Test our copy method assertEquals(100, IOUtils.copyLarge(is, os, -10, 100)); final byte[] oarr = os.toByteArray(); // check that output length is correct assertEquals(100, oarr.length); // check that output data corresponds to input data assertEquals(1, oarr[1]); assertEquals(79, oarr[79]); assertEquals(-1, oarr[80]); } finally { IOUtils.closeQuietly(is); IOUtils.closeQuietly(os); } } @Test public void testRead_ReadableByteChannel() throws Exception { final ByteBuffer buffer = ByteBuffer.allocate(FILE_SIZE); final FileInputStream fileInputStream = new FileInputStream(testFile); final FileChannel input = fileInputStream.getChannel(); try { assertEquals(FILE_SIZE, IOUtils.read(input, buffer)); assertEquals(0, IOUtils.read(input, buffer)); assertEquals(0, buffer.remaining()); assertEquals(0, input.read(buffer)); buffer.clear(); try { IOUtils.readFully(input, buffer); fail("Should have failed with EOFxception"); } catch (final EOFException expected) { // expected } } finally { IOUtils.closeQuietly(input, fileInputStream); } } @Test public void testReadFully_InputStream__ReturnByteArray() throws Exception { final byte[] bytes = "abcd1234".getBytes(StandardCharsets.UTF_8); final ByteArrayInputStream stream = new ByteArrayInputStream(bytes); final byte[] result = IOUtils.readFully(stream, bytes.length); IOUtils.closeQuietly(stream); assertEqualContent(result, bytes); } @Test public void testReadFully_InputStream_ByteArray() throws Exception { final int size = 1027; final byte[] buffer = new byte[size]; final InputStream input = new ByteArrayInputStream(new byte[size]); try { IOUtils.readFully(input, buffer, 0, -1); fail("Should have failed with IllegalArgumentException"); } catch (final IllegalArgumentException expected) { // expected } IOUtils.readFully(input, buffer, 0, 0); IOUtils.readFully(input, buffer, 0, size - 1); try { IOUtils.readFully(input, buffer, 0, 2); fail("Should have failed with EOFxception"); } catch (final EOFException expected) { // expected } IOUtils.closeQuietly(input); } @Test public void testReadFully_InputStream_Offset() throws Exception { final byte[] bytes = "abcd1234".getBytes(StandardCharsets.UTF_8); final ByteArrayInputStream stream = new ByteArrayInputStream(bytes); final byte[] buffer = "wx00000000".getBytes(StandardCharsets.UTF_8); IOUtils.readFully(stream, buffer, 2, 8); assertEquals("wxabcd1234", new String(buffer, 0, buffer.length, StandardCharsets.UTF_8)); IOUtils.closeQuietly(stream); } @Test public void testReadFully_ReadableByteChannel() throws Exception { final ByteBuffer buffer = ByteBuffer.allocate(FILE_SIZE); final FileInputStream fileInputStream = new FileInputStream(testFile); final FileChannel input = fileInputStream.getChannel(); try { IOUtils.readFully(input, buffer); assertEquals(FILE_SIZE, buffer.position()); assertEquals(0, buffer.remaining()); assertEquals(0, input.read(buffer)); IOUtils.readFully(input, buffer); assertEquals(FILE_SIZE, buffer.position()); assertEquals(0, buffer.remaining()); assertEquals(0, input.read(buffer)); IOUtils.readFully(input, buffer); buffer.clear(); try { IOUtils.readFully(input, buffer); fail("Should have failed with EOFxception"); } catch (final EOFException expected) { // expected } } finally { IOUtils.closeQuietly(input, fileInputStream); } } @Test public void testReadFully_Reader() throws Exception { final int size = 1027; final char[] buffer = new char[size]; final Reader input = new CharArrayReader(new char[size]); IOUtils.readFully(input, buffer, 0, 0); IOUtils.readFully(input, buffer, 0, size - 3); try { IOUtils.readFully(input, buffer, 0, -1); fail("Should have failed with IllegalArgumentException"); } catch (final IllegalArgumentException expected) { // expected } try { IOUtils.readFully(input, buffer, 0, 5); fail("Should have failed with EOFException"); } catch (final EOFException expected) { // expected } IOUtils.closeQuietly(input); } @Test public void testReadFully_Reader_Offset() throws Exception { final Reader reader = new StringReader("abcd1234"); final char[] buffer = "wx00000000".toCharArray(); IOUtils.readFully(reader, buffer, 2, 8); assertEquals("wxabcd1234", new String(buffer)); IOUtils.closeQuietly(reader); } @Test public void testReadLines_InputStream() throws Exception { final File file = TestUtils.newFile(temporaryFolder, "lines.txt"); InputStream in = null; try { final String[] data = {"hello", "world", "", "this is", "some text"}; TestUtils.createLineBasedFile(file, data); in = Files.newInputStream(file.toPath()); final List lines = IOUtils.readLines(in); assertEquals(Arrays.asList(data), lines); assertEquals(-1, in.read()); } finally { IOUtils.closeQuietly(in); TestUtils.deleteFile(file); } } @Test public void testReadLines_InputStream_String() throws Exception { final File file = TestUtils.newFile(temporaryFolder, "lines.txt"); InputStream in = null; try { final String[] data = {"hello", "/u1234", "", "this is", "some text"}; TestUtils.createLineBasedFile(file, data); in = Files.newInputStream(file.toPath()); final List lines = IOUtils.readLines(in, "UTF-8"); assertEquals(Arrays.asList(data), lines); assertEquals(-1, in.read()); } finally { IOUtils.closeQuietly(in); TestUtils.deleteFile(file); } } @Test public void testReadLines_Reader() throws Exception { final File file = TestUtils.newFile(temporaryFolder, "lines.txt"); Reader in = null; try { final String[] data = {"hello", "/u1234", "", "this is", "some text"}; TestUtils.createLineBasedFile(file, data); in = new InputStreamReader(Files.newInputStream(file.toPath())); final List lines = IOUtils.readLines(in); assertEquals(Arrays.asList(data), lines); assertEquals(-1, in.read()); } finally { IOUtils.closeQuietly(in); TestUtils.deleteFile(file); } } @Test public void testResourceToByteArray_ExistingResourceAtRootPackage() throws Exception { final long fileSize = TestResources.getFile("test-file-utf8.bin").length(); final byte[] bytes = IOUtils.resourceToByteArray("/org/apache/commons/io/test-file-utf8.bin"); assertNotNull(bytes); assertEquals(fileSize, bytes.length); } @Test public void testResourceToByteArray_ExistingResourceAtRootPackage_WithClassLoader() throws Exception { final long fileSize = TestResources.getFile("test-file-utf8.bin").length(); final byte[] bytes = IOUtils.resourceToByteArray("org/apache/commons/io/test-file-utf8.bin", ClassLoader.getSystemClassLoader()); assertNotNull(bytes); assertEquals(fileSize, bytes.length); } @Test public void testResourceToByteArray_ExistingResourceAtSubPackage() throws Exception { final long fileSize = TestResources.getFile("FileUtilsTestDataCR.dat").length(); final byte[] bytes = IOUtils.resourceToByteArray("/org/apache/commons/io/FileUtilsTestDataCR.dat"); assertNotNull(bytes); assertEquals(fileSize, bytes.length); } @Test public void testResourceToByteArray_ExistingResourceAtSubPackage_WithClassLoader() throws Exception { final long fileSize = TestResources.getFile("FileUtilsTestDataCR.dat").length(); final byte[] bytes = IOUtils.resourceToByteArray("org/apache/commons/io/FileUtilsTestDataCR.dat", ClassLoader.getSystemClassLoader()); assertNotNull(bytes); assertEquals(fileSize, bytes.length); } @Test public void testResourceToByteArray_NonExistingResource() { assertThrows(IOException.class, () -> IOUtils.resourceToByteArray("/non-existing-file.bin")); } @Test public void testResourceToByteArray_NonExistingResource_WithClassLoader() { assertThrows(IOException.class, () -> IOUtils.resourceToByteArray("non-existing-file.bin", ClassLoader.getSystemClassLoader())); } @Test public void testResourceToByteArray_Null() { assertThrows(NullPointerException.class, () -> IOUtils.resourceToByteArray(null)); } @Test public void testResourceToByteArray_Null_WithClassLoader() { assertThrows(NullPointerException.class, () -> IOUtils.resourceToByteArray(null, ClassLoader.getSystemClassLoader())); } @Test public void testResourceToString_ExistingResourceAtRootPackage() throws Exception { final long fileSize = TestResources.getFile("test-file-simple-utf8.bin").length(); final String content = IOUtils.resourceToString("/org/apache/commons/io/test-file-simple-utf8.bin", StandardCharsets.UTF_8); assertNotNull(content); assertEquals(fileSize, content.getBytes().length); } @Test public void testResourceToString_ExistingResourceAtRootPackage_WithClassLoader() throws Exception { final long fileSize = TestResources.getFile("test-file-simple-utf8.bin").length(); final String content = IOUtils.resourceToString("org/apache/commons/io/test-file-simple-utf8.bin", StandardCharsets.UTF_8, ClassLoader.getSystemClassLoader()); assertNotNull(content); assertEquals(fileSize, content.getBytes().length); } @Test public void testResourceToString_ExistingResourceAtSubPackage() throws Exception { final long fileSize = TestResources.getFile("FileUtilsTestDataCR.dat").length(); final String content = IOUtils.resourceToString("/org/apache/commons/io/FileUtilsTestDataCR.dat", StandardCharsets.UTF_8); assertNotNull(content); assertEquals(fileSize, content.getBytes().length); } // Tests from IO-305 @Test public void testResourceToString_ExistingResourceAtSubPackage_WithClassLoader() throws Exception { final long fileSize = TestResources.getFile("FileUtilsTestDataCR.dat").length(); final String content = IOUtils.resourceToString("org/apache/commons/io/FileUtilsTestDataCR.dat", StandardCharsets.UTF_8, ClassLoader.getSystemClassLoader()); assertNotNull(content); assertEquals(fileSize, content.getBytes().length); } @Test public void testResourceToString_NonExistingResource() { assertThrows(IOException.class, () -> IOUtils.resourceToString("/non-existing-file.bin", StandardCharsets.UTF_8)); } @Test public void testResourceToString_NonExistingResource_WithClassLoader() { assertThrows(IOException.class, () -> IOUtils.resourceToString("non-existing-file.bin", StandardCharsets.UTF_8, ClassLoader.getSystemClassLoader())); } @SuppressWarnings("squid:S2699") // Suppress "Add at least one assertion to this test case" @Test public void testResourceToString_NullCharset() throws Exception { IOUtils.resourceToString("/org/apache/commons/io//test-file-utf8.bin", null); } @SuppressWarnings("squid:S2699") // Suppress "Add at least one assertion to this test case" @Test public void testResourceToString_NullCharset_WithClassLoader() throws Exception { IOUtils.resourceToString("org/apache/commons/io/test-file-utf8.bin", null, ClassLoader.getSystemClassLoader()); } @Test public void testResourceToString_NullResource() { assertThrows(NullPointerException.class, () -> IOUtils.resourceToString(null, StandardCharsets.UTF_8)); } @Test public void testResourceToString_NullResource_WithClassLoader() { assertThrows(NullPointerException.class, () -> IOUtils.resourceToString(null, StandardCharsets.UTF_8, ClassLoader.getSystemClassLoader())); } @Test public void testResourceToURL_ExistingResourceAtRootPackage() throws Exception { final URL url = IOUtils.resourceToURL("/org/apache/commons/io/test-file-utf8.bin"); assertNotNull(url); assertTrue(url.getFile().endsWith("/test-file-utf8.bin")); } @Test public void testResourceToURL_ExistingResourceAtRootPackage_WithClassLoader() throws Exception { final URL url = IOUtils.resourceToURL("org/apache/commons/io/test-file-utf8.bin", ClassLoader.getSystemClassLoader()); assertNotNull(url); assertTrue(url.getFile().endsWith("/org/apache/commons/io/test-file-utf8.bin")); } @Test public void testResourceToURL_ExistingResourceAtSubPackage() throws Exception { final URL url = IOUtils.resourceToURL("/org/apache/commons/io/FileUtilsTestDataCR.dat"); assertNotNull(url); assertTrue(url.getFile().endsWith("/org/apache/commons/io/FileUtilsTestDataCR.dat")); } @Test public void testResourceToURL_ExistingResourceAtSubPackage_WithClassLoader() throws Exception { final URL url = IOUtils.resourceToURL("org/apache/commons/io/FileUtilsTestDataCR.dat", ClassLoader.getSystemClassLoader()); assertNotNull(url); assertTrue(url.getFile().endsWith("/org/apache/commons/io/FileUtilsTestDataCR.dat")); } @Test public void testResourceToURL_NonExistingResource() { assertThrows(IOException.class, () -> IOUtils.resourceToURL("/non-existing-file.bin")); } @Test public void testResourceToURL_NonExistingResource_WithClassLoader() { assertThrows(IOException.class, () -> IOUtils.resourceToURL("non-existing-file.bin", ClassLoader.getSystemClassLoader())); } @Test public void testResourceToURL_Null() { assertThrows(NullPointerException.class, () -> IOUtils.resourceToURL(null)); } @Test public void testResourceToURL_Null_WithClassLoader() { assertThrows(NullPointerException.class, () -> IOUtils.resourceToURL(null, ClassLoader.getSystemClassLoader())); } @Test public void testSkip_FileReader() throws Exception { try (Reader in = Files.newBufferedReader(testFilePath)) { assertEquals(FILE_SIZE - 10, IOUtils.skip(in, FILE_SIZE - 10)); assertEquals(10, IOUtils.skip(in, 20)); assertEquals(0, IOUtils.skip(in, 10)); } } @Test public void testSkip_InputStream() throws Exception { try (InputStream in = Files.newInputStream(testFilePath)) { assertEquals(FILE_SIZE - 10, IOUtils.skip(in, FILE_SIZE - 10)); assertEquals(10, IOUtils.skip(in, 20)); assertEquals(0, IOUtils.skip(in, 10)); } } @Test public void testSkip_ReadableByteChannel() throws Exception { final FileInputStream fileInputStream = new FileInputStream(testFile); final FileChannel fileChannel = fileInputStream.getChannel(); try { assertEquals(FILE_SIZE - 10, IOUtils.skip(fileChannel, FILE_SIZE - 10)); assertEquals(10, IOUtils.skip(fileChannel, 20)); assertEquals(0, IOUtils.skip(fileChannel, 10)); } finally { IOUtils.closeQuietly(fileChannel, fileInputStream); } } @Test public void testSkipFully_InputStream() throws Exception { final int size = 1027; final InputStream input = new ByteArrayInputStream(new byte[size]); try { IOUtils.skipFully(input, -1); fail("Should have failed with IllegalArgumentException"); } catch (final IllegalArgumentException expected) { // expected } IOUtils.skipFully(input, 0); IOUtils.skipFully(input, size - 1); try { IOUtils.skipFully(input, 2); fail("Should have failed with IOException"); } catch (final IOException expected) { // expected } IOUtils.closeQuietly(input); } @Test public void testSkipFully_ReadableByteChannel() throws Exception { final FileInputStream fileInputStream = new FileInputStream(testFile); final FileChannel fileChannel = fileInputStream.getChannel(); try { try { IOUtils.skipFully(fileChannel, -1); fail("Should have failed with IllegalArgumentException"); } catch (final IllegalArgumentException expected) { // expected } IOUtils.skipFully(fileChannel, 0); IOUtils.skipFully(fileChannel, FILE_SIZE - 1); try { IOUtils.skipFully(fileChannel, 2); fail("Should have failed with IOException"); } catch (final IOException expected) { // expected } } finally { IOUtils.closeQuietly(fileChannel, fileInputStream); } } @Test public void testSkipFully_Reader() throws Exception { final int size = 1027; final Reader input = new CharArrayReader(new char[size]); IOUtils.skipFully(input, 0); IOUtils.skipFully(input, size - 3); try { IOUtils.skipFully(input, -1); fail("Should have failed with IllegalArgumentException"); } catch (final IllegalArgumentException expected) { // expected } try { IOUtils.skipFully(input, 5); fail("Should have failed with IOException"); } catch (final IOException expected) { // expected } IOUtils.closeQuietly(input); } @Test public void testStringToOutputStream() throws Exception { final File destination = TestUtils.newFile(temporaryFolder, "copy5.txt"); String str; try (Reader fin = Files.newBufferedReader(testFilePath)) { // Create our String. Rely on testReaderToString() to make sure this is valid. str = IOUtils.toString(fin); } try (OutputStream fout = Files.newOutputStream(destination.toPath())) { CopyUtils.copy(str, fout); // Note: this method *does* flush. It is equivalent to: // OutputStreamWriter _out = new OutputStreamWriter(fout); // CopyUtils.copy( str, _out, 4096 ); // copy( Reader, Writer, int ); // _out.flush(); // out = fout; // note: we don't flush here; this IOUtils method does it for us TestUtils.checkFile(destination, testFile); TestUtils.checkWrite(fout); } TestUtils.deleteFile(destination); } @Test public void testToBufferedInputStream_InputStream() throws Exception { try (InputStream fin = Files.newInputStream(testFilePath)) { final InputStream in = IOUtils.toBufferedInputStream(fin); final byte[] out = IOUtils.toByteArray(in); assertNotNull(out); assertEquals(0, fin.available(), "Not all bytes were read"); assertEquals(FILE_SIZE, out.length, "Wrong output size"); TestUtils.assertEqualContent(out, testFile); } } @Test public void testToBufferedInputStreamWithBufferSize_InputStream() throws Exception { try (InputStream fin = Files.newInputStream(testFilePath)) { final InputStream in = IOUtils.toBufferedInputStream(fin, 2048); final byte[] out = IOUtils.toByteArray(in); assertNotNull(out); assertEquals(0, fin.available(), "Not all bytes were read"); assertEquals(FILE_SIZE, out.length, "Wrong output size"); TestUtils.assertEqualContent(out, testFile); } } @Test public void testToByteArray_InputStream() throws Exception { try (InputStream fin = Files.newInputStream(testFilePath)) { final byte[] out = IOUtils.toByteArray(fin); assertNotNull(out); assertEquals(0, fin.available(), "Not all bytes were read"); assertEquals(FILE_SIZE, out.length, "Wrong output size"); TestUtils.assertEqualContent(out, testFile); } } @Test @Disabled("Disable by default as it uses too much memory and can cause builds to fail.") public void testToByteArray_InputStream_LongerThanIntegerMaxValue() throws Exception { final CircularInputStream cin = new CircularInputStream(IOUtils.byteArray(), Integer.MAX_VALUE + 1L); assertThrows(IllegalArgumentException.class, () -> IOUtils.toByteArray(cin)); } @Test public void testToByteArray_InputStream_NegativeSize() throws Exception { try (InputStream fin = Files.newInputStream(testFilePath)) { IOUtils.toByteArray(fin, -1); fail("IllegalArgumentException expected"); } catch (final IllegalArgumentException exc) { assertTrue(exc.getMessage().startsWith("Size must be equal or greater than zero"), "Exception message does not start with \"Size must be equal or greater than zero\""); } } @Test public void testToByteArray_InputStream_Size() throws Exception { try (InputStream fin = Files.newInputStream(testFilePath)) { final byte[] out = IOUtils.toByteArray(fin, testFile.length()); assertNotNull(out); assertEquals(0, fin.available(), "Not all bytes were read"); assertEquals(FILE_SIZE, out.length, "Wrong output size: out.length=" + out.length + "!=" + FILE_SIZE); TestUtils.assertEqualContent(out, testFile); } } @Test public void testToByteArray_InputStream_SizeIllegal() throws Exception { try (InputStream fin = Files.newInputStream(testFilePath)) { IOUtils.toByteArray(fin, testFile.length() + 1); fail("IOException expected"); } catch (final IOException exc) { assertTrue(exc.getMessage().startsWith("Unexpected read size"), "Exception message does not start with \"Unexpected read size\""); } } @Test public void testToByteArray_InputStream_SizeLong() throws Exception { try (InputStream fin = Files.newInputStream(testFilePath)) { IOUtils.toByteArray(fin, (long) Integer.MAX_VALUE + 1); fail("IOException expected"); } catch (final IllegalArgumentException exc) { assertTrue(exc.getMessage().startsWith("Size cannot be greater than Integer max value"), "Exception message does not start with \"Size cannot be greater than Integer max value\""); } } @Test public void testToByteArray_InputStream_SizeZero() throws Exception { try (InputStream fin =Files.newInputStream(testFilePath)) { final byte[] out = IOUtils.toByteArray(fin, 0); assertNotNull(out, "Out cannot be null"); assertEquals(0, out.length, "Out length must be 0"); } } @Test public void testToByteArray_InputStream_SizeOne() throws Exception { try (InputStream fin = Files.newInputStream(testFilePath)) { final byte[] out = IOUtils.toByteArray(fin, 1); assertNotNull(out, "Out cannot be null"); assertEquals(1, out.length, "Out length must be 1"); } } @Test public void testToByteArray_Reader() throws IOException { final String charsetName = "UTF-8"; final byte[] expecteds = charsetName.getBytes(charsetName); byte[] actuals = IOUtils.toByteArray(new InputStreamReader(new ByteArrayInputStream(expecteds))); assertArrayEquals(expecteds, actuals); actuals = IOUtils.toByteArray(new InputStreamReader(new ByteArrayInputStream(expecteds)), charsetName); assertArrayEquals(expecteds, actuals); } @Test public void testToByteArray_String() throws Exception { try (Reader fin = Files.newBufferedReader(testFilePath)) { // Create our String. Rely on testReaderToString() to make sure this is valid. final String str = IOUtils.toString(fin); final byte[] out = IOUtils.toByteArray(str); assertEqualContent(str.getBytes(), out); } } @Test public void testToByteArray_URI() throws Exception { final URI url = testFile.toURI(); final byte[] actual = IOUtils.toByteArray(url); assertEquals(FILE_SIZE, actual.length); } @Test public void testToByteArray_URL() throws Exception { final URL url = testFile.toURI().toURL(); final byte[] actual = IOUtils.toByteArray(url); assertEquals(FILE_SIZE, actual.length); } @Test public void testToByteArray_URLConnection() throws Exception { final URLConnection urlConn = testFile.toURI().toURL().openConnection(); byte[] actual; try { actual = IOUtils.toByteArray(urlConn); } finally { IOUtils.close(urlConn); } assertEquals(FILE_SIZE, actual.length); } @Test public void testToCharArray_InputStream() throws Exception { try (InputStream fin = Files.newInputStream(testFilePath)) { final char[] out = IOUtils.toCharArray(fin); assertNotNull(out); assertEquals(0, fin.available(), "Not all chars were read"); assertEquals(FILE_SIZE, out.length, "Wrong output size"); TestUtils.assertEqualContent(out, testFile); } } @Test public void testToCharArray_InputStream_CharsetName() throws Exception { try (InputStream fin = Files.newInputStream(testFilePath)) { final char[] out = IOUtils.toCharArray(fin, "UTF-8"); assertNotNull(out); assertEquals(0, fin.available(), "Not all chars were read"); assertEquals(FILE_SIZE, out.length, "Wrong output size"); TestUtils.assertEqualContent(out, testFile); } } @Test public void testToCharArray_Reader() throws Exception { try (Reader fr = Files.newBufferedReader(testFilePath)) { final char[] out = IOUtils.toCharArray(fr); assertNotNull(out); assertEquals(FILE_SIZE, out.length, "Wrong output size"); TestUtils.assertEqualContent(out, testFile); } } /** * Test for {@link IOUtils#toInputStream(CharSequence)} and {@link IOUtils#toInputStream(CharSequence, String)}. * Note, this test utilizes on {@link IOUtils#toByteArray(java.io.InputStream)} and so relies on * {@link #testToByteArray_InputStream()} to ensure this method functions correctly. * * @throws Exception on error */ @Test public void testToInputStream_CharSequence() throws Exception { final CharSequence csq = new StringBuilder("Abc123Xyz!"); InputStream inStream = IOUtils.toInputStream(csq); // deliberately testing deprecated method byte[] bytes = IOUtils.toByteArray(inStream); assertEqualContent(csq.toString().getBytes(), bytes); inStream = IOUtils.toInputStream(csq, (String) null); bytes = IOUtils.toByteArray(inStream); assertEqualContent(csq.toString().getBytes(), bytes); inStream = IOUtils.toInputStream(csq, "UTF-8"); bytes = IOUtils.toByteArray(inStream); assertEqualContent(csq.toString().getBytes(StandardCharsets.UTF_8), bytes); } /** * Test for {@link IOUtils#toInputStream(String)} and {@link IOUtils#toInputStream(String, String)}. Note, this test * utilizes on {@link IOUtils#toByteArray(java.io.InputStream)} and so relies on * {@link #testToByteArray_InputStream()} to ensure this method functions correctly. * * @throws Exception on error */ @Test public void testToInputStream_String() throws Exception { final String str = "Abc123Xyz!"; InputStream inStream = IOUtils.toInputStream(str); byte[] bytes = IOUtils.toByteArray(inStream); assertEqualContent(str.getBytes(), bytes); inStream = IOUtils.toInputStream(str, (String) null); bytes = IOUtils.toByteArray(inStream); assertEqualContent(str.getBytes(), bytes); inStream = IOUtils.toInputStream(str, "UTF-8"); bytes = IOUtils.toByteArray(inStream); assertEqualContent(str.getBytes(StandardCharsets.UTF_8), bytes); } @Test public void testToString_ByteArray() throws Exception { try (InputStream fin = Files.newInputStream(testFilePath)) { final byte[] in = IOUtils.toByteArray(fin); // Create our byte[]. Rely on testInputStreamToByteArray() to make sure this is valid. final String str = IOUtils.toString(in); assertEqualContent(in, str.getBytes()); } } @Test public void testToString_InputStream() throws Exception { try (InputStream fin = Files.newInputStream(testFilePath)) { final String out = IOUtils.toString(fin); assertNotNull(out); assertEquals(0, fin.available(), "Not all bytes were read"); assertEquals(FILE_SIZE, out.length(), "Wrong output size"); } } @Test public void testToString_Reader() throws Exception { try (Reader fin = Files.newBufferedReader(testFilePath)) { final String out = IOUtils.toString(fin); assertNotNull(out); assertEquals(FILE_SIZE, out.length(), "Wrong output size"); } } @Test public void testToString_URI() throws Exception { final URI url = testFile.toURI(); final String out = IOUtils.toString(url); assertNotNull(out); assertEquals(FILE_SIZE, out.length(), "Wrong output size"); } private void testToString_URI(final String encoding) throws Exception { final URI uri = testFile.toURI(); final String out = IOUtils.toString(uri, encoding); assertNotNull(out); assertEquals(FILE_SIZE, out.length(), "Wrong output size"); } @Test public void testToString_URI_CharsetName() throws Exception { testToString_URI("US-ASCII"); } @Test public void testToString_URI_CharsetNameNull() throws Exception { testToString_URI(null); } @Test public void testToString_URL() throws Exception { final URL url = testFile.toURI().toURL(); final String out = IOUtils.toString(url); assertNotNull(out); assertEquals(FILE_SIZE, out.length(), "Wrong output size"); } private void testToString_URL(final String encoding) throws Exception { final URL url = testFile.toURI().toURL(); final String out = IOUtils.toString(url, encoding); assertNotNull(out); assertEquals(FILE_SIZE, out.length(), "Wrong output size"); } @Test public void testToString_URL_CharsetName() throws Exception { testToString_URL("US-ASCII"); } @Test public void testToString_URL_CharsetNameNull() throws Exception { testToString_URL(null); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/IOUtilsWriteTestCase.java0100644 0000000 0000000 00000071056 13612062727 030441 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Writer; import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.List; import org.apache.commons.io.output.ByteArrayOutputStream; import org.apache.commons.io.test.TestUtils; import org.apache.commons.io.test.ThrowOnFlushAndCloseOutputStream; import org.junit.jupiter.api.Test; /** * JUnit tests for IOUtils write methods. * * @see IOUtils */ @SuppressWarnings("deprecation") // includes tests for deprecated methods public class IOUtilsWriteTestCase { private static final int FILE_SIZE = 1024 * 4 + 1; private final byte[] inData = TestUtils.generateTestData(FILE_SIZE); @Test public void testWrite_byteArrayToOutputStream() throws Exception { final ByteArrayOutputStream baout = new ByteArrayOutputStream(); final ThrowOnFlushAndCloseOutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, true, true); IOUtils.write(inData, out); out.off(); out.flush(); assertEquals(inData.length, baout.size(), "Sizes differ"); assertArrayEquals(inData, baout.toByteArray(), "Content differs"); } @Test public void testWrite_byteArrayToOutputStream_nullData() throws Exception { final ByteArrayOutputStream baout = new ByteArrayOutputStream(); final ThrowOnFlushAndCloseOutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, true, true); IOUtils.write((byte[]) null, out); out.off(); out.flush(); assertEquals(0, baout.size(), "Sizes differ"); } @Test public void testWrite_byteArrayToOutputStream_nullStream() throws Exception { try { IOUtils.write(inData, (OutputStream) null); fail(); } catch (final NullPointerException ignore) { } } @Test public void testWrite_byteArrayToWriter() throws Exception { final ByteArrayOutputStream baout = new ByteArrayOutputStream(); @SuppressWarnings("resource") // deliberately not closed final ThrowOnFlushAndCloseOutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, true, true); final Writer writer = new OutputStreamWriter(baout, StandardCharsets.US_ASCII); IOUtils.write(inData, writer); out.off(); writer.flush(); assertEquals(inData.length, baout.size(), "Sizes differ"); assertArrayEquals(inData, baout.toByteArray(), "Content differs"); } @Test public void testWrite_byteArrayToWriter_nullData() throws Exception { final ByteArrayOutputStream baout = new ByteArrayOutputStream(); @SuppressWarnings("resource") // deliberately not closed final ThrowOnFlushAndCloseOutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, true, true); final Writer writer = new OutputStreamWriter(baout, StandardCharsets.US_ASCII); IOUtils.write((byte[]) null, writer); out.off(); writer.flush(); assertEquals(0, baout.size(), "Sizes differ"); } @Test public void testWrite_byteArrayToWriter_nullWriter() throws Exception { try { IOUtils.write(inData, (Writer) null); fail(); } catch (final NullPointerException ignore) { } } @Test public void testWrite_byteArrayToWriter_Encoding() throws Exception { final ByteArrayOutputStream baout = new ByteArrayOutputStream(); @SuppressWarnings("resource") // deliberately not closed final ThrowOnFlushAndCloseOutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, true, true); final Writer writer = new OutputStreamWriter(baout, StandardCharsets.US_ASCII); IOUtils.write(inData, writer, "UTF8"); out.off(); writer.flush(); byte[] bytes = baout.toByteArray(); bytes = new String(bytes, StandardCharsets.UTF_8).getBytes(StandardCharsets.US_ASCII); assertArrayEquals(inData, bytes, "Content differs"); } @Test public void testWrite_byteArrayToWriter_Encoding_nullData() throws Exception { final ByteArrayOutputStream baout = new ByteArrayOutputStream(); @SuppressWarnings("resource") // deliberately not closed final ThrowOnFlushAndCloseOutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, true, true); final Writer writer = new OutputStreamWriter(baout, StandardCharsets.US_ASCII); IOUtils.write(null, writer, "UTF8"); out.off(); writer.flush(); assertEquals(0, baout.size(), "Sizes differ"); } @Test public void testWrite_byteArrayToWriter_Encoding_nullWriter() throws Exception { try { IOUtils.write(inData, null, "UTF8"); fail(); } catch (final NullPointerException ignore) { } } @Test public void testWrite_byteArrayToWriter_Encoding_nullEncoding() throws Exception { final ByteArrayOutputStream baout = new ByteArrayOutputStream(); @SuppressWarnings("resource") // deliberately not closed final ThrowOnFlushAndCloseOutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, true, true); final Writer writer = new OutputStreamWriter(baout, StandardCharsets.US_ASCII); IOUtils.write(inData, writer, (String) null); out.off(); writer.flush(); assertEquals(inData.length, baout.size(), "Sizes differ"); assertArrayEquals(inData, baout.toByteArray(), "Content differs"); } @Test public void testWrite_charSequenceToOutputStream() throws Exception { final CharSequence csq = new StringBuilder(new String(inData, StandardCharsets.US_ASCII)); final ByteArrayOutputStream baout = new ByteArrayOutputStream(); final ThrowOnFlushAndCloseOutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, true, true); IOUtils.write(csq, out); out.off(); out.flush(); assertEquals(inData.length, baout.size(), "Sizes differ"); assertArrayEquals(inData, baout.toByteArray(), "Content differs"); } @Test public void testWrite_charSequenceToOutputStream_nullData() throws Exception { final ByteArrayOutputStream baout = new ByteArrayOutputStream(); final ThrowOnFlushAndCloseOutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, true, true); IOUtils.write((CharSequence) null, out); out.off(); out.flush(); assertEquals(0, baout.size(), "Sizes differ"); } @Test public void testWrite_charSequenceToOutputStream_nullStream() throws Exception { final CharSequence csq = new StringBuilder(new String(inData, StandardCharsets.US_ASCII)); try { IOUtils.write(csq, (OutputStream) null); fail(); } catch (final NullPointerException ignore) { } } @Test public void testWrite_charSequenceToOutputStream_Encoding() throws Exception { final CharSequence csq = new StringBuilder(new String(inData, StandardCharsets.US_ASCII)); final ByteArrayOutputStream baout = new ByteArrayOutputStream(); final ThrowOnFlushAndCloseOutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, true, true); IOUtils.write(csq, out, "UTF16"); out.off(); out.flush(); byte[] bytes = baout.toByteArray(); bytes = new String(bytes, StandardCharsets.UTF_16).getBytes(StandardCharsets.US_ASCII); assertArrayEquals(inData, bytes, "Content differs"); } @Test public void testWrite_charSequenceToOutputStream_Encoding_nullData() throws Exception { final ByteArrayOutputStream baout = new ByteArrayOutputStream(); final ThrowOnFlushAndCloseOutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, true, true); IOUtils.write((CharSequence) null, out); out.off(); out.flush(); assertEquals(0, baout.size(), "Sizes differ"); } @Test public void testWrite_charSequenceToOutputStream_Encoding_nullStream() throws Exception { final CharSequence csq = new StringBuilder(new String(inData, StandardCharsets.US_ASCII)); try { IOUtils.write(csq, (OutputStream) null); fail(); } catch (final NullPointerException ignore) { } } @Test public void testWrite_charSequenceToOutputStream_nullEncoding() throws Exception { final CharSequence csq = new StringBuilder(new String(inData, StandardCharsets.US_ASCII)); final ByteArrayOutputStream baout = new ByteArrayOutputStream(); final ThrowOnFlushAndCloseOutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, true, true); IOUtils.write(csq, out, (String) null); out.off(); out.flush(); assertEquals(inData.length, baout.size(), "Sizes differ"); assertArrayEquals(inData, baout.toByteArray(), "Content differs"); } @Test public void testWrite_charSequenceToWriter() throws Exception { final CharSequence csq = new StringBuilder(new String(inData, StandardCharsets.US_ASCII)); final ByteArrayOutputStream baout = new ByteArrayOutputStream(); @SuppressWarnings("resource") // deliberately not closed final ThrowOnFlushAndCloseOutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, true, true); final Writer writer = new OutputStreamWriter(baout, StandardCharsets.US_ASCII); IOUtils.write(csq, writer); out.off(); writer.flush(); assertEquals(inData.length, baout.size(), "Sizes differ"); assertArrayEquals(inData, baout.toByteArray(), "Content differs"); } @Test public void testWrite_charSequenceToWriter_Encoding_nullData() throws Exception { final ByteArrayOutputStream baout = new ByteArrayOutputStream(); @SuppressWarnings("resource") // deliberately not closed final ThrowOnFlushAndCloseOutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, true, true); final Writer writer = new OutputStreamWriter(baout, StandardCharsets.US_ASCII); IOUtils.write((CharSequence) null, writer); out.off(); writer.flush(); assertEquals(0, baout.size(), "Sizes differ"); } @Test public void testWrite_charSequenceToWriter_Encoding_nullStream() throws Exception { final CharSequence csq = new StringBuilder(new String(inData, StandardCharsets.US_ASCII)); try { IOUtils.write(csq, (Writer) null); fail(); } catch (final NullPointerException ignore) { } } @Test public void testWrite_stringToOutputStream() throws Exception { final String str = new String(inData, StandardCharsets.US_ASCII); final ByteArrayOutputStream baout = new ByteArrayOutputStream(); final ThrowOnFlushAndCloseOutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, true, true); IOUtils.write(str, out); out.off(); out.flush(); assertEquals(inData.length, baout.size(), "Sizes differ"); assertArrayEquals(inData, baout.toByteArray(), "Content differs"); } @Test public void testWrite_stringToOutputStream_nullData() throws Exception { final ByteArrayOutputStream baout = new ByteArrayOutputStream(); final ThrowOnFlushAndCloseOutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, true, true); IOUtils.write((String) null, out); out.off(); out.flush(); assertEquals(0, baout.size(), "Sizes differ"); } @Test public void testWrite_stringToOutputStream_nullStream() throws Exception { final String str = new String(inData, StandardCharsets.US_ASCII); try { IOUtils.write(str, (OutputStream) null); fail(); } catch (final NullPointerException ignore) { } } @Test public void testWrite_stringToOutputStream_Encoding() throws Exception { final String str = new String(inData, StandardCharsets.US_ASCII); final ByteArrayOutputStream baout = new ByteArrayOutputStream(); final ThrowOnFlushAndCloseOutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, true, true); IOUtils.write(str, out, "UTF16"); out.off(); out.flush(); byte[] bytes = baout.toByteArray(); bytes = new String(bytes, StandardCharsets.UTF_16).getBytes(StandardCharsets.US_ASCII); assertArrayEquals(inData, bytes, "Content differs"); } @Test public void testWrite_stringToOutputStream_Encoding_nullData() throws Exception { final ByteArrayOutputStream baout = new ByteArrayOutputStream(); final ThrowOnFlushAndCloseOutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, true, true); IOUtils.write((String) null, out); out.off(); out.flush(); assertEquals(0, baout.size(), "Sizes differ"); } @Test public void testWrite_stringToOutputStream_Encoding_nullStream() throws Exception { final String str = new String(inData, StandardCharsets.US_ASCII); try { IOUtils.write(str, (OutputStream) null); fail(); } catch (final NullPointerException ignore) { } } @Test public void testWrite_stringToOutputStream_nullEncoding() throws Exception { final String str = new String(inData, StandardCharsets.US_ASCII); final ByteArrayOutputStream baout = new ByteArrayOutputStream(); final ThrowOnFlushAndCloseOutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, true, true); IOUtils.write(str, out, (String) null); out.off(); out.flush(); assertEquals(inData.length, baout.size(), "Sizes differ"); assertArrayEquals(inData, baout.toByteArray(), "Content differs"); } @Test public void testWrite_stringToWriter() throws Exception { final String str = new String(inData, StandardCharsets.US_ASCII); final ByteArrayOutputStream baout = new ByteArrayOutputStream(); @SuppressWarnings("resource") // deliberately not closed final ThrowOnFlushAndCloseOutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, true, true); final Writer writer = new OutputStreamWriter(baout, StandardCharsets.US_ASCII); IOUtils.write(str, writer); out.off(); writer.flush(); assertEquals(inData.length, baout.size(), "Sizes differ"); assertArrayEquals(inData, baout.toByteArray(), "Content differs"); } @Test public void testWrite_stringToWriter_Encoding_nullData() throws Exception { final ByteArrayOutputStream baout = new ByteArrayOutputStream(); @SuppressWarnings("resource") // deliberately not closed final ThrowOnFlushAndCloseOutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, true, true); final Writer writer = new OutputStreamWriter(baout, StandardCharsets.US_ASCII); IOUtils.write((String) null, writer); out.off(); writer.flush(); assertEquals(0, baout.size(), "Sizes differ"); } @Test public void testWrite_stringToWriter_Encoding_nullStream() throws Exception { final String str = new String(inData, StandardCharsets.US_ASCII); try { IOUtils.write(str, (Writer) null); fail(); } catch (final NullPointerException ignore) { } } @Test public void testWrite_charArrayToOutputStream() throws Exception { final String str = new String(inData, StandardCharsets.US_ASCII); final ByteArrayOutputStream baout = new ByteArrayOutputStream(); final ThrowOnFlushAndCloseOutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, true, true); IOUtils.write(str.toCharArray(), out); out.off(); out.flush(); assertEquals(inData.length, baout.size(), "Sizes differ"); assertArrayEquals(inData, baout.toByteArray(), "Content differs"); } @Test public void testWrite_charArrayToOutputStream_nullData() throws Exception { final ByteArrayOutputStream baout = new ByteArrayOutputStream(); final ThrowOnFlushAndCloseOutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, true, true); IOUtils.write((char[]) null, out); out.off(); out.flush(); assertEquals(0, baout.size(), "Sizes differ"); } @Test public void testWrite_charArrayToOutputStream_nullStream() throws Exception { final String str = new String(inData, StandardCharsets.US_ASCII); try { IOUtils.write(str.toCharArray(), (OutputStream) null); fail(); } catch (final NullPointerException ignore) { } } @Test public void testWrite_charArrayToOutputStream_Encoding() throws Exception { final String str = new String(inData, StandardCharsets.US_ASCII); final ByteArrayOutputStream baout = new ByteArrayOutputStream(); final ThrowOnFlushAndCloseOutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, true, true); IOUtils.write(str.toCharArray(), out, "UTF16"); out.off(); out.flush(); byte[] bytes = baout.toByteArray(); bytes = new String(bytes, StandardCharsets.UTF_16).getBytes(StandardCharsets.US_ASCII); assertArrayEquals(inData, bytes, "Content differs"); } @Test public void testWrite_charArrayToOutputStream_Encoding_nullData() throws Exception { final ByteArrayOutputStream baout = new ByteArrayOutputStream(); final ThrowOnFlushAndCloseOutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, true, true); IOUtils.write((char[]) null, out); out.off(); out.flush(); assertEquals(0, baout.size(), "Sizes differ"); } @Test public void testWrite_charArrayToOutputStream_Encoding_nullStream() throws Exception { final String str = new String(inData, StandardCharsets.US_ASCII); try { IOUtils.write(str.toCharArray(), (OutputStream) null); fail(); } catch (final NullPointerException ignore) { } } @Test public void testWrite_charArrayToOutputStream_nullEncoding() throws Exception { final String str = new String(inData, StandardCharsets.US_ASCII); final ByteArrayOutputStream baout = new ByteArrayOutputStream(); final ThrowOnFlushAndCloseOutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, true, true); IOUtils.write(str.toCharArray(), out, (String) null); out.off(); out.flush(); assertEquals(inData.length, baout.size(), "Sizes differ"); assertArrayEquals(inData, baout.toByteArray(), "Content differs"); } @Test public void testWrite_charArrayToWriter() throws Exception { final String str = new String(inData, StandardCharsets.US_ASCII); final ByteArrayOutputStream baout = new ByteArrayOutputStream(); @SuppressWarnings("resource") // deliberately not closed final ThrowOnFlushAndCloseOutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, true, true); final Writer writer = new OutputStreamWriter(baout, StandardCharsets.US_ASCII); IOUtils.write(str.toCharArray(), writer); out.off(); writer.flush(); assertEquals(inData.length, baout.size(), "Sizes differ"); assertArrayEquals(inData, baout.toByteArray(), "Content differs"); } @Test public void testWrite_charArrayToWriter_Encoding_nullData() throws Exception { final ByteArrayOutputStream baout = new ByteArrayOutputStream(); @SuppressWarnings("resource") // deliberately not closed final ThrowOnFlushAndCloseOutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, true, true); final Writer writer = new OutputStreamWriter(baout, StandardCharsets.US_ASCII); IOUtils.write((char[]) null, writer); out.off(); writer.flush(); assertEquals(0, baout.size(), "Sizes differ"); } @Test public void testWrite_charArrayToWriter_Encoding_nullStream() throws Exception { final String str = new String(inData, StandardCharsets.US_ASCII); try { IOUtils.write(str.toCharArray(), (Writer) null); fail(); } catch (final NullPointerException ignore) { } } @Test public void testWriteLines_OutputStream() throws Exception { final Object[] data = { "hello", new StringBuffer("world"), "", "this is", null, "some text"}; final List list = Arrays.asList(data); final ByteArrayOutputStream baout = new ByteArrayOutputStream(); final ThrowOnFlushAndCloseOutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, false, true); IOUtils.writeLines(list, "*", out); out.off(); out.flush(); final String expected = "hello*world**this is**some text*"; final String actual = baout.toString(); assertEquals(expected, actual); } @Test public void testWriteLines_OutputStream_nullData() throws Exception { final ByteArrayOutputStream baout = new ByteArrayOutputStream(); final ThrowOnFlushAndCloseOutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, false, true); IOUtils.writeLines(null, "*", out); out.off(); out.flush(); assertEquals(0, baout.size(), "Sizes differ"); } @Test public void testWriteLines_OutputStream_nullSeparator() throws Exception { final Object[] data = {"hello", "world"}; final List list = Arrays.asList(data); final ByteArrayOutputStream baout = new ByteArrayOutputStream(); final ThrowOnFlushAndCloseOutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, false, true); IOUtils.writeLines(list, null, out); out.off(); out.flush(); final String expected = "hello" + System.lineSeparator() + "world" + System.lineSeparator(); final String actual = baout.toString(); assertEquals(expected, actual); } @Test public void testWriteLines_OutputStream_nullStream() throws Exception { final Object[] data = {"hello", "world"}; final List list = Arrays.asList(data); try { IOUtils.writeLines(list, "*", (OutputStream) null); fail(); } catch (final NullPointerException ignore) { } } @Test public void testWriteLines_OutputStream_Encoding() throws Exception { final Object[] data = { "hello\u8364", new StringBuffer("world"), "", "this is", null, "some text"}; final List list = Arrays.asList(data); final ByteArrayOutputStream baout = new ByteArrayOutputStream(); final ThrowOnFlushAndCloseOutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, false, true); IOUtils.writeLines(list, "*", out, "UTF-8"); out.off(); out.flush(); final String expected = "hello\u8364*world**this is**some text*"; final String actual = baout.toString("UTF-8"); assertEquals(expected, actual); } @Test public void testWriteLines_OutputStream_Encoding_nullData() throws Exception { final ByteArrayOutputStream baout = new ByteArrayOutputStream(); final ThrowOnFlushAndCloseOutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, false, true); IOUtils.writeLines(null, "*", out, "US-ASCII"); out.off(); out.flush(); assertEquals(0, baout.size(), "Sizes differ"); } @Test public void testWriteLines_OutputStream_Encoding_nullSeparator() throws Exception { final Object[] data = {"hello", "world"}; final List list = Arrays.asList(data); final ByteArrayOutputStream baout = new ByteArrayOutputStream(); final ThrowOnFlushAndCloseOutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, false, true); IOUtils.writeLines(list, null, out, "US-ASCII"); out.off(); out.flush(); final String expected = "hello" + System.lineSeparator() + "world" + System.lineSeparator(); final String actual = baout.toString(); assertEquals(expected, actual); } @Test public void testWriteLines_OutputStream_Encoding_nullStream() throws Exception { final Object[] data = {"hello", "world"}; final List list = Arrays.asList(data); try { IOUtils.writeLines(list, "*", null, "US-ASCII"); fail(); } catch (final NullPointerException ignore) { } } @Test public void testWriteLines_OutputStream_Encoding_nullEncoding() throws Exception { final Object[] data = { "hello", new StringBuffer("world"), "", "this is", null, "some text"}; final List list = Arrays.asList(data); final ByteArrayOutputStream baout = new ByteArrayOutputStream(); final ThrowOnFlushAndCloseOutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, false, true); IOUtils.writeLines(list, "*", out, (String) null); out.off(); out.flush(); final String expected = "hello*world**this is**some text*"; final String actual = baout.toString(); assertEquals(expected, actual); } @Test public void testWriteLines_Writer() throws Exception { final Object[] data = { "hello", new StringBuffer("world"), "", "this is", null, "some text"}; final List list = Arrays.asList(data); final ByteArrayOutputStream baout = new ByteArrayOutputStream(); @SuppressWarnings("resource") // deliberately not closed final ThrowOnFlushAndCloseOutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, true, true); final Writer writer = new OutputStreamWriter(baout, StandardCharsets.US_ASCII); IOUtils.writeLines(list, "*", writer); out.off(); writer.flush(); final String expected = "hello*world**this is**some text*"; final String actual = baout.toString(); assertEquals(expected, actual); } @Test public void testWriteLines_Writer_nullData() throws Exception { final ByteArrayOutputStream baout = new ByteArrayOutputStream(); @SuppressWarnings("resource") // deliberately not closed final ThrowOnFlushAndCloseOutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, true, true); final Writer writer = new OutputStreamWriter(baout, StandardCharsets.US_ASCII); IOUtils.writeLines(null, "*", writer); out.off(); writer.flush(); assertEquals(0, baout.size(), "Sizes differ"); } @Test public void testWriteLines_Writer_nullSeparator() throws Exception { final Object[] data = {"hello", "world"}; final List list = Arrays.asList(data); final ByteArrayOutputStream baout = new ByteArrayOutputStream(); @SuppressWarnings("resource") // deliberately not closed final ThrowOnFlushAndCloseOutputStream out = new ThrowOnFlushAndCloseOutputStream(baout, true, true); final Writer writer = new OutputStreamWriter(baout, StandardCharsets.US_ASCII); IOUtils.writeLines(list, null, writer); out.off(); writer.flush(); final String expected = "hello" + System.lineSeparator() + "world" + System.lineSeparator(); final String actual = baout.toString(); assertEquals(expected, actual); } @Test public void testWriteLines_Writer_nullStream() throws Exception { final Object[] data = {"hello", "world"}; final List list = Arrays.asList(data); try { IOUtils.writeLines(list, "*", (Writer) null); fail(); } catch (final NullPointerException ignore) { } } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/LineIteratorTestCase.java0100644 0000000 0000000 00000034220 13612062727 030467 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import java.nio.charset.UnsupportedCharsetException; import java.nio.file.Files; import java.util.ArrayList; import java.util.List; import java.util.NoSuchElementException; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; /** * This is used to test LineIterator for correctness. * */ public class LineIteratorTestCase { @TempDir public File temporaryFolder; private void assertLines(final List lines, final LineIterator iterator) { try { for (int i = 0; i < lines.size(); i++) { final String line = iterator.nextLine(); assertEquals(lines.get(i), line, "nextLine() line " + i); } assertFalse(iterator.hasNext(), "No more expected"); } finally { try { IOUtils.close(iterator); } catch (final IOException ignored) { // Ignored } } } /** * Creates a test file with a specified number of lines. * * @param file target file * @param lineCount number of lines to create * * @throws IOException If an I/O error occurs */ private List createLinesFile(final File file, final int lineCount) throws IOException { final List lines = createStringLines(lineCount); FileUtils.writeLines(file, lines); return lines; } /** * Creates a test file with a specified number of lines. * * @param file target file * @param encoding the encoding to use while writing the lines * @param lineCount number of lines to create * * @throws IOException If an I/O error occurs */ private List createLinesFile(final File file, final String encoding, final int lineCount) throws IOException { final List lines = createStringLines(lineCount); FileUtils.writeLines(file, encoding, lines); return lines; } /** * Creates String data lines. * * @param lineCount number of lines to create * @return a new lines list. */ private List createStringLines(final int lineCount) { final List lines = new ArrayList<>(); for (int i = 0; i < lineCount; i++) { lines.add("LINE " + i); } return lines; } // ----------------------------------------------------------------------- @Test public void testConstructor() { assertThrows(IllegalArgumentException.class, () -> { try ( LineIterator li = new LineIterator(null) ) { } }); } @Test public void testZeroLines() throws Exception { doTestFileWithSpecifiedLines(0); } @Test public void testOneLines() throws Exception { doTestFileWithSpecifiedLines(1); } @Test public void testTwoLines() throws Exception { doTestFileWithSpecifiedLines(2); } @Test public void testThreeLines() throws Exception { doTestFileWithSpecifiedLines(3); } @Test public void testMissingFile() throws Exception { final File testFile = new File(temporaryFolder, "dummy-missing-file.txt"); try ( LineIterator iterator = FileUtils.lineIterator(testFile, "UTF-8") ){ fail("Expected FileNotFoundException"); } catch (final FileNotFoundException expected) { // ignore, expected result } } @Test public void testValidEncoding() throws Exception { final String encoding = "UTF-8"; final File testFile = new File(temporaryFolder, "LineIterator-validEncoding.txt"); createLinesFile(testFile, encoding, 3); try ( final LineIterator iterator = FileUtils.lineIterator(testFile, encoding) ){ int count = 0; while (iterator.hasNext()) { assertNotNull(iterator.next()); count++; } assertEquals(3, count); } } @Test public void testInvalidEncoding() throws Exception { final String encoding = "XXXXXXXX"; final File testFile = new File(temporaryFolder, "LineIterator-invalidEncoding.txt"); createLinesFile(testFile, "UTF-8", 3); try ( LineIterator iterator = FileUtils.lineIterator(testFile, encoding) ) { fail("Expected UnsupportedCharsetException"); } catch (final UnsupportedCharsetException expected) { // ignore, expected result } } @Test public void testNextLineOnlyDefaultEncoding() throws Exception { final File testFile = new File(temporaryFolder, "LineIterator-nextOnly.txt"); final List lines = createLinesFile(testFile, 3); final LineIterator iterator = FileUtils.lineIterator(testFile); assertLines(lines, iterator); } @Test public void testNextLineOnlyNullEncoding() throws Exception { final String encoding = null; final File testFile = new File(temporaryFolder, "LineIterator-nextOnly.txt"); final List lines = createLinesFile(testFile, encoding, 3); final LineIterator iterator = FileUtils.lineIterator(testFile, encoding); assertLines(lines, iterator); } @Test public void testNextLineOnlyUtf8Encoding() throws Exception { final String encoding = "UTF-8"; final File testFile = new File(temporaryFolder, "LineIterator-nextOnly.txt"); final List lines = createLinesFile(testFile, encoding, 3); final LineIterator iterator = FileUtils.lineIterator(testFile, encoding); assertLines(lines, iterator); } @Test public void testNextOnly() throws Exception { final String encoding = null; final File testFile = new File(temporaryFolder, "LineIterator-nextOnly.txt"); final List lines = createLinesFile(testFile, encoding, 3); try ( final LineIterator iterator = FileUtils.lineIterator(testFile, encoding) ){ for (int i = 0; i < lines.size(); i++) { final String line = iterator.next(); assertEquals(lines.get(i), line, "next() line " + i); } assertFalse(iterator.hasNext(), "No more expected"); } } @Test public void testNextWithException() throws Exception { final Reader reader = new BufferedReader(new StringReader("")) { @Override public String readLine() throws IOException { throw new IOException("hasNext"); } }; try ( LineIterator li = new LineIterator(reader) ) { assertThrows(IllegalStateException.class, () -> { li.hasNext(); }); } } @Test public void testCloseEarly() throws Exception { final String encoding = "UTF-8"; final File testFile = new File(temporaryFolder, "LineIterator-closeEarly.txt"); createLinesFile(testFile, encoding, 3); try ( final LineIterator iterator = FileUtils.lineIterator(testFile, encoding) ) { // get assertNotNull("Line expected", iterator.next()); assertTrue(iterator.hasNext(), "More expected"); // close iterator.close(); assertFalse(iterator.hasNext(), "No more expected"); try { iterator.next(); fail(); } catch (final NoSuchElementException ex) { // expected } try { iterator.nextLine(); fail(); } catch (final NoSuchElementException ex) { // expected } // try closing again iterator.close(); try { iterator.next(); fail(); } catch (final NoSuchElementException ex) { // expected } try { iterator.nextLine(); fail(); } catch (final NoSuchElementException ex) { // expected } } } /** * Utility method to create and test a file with a specified number of lines. * * @param lineCount the lines to create in the test file * * @throws IOException If an I/O error occurs while creating the file */ private void doTestFileWithSpecifiedLines(final int lineCount) throws IOException { final String encoding = "UTF-8"; final String fileName = "LineIterator-" + lineCount + "-test.txt"; final File testFile = new File(temporaryFolder, fileName); final List lines = createLinesFile(testFile, encoding, lineCount); try ( final LineIterator iterator = FileUtils.lineIterator(testFile, encoding) ){ try { iterator.remove(); fail("Remove is unsupported"); } catch (final UnsupportedOperationException ex) { // expected } int idx = 0; while (iterator.hasNext()) { final String line = iterator.next(); assertEquals(lines.get(idx), line, "Comparing line " + idx); assertTrue(idx < lines.size(), "Exceeded expected idx=" + idx + " size=" + lines.size()); idx++; } assertEquals(idx, lines.size(), "Line Count doesn't match"); // try calling next() after file processed try { iterator.next(); fail("Expected NoSuchElementException"); } catch (final NoSuchElementException expected) { // ignore, expected result } try { iterator.nextLine(); fail("Expected NoSuchElementException"); } catch (final NoSuchElementException expected) { // ignore, expected result } } } // ----------------------------------------------------------------------- @Test public void testFilteringFileReader() throws Exception { final String encoding = "UTF-8"; final String fileName = "LineIterator-Filter-test.txt"; final File testFile = new File(temporaryFolder, fileName); final List lines = createLinesFile(testFile, encoding, 9); final Reader reader = Files.newBufferedReader(testFile.toPath()); this.testFiltering(lines, reader); } @Test public void testFilteringBufferedReader() throws Exception { final String encoding = "UTF-8"; final String fileName = "LineIterator-Filter-test.txt"; final File testFile = new File(temporaryFolder, fileName); final List lines = createLinesFile(testFile, encoding, 9); final Reader reader = new BufferedReader(Files.newBufferedReader(testFile.toPath())); this.testFiltering(lines, reader); } private void testFiltering(final List lines, final Reader reader) { final LineIterator iterator = new LineIterator(reader) { @Override protected boolean isValidLine(final String line) { final char c = line.charAt(line.length() - 1); return (c - 48) % 3 != 1; } }; try { try { iterator.remove(); fail("Remove is unsupported"); } catch (final UnsupportedOperationException ex) { // expected } int idx = 0; int actualLines = 0; while (iterator.hasNext()) { final String line = iterator.next(); actualLines++; assertEquals(lines.get(idx), line, "Comparing line " + idx); assertTrue(idx < lines.size(), "Exceeded expected idx=" + idx + " size=" + lines.size()); idx++; if (idx % 3 == 1) { idx++; } } assertEquals(9, lines.size(), "Line Count doesn't match"); assertEquals(9, idx, "Line Count doesn't match"); assertEquals(6, actualLines, "Line Count doesn't match"); // try calling next() after file processed try { iterator.next(); fail("Expected NoSuchElementException"); } catch (final NoSuchElementException expected) { // ignore, expected result } try { iterator.nextLine(); fail("Expected NoSuchElementException"); } catch (final NoSuchElementException expected) { // ignore, expected result } } finally { try { IOUtils.close(iterator); } catch (final IOException ignored) { // Ignored } } } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/SelectorAdapter.java0100644 0000000 0000000 00000003502 13612062727 027512 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import java.io.IOException; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.spi.SelectorProvider; import java.util.Set; /** * Extends {@link Selector} with no-ops for testing. * */ public class SelectorAdapter extends Selector { @Override public boolean isOpen() { return false; } @Override public SelectorProvider provider() { return null; } @Override public Set keys() { return null; } @Override public Set selectedKeys() { return null; } @Override public int selectNow() throws IOException { return 0; } @Override public int select(final long timeout) throws IOException { return 0; } @Override public int select() throws IOException { return 0; } @Override public Selector wakeup() { return null; } @Override public void close() throws IOException { } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/StandardLineSeparatorTest.java0100644 0000000 0000000 00000004061 13612062727 031523 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import static org.apache.commons.io.StandardLineSeparator.CR; import static org.apache.commons.io.StandardLineSeparator.CRLF; import static org.apache.commons.io.StandardLineSeparator.LF; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import java.nio.charset.StandardCharsets; import org.junit.jupiter.api.Test; /** * Tests {@link StandardLineSeparator}. */ public class StandardLineSeparatorTest { @Test public void testCR() { assertEquals("\r", CR.getString()); } @Test public void testCR_getBytes() { assertArrayEquals("\r".getBytes(StandardCharsets.ISO_8859_1), CR.getBytes(StandardCharsets.ISO_8859_1)); } @Test public void testCRLF() { assertEquals("\r\n", CRLF.getString()); } @Test public void testCRLF_getBytes() { assertArrayEquals("\r\n".getBytes(StandardCharsets.ISO_8859_1), CRLF.getBytes(StandardCharsets.ISO_8859_1)); } @Test public void testLF() { assertEquals("\n", LF.getString()); } @Test public void testLF_getBytes() { assertArrayEquals("\n".getBytes(StandardCharsets.ISO_8859_1), LF.getBytes(StandardCharsets.ISO_8859_1)); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/TaggedIOExceptionTest.java0100644 0000000 0000000 00000003336 13612062727 030600 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; import java.io.Serializable; import java.util.UUID; import org.junit.jupiter.api.Test; /** * JUnit Test Case for {@link TaggedIOException}. */ public class TaggedIOExceptionTest { @Test public void testTaggedIOException() { final Serializable tag = UUID.randomUUID(); final IOException exception = new IOException("Test exception"); final TaggedIOException tagged = new TaggedIOException(exception, tag); assertTrue(TaggedIOException.isTaggedWith(tagged, tag)); assertFalse(TaggedIOException.isTaggedWith(tagged, UUID.randomUUID())); assertEquals(exception, tagged.getCause()); assertEquals(exception.getMessage(), tagged.getMessage()); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/TestResources.java0100644 0000000 0000000 00000003466 13612062727 027254 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import java.io.File; import java.io.InputStream; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.nio.file.Path; import java.nio.file.Paths; /** * Provides access to this package's test resources. */ public class TestResources { private static final String ROOT = "/org/apache/commons/io/"; public static File getFile(final String fileName) throws URISyntaxException { return new File(getURI(fileName)); } public static Path getPath(final String fileName) throws URISyntaxException { return Paths.get(getURI(fileName)); } public static URI getURI(final String fileName) throws URISyntaxException { return getURL(fileName).toURI(); } public static URL getURL(final String fileName) { return TestResources.class.getResource(ROOT + fileName); } public static InputStream getInputStream(final String fileName) { return TestResources.class.getResourceAsStream(ROOT + fileName); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/ThreadMonitorTestCase.java0100644 0000000 0000000 00000005241 13612062727 030646 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.fail; import java.time.Duration; import org.apache.commons.io.test.TestUtils; import org.junit.jupiter.api.Test; /** * Tests for {@link ThreadMonitor}. */ public class ThreadMonitorTestCase { /** * Test timeout. */ @Test public void testTimeout() { try { final Thread monitor = ThreadMonitor.start(Duration.ofMillis(100)); TestUtils.sleep(200); ThreadMonitor.stop(monitor); fail("Expected InterruptedException"); } catch (final InterruptedException e) { // expected result - timeout } } /** * Test task completed before timeout. */ @Test public void testCompletedWithoutTimeout() { try { final Thread monitor = ThreadMonitor.start(Duration.ofMillis(200)); TestUtils.sleep(100); ThreadMonitor.stop(monitor); } catch (final InterruptedException e) { fail("Timed Out"); } } /** * Test No timeout. */ @Test public void testNoTimeout() { // timeout = -1 try { final Thread monitor = ThreadMonitor.start(Duration.ofMillis(-1)); assertNull(monitor,"Timeout -1, Monitor should be null"); TestUtils.sleep(100); ThreadMonitor.stop(monitor); } catch (final Exception e) { fail("Timeout -1, threw " + e); } // timeout = 0 try { final Thread monitor = ThreadMonitor.start(Duration.ZERO); assertNull(monitor, "Timeout 0, Monitor should be null"); TestUtils.sleep(100); ThreadMonitor.stop(monitor); } catch (final Exception e) { fail("Timeout 0, threw " + e); } } } ././@LongLink0100644 0000000 0000000 00000000145 13612062727 011641 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/java/org/apache/commons/io/comparator/ComparatorAbstractTestCase.javacommons-io-2.11.0-src/src/test/java/org/apache/commons/io/comparator/ComparatorAbstractTestCase.java0100644 0000000 0000000 00000007722 13612062727 034037 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.comparator; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.File; import java.util.ArrayList; import java.util.Comparator; import java.util.List; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; /** * Base Test case for Comparator implementations. */ public abstract class ComparatorAbstractTestCase { @TempDir public File dir; /** comparator instance */ protected AbstractFileComparator comparator; /** reverse comparator instance */ protected Comparator reverse; /** File which compares equal to "equalFile2" */ protected File equalFile1; /** File which compares equal to "equalFile1" */ protected File equalFile2; /** File which is less than the "moreFile" */ protected File lessFile; /** File which is more than the "lessFile" */ protected File moreFile; /** * Test the comparator. */ @Test public void testComparator() { assertEquals(0, comparator.compare(equalFile1, equalFile2), "equal"); assertTrue(comparator.compare(lessFile, moreFile) < 0, "less"); assertTrue(comparator.compare(moreFile, lessFile) > 0, "more"); } /** * Test the comparator reversed. */ @Test public void testReverseComparator() { assertEquals(0, reverse.compare(equalFile1, equalFile2), "equal"); assertTrue(reverse.compare(moreFile, lessFile) < 0, "less"); assertTrue(reverse.compare(lessFile, moreFile) > 0, "more"); } /** * Test comparator array sort is null safe. */ @Test public void testSortArrayNull() { assertNull(comparator.sort((File[])null)); } /** * Test the comparator array sort. */ @Test public void testSortArray() { final File[] files = new File[3]; files[0] = equalFile1; files[1] = moreFile; files[2] = lessFile; comparator.sort(files); assertSame(lessFile, files[0], "equal"); assertSame(equalFile1, files[1], "less"); assertSame(moreFile, files[2], "more"); } /** * Test the comparator array sort. */ @Test public void testSortList() { final List files = new ArrayList<>(); files.add(equalFile1); files.add(moreFile); files.add(lessFile); comparator.sort(files); assertSame(lessFile, files.get(0), "equal"); assertSame(equalFile1, files.get(1), "less"); assertSame(moreFile, files.get(2), "more"); } /** * Test comparator list sort is null safe. */ @Test public void testSortListNull() { assertNull(comparator.sort((List)null)); } /** * Test comparator toString. */ @Test public void testToString() { assertNotNull(comparator.toString(), "comparator"); assertTrue(reverse.toString().startsWith("ReverseFileComparator["), "reverse"); } } ././@LongLink0100644 0000000 0000000 00000000146 13612062727 011642 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/java/org/apache/commons/io/comparator/CompositeFileComparatorTest.javacommons-io-2.11.0-src/src/test/java/org/apache/commons/io/comparator/CompositeFileComparatorTest.jav0100644 0000000 0000000 00000011506 13612062727 034074 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.comparator; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.BufferedOutputStream; import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.util.ArrayList; import java.util.Comparator; import java.util.List; import org.apache.commons.io.test.TestUtils; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Test case for {@link CompositeFileComparator}. */ public class CompositeFileComparatorTest extends ComparatorAbstractTestCase { @BeforeEach public void setUp() throws Exception { comparator = new CompositeFileComparator( (AbstractFileComparator) SizeFileComparator.SIZE_COMPARATOR, (AbstractFileComparator) ExtensionFileComparator.EXTENSION_COMPARATOR); reverse = new ReverseFileComparator(comparator); lessFile = new File(dir, "xyz.txt"); equalFile1 = new File(dir, "foo.txt"); equalFile2 = new File(dir, "bar.txt"); moreFile = new File(dir, "foo.xyz"); if (!lessFile.getParentFile().exists()) { throw new IOException("Cannot create file " + lessFile + " as the parent directory does not exist"); } try (final BufferedOutputStream output3 = new BufferedOutputStream(Files.newOutputStream(lessFile.toPath()))) { TestUtils.generateTestData(output3, 32); } if (!equalFile1.getParentFile().exists()) { throw new IOException("Cannot create file " + equalFile1 + " as the parent directory does not exist"); } try (final BufferedOutputStream output2 = new BufferedOutputStream(Files.newOutputStream(equalFile1.toPath()))) { TestUtils.generateTestData(output2, 48); } if (!equalFile2.getParentFile().exists()) { throw new IOException("Cannot create file " + equalFile2 + " as the parent directory does not exist"); } try (final BufferedOutputStream output1 = new BufferedOutputStream(Files.newOutputStream(equalFile2.toPath()))) { TestUtils.generateTestData(output1, 48); } if (!moreFile.getParentFile().exists()) { throw new IOException("Cannot create file " + moreFile + " as the parent directory does not exist"); } try (final BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(moreFile.toPath()))) { TestUtils.generateTestData(output, 48); } } /** * Test Constructor with null Iterable */ @Test public void constructorIterable_order() { final List> list = new ArrayList<>(); list.add(SizeFileComparator.SIZE_COMPARATOR); list.add(ExtensionFileComparator.EXTENSION_COMPARATOR); final Comparator c = new CompositeFileComparator(list); assertEquals(0, c.compare(equalFile1, equalFile2), "equal"); assertTrue(c.compare(lessFile, moreFile) < 0, "less"); assertTrue(c.compare(moreFile, lessFile) > 0, "more"); } /** * Test Constructor with null Iterable */ @Test public void constructorIterable_Null() { final Comparator c = new CompositeFileComparator((Iterable>)null); assertEquals(0, c.compare(lessFile, moreFile), "less,more"); assertEquals(0, c.compare(moreFile, lessFile), "more,less"); assertEquals("CompositeFileComparator{}", c.toString(), "toString"); } /** * Test Constructor with null array */ @Test public void constructorArray_Null() { final Comparator c = new CompositeFileComparator((Comparator[])null); assertEquals(0, c.compare(lessFile, moreFile), "less,more"); assertEquals(0, c.compare(moreFile, lessFile), "more,less"); assertEquals("CompositeFileComparator{}", c.toString(), "toString"); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/comparator/DefaultFileComparatorTest.java0100644 0000000 0000000 00000002556 13612062727 033664 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.comparator; import java.io.File; import org.junit.jupiter.api.BeforeEach; /** * Test case for {@link DefaultFileComparator}. */ public class DefaultFileComparatorTest extends ComparatorAbstractTestCase { @BeforeEach public void setUp() { comparator = (AbstractFileComparator) DefaultFileComparator.DEFAULT_COMPARATOR; reverse = DefaultFileComparator.DEFAULT_REVERSE; equalFile1 = new File("foo"); equalFile2 = new File("foo"); lessFile = new File("abc"); moreFile = new File("xyz"); } } ././@LongLink0100644 0000000 0000000 00000000146 13612062727 011642 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/java/org/apache/commons/io/comparator/DirectoryFileComparatorTest.javacommons-io-2.11.0-src/src/test/java/org/apache/commons/io/comparator/DirectoryFileComparatorTest.jav0100644 0000000 0000000 00000003444 13612062727 034100 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.comparator; import java.io.File; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Test case for {@link DirectoryFileComparator}. */ public class DirectoryFileComparatorTest extends ComparatorAbstractTestCase { @BeforeEach public void setUp() { comparator = (AbstractFileComparator) DirectoryFileComparator.DIRECTORY_COMPARATOR; reverse = DirectoryFileComparator.DIRECTORY_REVERSE; final File currentDir = new File("."); equalFile1 = new File(currentDir, "src"); equalFile2 = new File(currentDir, "src/site/xdoc"); lessFile = new File(currentDir, "src"); moreFile = new File(currentDir, "pom.xml"); } /** * Test the comparator array sort. */ @Override @Test public void testSortArray() { // skip sort test } /** * Test the comparator array sort. */ @Override public void testSortList() { // skip sort test } } ././@LongLink0100644 0000000 0000000 00000000146 13612062727 011642 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/java/org/apache/commons/io/comparator/ExtensionFileComparatorTest.javacommons-io-2.11.0-src/src/test/java/org/apache/commons/io/comparator/ExtensionFileComparatorTest.jav0100644 0000000 0000000 00000005110 13612062727 034100 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.comparator; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.File; import java.util.Comparator; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Test case for {@link ExtensionFileComparator}. */ public class ExtensionFileComparatorTest extends ComparatorAbstractTestCase { @BeforeEach public void setUp() { comparator = (AbstractFileComparator) ExtensionFileComparator.EXTENSION_COMPARATOR; reverse = ExtensionFileComparator.EXTENSION_REVERSE; equalFile1 = new File("abc.foo"); equalFile2 = new File("def.foo"); lessFile = new File("abc.abc"); moreFile = new File("abc.xyz"); } /** Test case sensitivity */ @Test public void testCaseSensitivity() { final File file3 = new File("abc.FOO"); final Comparator sensitive = new ExtensionFileComparator(null); /* test null as well */ assertEquals(0, sensitive.compare(equalFile1, equalFile2), "sensitive file1 & file2 = 0"); assertTrue(sensitive.compare(equalFile1, file3) > 0, "sensitive file1 & file3 > 0"); assertTrue(sensitive.compare(equalFile1, lessFile) > 0, "sensitive file1 & less > 0"); final Comparator insensitive = ExtensionFileComparator.EXTENSION_INSENSITIVE_COMPARATOR; assertEquals(0, insensitive.compare(equalFile1, equalFile2), "insensitive file1 & file2 = 0"); assertEquals(0, insensitive.compare(equalFile1, file3), "insensitive file1 & file3 = 0"); assertTrue(insensitive.compare(equalFile1, lessFile) > 0, "insensitive file1 & file4 > 0"); assertTrue(insensitive.compare(file3, lessFile) > 0, "insensitive file3 & less > 0"); } } ././@LongLink0100644 0000000 0000000 00000000151 13612062727 011636 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/java/org/apache/commons/io/comparator/LastModifiedFileComparatorTest.javacommons-io-2.11.0-src/src/test/java/org/apache/commons/io/comparator/LastModifiedFileComparatorTest.0100644 0000000 0000000 00000006275 13612062727 034004 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.comparator; import java.io.BufferedOutputStream; import java.io.File; import java.io.IOException; import java.nio.file.Files; import org.apache.commons.io.FileUtils; import org.apache.commons.io.test.TestUtils; import org.junit.jupiter.api.BeforeEach; /** * Test case for {@link LastModifiedFileComparator}. */ public class LastModifiedFileComparatorTest extends ComparatorAbstractTestCase { @BeforeEach public void setUp() throws Exception { comparator = (AbstractFileComparator) LastModifiedFileComparator.LASTMODIFIED_COMPARATOR; reverse = LastModifiedFileComparator.LASTMODIFIED_REVERSE; final File olderFile = new File(dir, "older.txt"); if (!olderFile.getParentFile().exists()) { throw new IOException("Cannot create file " + olderFile + " as the parent directory does not exist"); } try (final BufferedOutputStream output2 = new BufferedOutputStream(Files.newOutputStream(olderFile.toPath()))) { TestUtils.generateTestData(output2, 0); } final File equalFile = new File(dir, "equal.txt"); if (!equalFile.getParentFile().exists()) { throw new IOException("Cannot create file " + equalFile + " as the parent directory does not exist"); } try (final BufferedOutputStream output1 = new BufferedOutputStream(Files.newOutputStream(equalFile.toPath()))) { TestUtils.generateTestData(output1, 0); } do { TestUtils.sleepQuietly(300); equalFile.setLastModified(System.currentTimeMillis()); } while (FileUtils.lastModified(olderFile) == FileUtils.lastModified(equalFile)); final File newerFile = new File(dir, "newer.txt"); if (!newerFile.getParentFile().exists()) { throw new IOException("Cannot create file " + newerFile + " as the parent directory does not exist"); } try (final BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(newerFile.toPath()))) { TestUtils.generateTestData(output, 0); } do { TestUtils.sleepQuietly(300); newerFile.setLastModified(System.currentTimeMillis()); } while (FileUtils.lastModified(equalFile) == FileUtils.lastModified(newerFile)); equalFile1 = equalFile; equalFile2 = equalFile; lessFile = olderFile; moreFile = newerFile; } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/comparator/NameFileComparatorTest.java0100644 0000000 0000000 00000005060 13612062727 033151 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.comparator; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.File; import java.util.Comparator; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Test case for {@link NameFileComparator}. */ public class NameFileComparatorTest extends ComparatorAbstractTestCase { @BeforeEach public void setUp() { comparator = (AbstractFileComparator) NameFileComparator.NAME_INSENSITIVE_COMPARATOR; reverse = NameFileComparator.NAME_REVERSE; equalFile1 = new File("a/foo.txt"); equalFile2 = new File("b/foo.txt"); lessFile = new File("c/ABC.txt"); moreFile = new File("d/XYZ.txt"); } /** Test case sensitivity */ @Test public void testCaseSensitivity() { final File file3 = new File("a/FOO.txt"); final Comparator sensitive = new NameFileComparator(null); /* test null as well */ assertEquals(0, sensitive.compare(equalFile1, equalFile2), "sensitive file1 & file2 = 0"); assertTrue(sensitive.compare(equalFile1, file3) > 0, "sensitive file1 & file3 > 0"); assertTrue(sensitive.compare(equalFile1, lessFile) > 0, "sensitive file1 & less > 0"); final Comparator insensitive = NameFileComparator.NAME_INSENSITIVE_COMPARATOR; assertEquals(0, insensitive.compare(equalFile1, equalFile2), "insensitive file1 & file2 = 0"); assertEquals(0, insensitive.compare(equalFile1, file3), "insensitive file1 & file3 = 0"); assertTrue(insensitive.compare(equalFile1, lessFile) > 0, "insensitive file1 & file4 > 0"); assertTrue(insensitive.compare(file3, lessFile) > 0, "insensitive file3 & less > 0"); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/comparator/PathFileComparatorTest.java0100644 0000000 0000000 00000005064 13612062727 033171 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.comparator; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.File; import java.util.Comparator; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Test case for {@link PathFileComparator}. */ public class PathFileComparatorTest extends ComparatorAbstractTestCase { @BeforeEach public void setUp() { comparator = (AbstractFileComparator) PathFileComparator.PATH_COMPARATOR; reverse = PathFileComparator.PATH_REVERSE; equalFile1 = new File("foo/file.txt"); equalFile2 = new File("foo/file.txt"); lessFile = new File("abc/file.txt"); moreFile = new File("xyz/file.txt"); } /** Test case sensitivity */ @Test public void testCaseSensitivity() { final File file3 = new File("FOO/file.txt"); final Comparator sensitive = new PathFileComparator(null); /* test null as well */ assertEquals(0, sensitive.compare(equalFile1, equalFile2), "sensitive file1 & file2 = 0"); assertTrue(sensitive.compare(equalFile1, file3) > 0, "sensitive file1 & file3 > 0"); assertTrue(sensitive.compare(equalFile1, lessFile) > 0, "sensitive file1 & less > 0"); final Comparator insensitive = PathFileComparator.PATH_INSENSITIVE_COMPARATOR; assertEquals(0, insensitive.compare(equalFile1, equalFile2), "insensitive file1 & file2 = 0"); assertEquals(0, insensitive.compare(equalFile1, file3), "insensitive file1 & file3 = 0"); assertTrue(insensitive.compare(equalFile1, lessFile) > 0, "insensitive file1 & file4 > 0"); assertTrue(insensitive.compare(file3, lessFile) > 0, "insensitive file3 & less > 0"); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/comparator/SizeFileComparatorTest.java0100644 0000000 0000000 00000010013 13612062727 033175 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.comparator; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.BufferedOutputStream; import java.io.File; import java.io.IOException; import java.nio.file.Files; import org.apache.commons.io.test.TestUtils; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Test case for {@link SizeFileComparator}. */ public class SizeFileComparatorTest extends ComparatorAbstractTestCase { private File smallerDir; private File largerDir; private File smallerFile; private File largerFile; @BeforeEach public void setUp() throws Exception { comparator = (AbstractFileComparator) SizeFileComparator.SIZE_COMPARATOR; reverse = SizeFileComparator.SIZE_REVERSE; smallerDir = new File(dir, "smallerdir"); largerDir = new File(dir, "largerdir"); smallerFile = new File(smallerDir, "smaller.txt"); final File equalFile = new File(dir, "equal.txt"); largerFile = new File(largerDir, "larger.txt"); smallerDir.mkdir(); largerDir.mkdir(); if (!smallerFile.getParentFile().exists()) { throw new IOException("Cannot create file " + smallerFile + " as the parent directory does not exist"); } try (final BufferedOutputStream output2 = new BufferedOutputStream(Files.newOutputStream(smallerFile.toPath()))) { TestUtils.generateTestData(output2, 32); } if (!equalFile.getParentFile().exists()) { throw new IOException("Cannot create file " + equalFile + " as the parent directory does not exist"); } try (final BufferedOutputStream output1 = new BufferedOutputStream(Files.newOutputStream(equalFile.toPath()))) { TestUtils.generateTestData(output1, 48); } if (!largerFile.getParentFile().exists()) { throw new IOException("Cannot create file " + largerFile + " as the parent directory does not exist"); } try (final BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(largerFile.toPath()))) { TestUtils.generateTestData(output, 64); } equalFile1 = equalFile; equalFile2 = equalFile; lessFile = smallerFile; moreFile = largerFile; } /** * Test a file which doesn't exist. */ @Test public void testNonexistantFile() { final File nonexistantFile = new File(new File("."), "nonexistant.txt"); assertFalse(nonexistantFile.exists()); assertTrue(comparator.compare(nonexistantFile, moreFile) < 0, "less"); } /** * Test a file which doesn't exist. */ @Test public void testCompareDirectorySizes() { assertEquals(0, comparator.compare(smallerDir, largerDir), "sumDirectoryContents=false"); assertEquals(-1, SizeFileComparator.SIZE_SUMDIR_COMPARATOR.compare(smallerDir, largerDir), "less"); assertEquals(1, SizeFileComparator.SIZE_SUMDIR_REVERSE.compare(smallerDir, largerDir), "less"); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/file/AccumulatorPathVisitorTest.java0100644 0000000 0000000 00000012074 13612062727 032670 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.file; import static org.apache.commons.io.file.CounterAssertions.assertCounts; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.function.Supplier; import java.util.stream.Stream; import org.apache.commons.io.filefilter.AndFileFilter; import org.apache.commons.io.filefilter.DirectoryFileFilter; import org.apache.commons.io.filefilter.EmptyFileFilter; import org.apache.commons.io.filefilter.PathVisitorFileFilter; import org.junit.jupiter.api.io.TempDir; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; /** * Tests both {@link AccumulatorPathVisitor} and {@link PathVisitorFileFilter}. */ public class AccumulatorPathVisitorTest { static Stream testParameters() { // @formatter:off return Stream.of( Arguments.of((Supplier) AccumulatorPathVisitor::withLongCounters), Arguments.of((Supplier) AccumulatorPathVisitor::withBigIntegerCounters)); // @formatter:on } @TempDir File tempDirFile; /** * Tests an empty folder. */ @ParameterizedTest @MethodSource("testParameters") public void testEmptyFolder(final Supplier supplier) throws IOException { final Path tempDir = tempDirFile.toPath(); final AccumulatorPathVisitor accPathVisitor = supplier.get(); final PathVisitorFileFilter countingFileFilter = new PathVisitorFileFilter(accPathVisitor); Files.walkFileTree(tempDir, new AndFileFilter(countingFileFilter, DirectoryFileFilter.INSTANCE, EmptyFileFilter.EMPTY)); assertCounts(1, 0, 0, accPathVisitor.getPathCounters()); assertEquals(1, accPathVisitor.getDirList().size()); assertTrue(accPathVisitor.getFileList().isEmpty()); } /** * Tests a directory with one file of size 0. */ @ParameterizedTest @MethodSource("testParameters") public void testFolders1FileSize0(final Supplier supplier) throws IOException { final AccumulatorPathVisitor accPathVisitor = supplier.get(); final PathVisitorFileFilter countingFileFilter = new PathVisitorFileFilter(accPathVisitor); Files.walkFileTree(Paths.get("src/test/resources/org/apache/commons/io/dirs-1-file-size-0"), countingFileFilter); assertCounts(1, 1, 0, accPathVisitor.getPathCounters()); assertEquals(1, accPathVisitor.getDirList().size()); assertEquals(1, accPathVisitor.getFileList().size()); } /** * Tests a directory with one file of size 1. */ @ParameterizedTest @MethodSource("testParameters") public void testFolders1FileSize1(final Supplier supplier) throws IOException { final AccumulatorPathVisitor accPathVisitor = supplier.get(); final PathVisitorFileFilter countingFileFilter = new PathVisitorFileFilter(accPathVisitor); Files.walkFileTree(Paths.get("src/test/resources/org/apache/commons/io/dirs-1-file-size-1"), countingFileFilter); assertCounts(1, 1, 1, accPathVisitor.getPathCounters()); assertEquals(1, accPathVisitor.getDirList().size()); assertEquals(1, accPathVisitor.getFileList().size()); } /** * Tests a directory with two subdirectories, each containing one file of size 1. */ @ParameterizedTest @MethodSource("testParameters") public void testFolders2FileSize2(final Supplier supplier) throws IOException { final AccumulatorPathVisitor accPathVisitor = supplier.get(); final PathVisitorFileFilter countingFileFilter = new PathVisitorFileFilter(accPathVisitor); Files.walkFileTree(Paths.get("src/test/resources/org/apache/commons/io/dirs-2-file-size-2"), countingFileFilter); assertCounts(3, 2, 2, accPathVisitor.getPathCounters()); assertEquals(3, accPathVisitor.getDirList().size()); assertEquals(2, accPathVisitor.getFileList().size()); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/file/CleaningPathVisitorTest.java0100644 0000000 0000000 00000011322 13612062727 032124 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.file; import static org.apache.commons.io.file.CounterAssertions.assertCounts; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import org.apache.commons.io.file.Counters.PathCounters; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; /** * Tests {@link DeletingPathVisitor}. */ public class CleaningPathVisitorTest extends TestArguments { private Path tempDir; @AfterEach public void afterEach() throws IOException { // temp dir should still exist since we are cleaning and not deleting. assertTrue(Files.exists(tempDir)); // backstop if (Files.exists(tempDir) && PathUtils.isEmptyDirectory(tempDir)) { Files.deleteIfExists(tempDir); } } private void applyCleanEmptyDirectory(final CleaningPathVisitor visitor) throws IOException { Files.walkFileTree(tempDir, visitor); assertCounts(1, 0, 0, visitor); } @BeforeEach public void beforeEach() throws IOException { tempDir = Files.createTempDirectory(getClass().getCanonicalName()); } /** * Tests an empty folder. */ @ParameterizedTest @MethodSource("cleaningPathVisitors") public void testCleanEmptyDirectory(final CleaningPathVisitor visitor) throws IOException { applyCleanEmptyDirectory(visitor); } /** * Tests an empty folder. */ @ParameterizedTest @MethodSource("pathCounters") public void testCleanEmptyDirectoryNullCtorArg(final PathCounters pathCounters) throws IOException { applyCleanEmptyDirectory(new CleaningPathVisitor(pathCounters, (String[]) null)); } /** * Tests a directory with one file of size 0. */ @ParameterizedTest @MethodSource("cleaningPathVisitors") public void testCleanFolders1FileSize0(final CleaningPathVisitor visitor) throws IOException { PathUtils.copyDirectory(Paths.get("src/test/resources/org/apache/commons/io/dirs-1-file-size-0"), tempDir); assertCounts(1, 1, 0, PathUtils.visitFileTree(visitor, tempDir)); } /** * Tests a directory with one file of size 1. */ @ParameterizedTest @MethodSource("cleaningPathVisitors") public void testCleanFolders1FileSize1(final CleaningPathVisitor visitor) throws IOException { PathUtils.copyDirectory(Paths.get("src/test/resources/org/apache/commons/io/dirs-1-file-size-1"), tempDir); assertCounts(1, 1, 1, PathUtils.visitFileTree(visitor, tempDir)); } /** * Tests a directory with one file of size 1 but skip that file. */ @ParameterizedTest @MethodSource("pathCounters") public void testCleanFolders1FileSize1Skip(final PathCounters pathCounters) throws IOException { PathUtils.copyDirectory(Paths.get("src/test/resources/org/apache/commons/io/dirs-1-file-size-1"), tempDir); final String skipFileName = "file-size-1.bin"; final CountingPathVisitor visitor = new CleaningPathVisitor(pathCounters, skipFileName); assertCounts(1, 1, 1, PathUtils.visitFileTree(visitor, tempDir)); final Path skippedFile = tempDir.resolve(skipFileName); Assertions.assertTrue(Files.exists(skippedFile)); Files.delete(skippedFile); } /** * Tests a directory with two subdirectories, each containing one file of size 1. */ @ParameterizedTest @MethodSource("cleaningPathVisitors") public void testCleanFolders2FileSize2(final CleaningPathVisitor visitor) throws IOException { PathUtils.copyDirectory(Paths.get("src/test/resources/org/apache/commons/io/dirs-2-file-size-2"), tempDir); assertCounts(3, 2, 2, PathUtils.visitFileTree(visitor, tempDir)); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/file/CopyDirectoryVisitorTest.java0100644 0000000 0000000 00000007570 13612062727 032400 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.file; import static org.apache.commons.io.file.CounterAssertions.assertCounts; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import org.apache.commons.io.file.Counters.PathCounters; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; /** * Tests {@link CountingPathVisitor}. */ public class CopyDirectoryVisitorTest extends TestArguments { private Path targetDir; @AfterEach public void afterEach() throws IOException { PathUtils.deleteDirectory(targetDir); } @BeforeEach public void beforeEach() throws IOException { targetDir = Files.createTempDirectory(getClass().getCanonicalName() + "-target"); } /** * Tests an empty folder. */ @ParameterizedTest @MethodSource("pathCounters") public void testCopyDirectoryEmptyFolder(final PathCounters pathCounters) throws IOException { final Path sourceDir = Files.createTempDirectory(getClass().getSimpleName()); try { assertCounts(1, 0, 0, PathUtils.visitFileTree(new CopyDirectoryVisitor(pathCounters, sourceDir, targetDir, StandardCopyOption.REPLACE_EXISTING), sourceDir)); } finally { Files.deleteIfExists(sourceDir); } } /** * Tests a directory with one file of size 0. */ @ParameterizedTest @MethodSource("pathCounters") public void testCopyDirectoryFolders1FileSize0(final PathCounters pathCounters) throws IOException { final Path sourceDir = Paths.get("src/test/resources/org/apache/commons/io/dirs-1-file-size-0"); assertCounts(1, 1, 0, PathUtils.visitFileTree( new CopyDirectoryVisitor(pathCounters, sourceDir, targetDir, StandardCopyOption.REPLACE_EXISTING), sourceDir)); } /** * Tests a directory with one file of size 1. */ @ParameterizedTest @MethodSource("pathCounters") public void testCopyDirectoryFolders1FileSize1(final PathCounters pathCounters) throws IOException { final Path sourceDir = Paths.get("src/test/resources/org/apache/commons/io/dirs-1-file-size-1"); assertCounts(1, 1, 1, PathUtils.visitFileTree( new CopyDirectoryVisitor(pathCounters, sourceDir, targetDir, StandardCopyOption.REPLACE_EXISTING), sourceDir)); } /** * Tests a directory with two subdirectories, each containing one file of size 1. */ @ParameterizedTest @MethodSource("pathCounters") public void testCopyDirectoryFolders2FileSize2(final PathCounters pathCounters) throws IOException { final Path sourceDir = Paths.get("src/test/resources/org/apache/commons/io/dirs-2-file-size-2"); assertCounts(3, 2, 2, PathUtils.visitFileTree( new CopyDirectoryVisitor(pathCounters, sourceDir, targetDir, StandardCopyOption.REPLACE_EXISTING), sourceDir)); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/file/CounterAssertions.java0100644 0000000 0000000 00000004457 13612062727 031054 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.file; import static org.junit.jupiter.api.Assertions.assertEquals; import java.math.BigInteger; import org.apache.commons.io.file.Counters.Counter; import org.apache.commons.io.file.Counters.PathCounters; public class CounterAssertions { static void assertCounter(final long expected, final Counter actual, final String message) { assertEquals(expected, actual.get(), message); assertEquals(Long.valueOf(expected), actual.getLong(), message); assertEquals(BigInteger.valueOf(expected), actual.getBigInteger(), message); } static void assertCounts(final long expectedDirCount, final long expectedFileCount, final long expectedByteCount, final CountingPathVisitor actualVisitor) { assertCounts(expectedDirCount, expectedFileCount, expectedByteCount, actualVisitor.getPathCounters()); } static void assertCounts(final long expectedDirCount, final long expectedFileCount, final long expectedByteCount, final PathCounters actualPathCounters) { assertCounter(expectedDirCount, actualPathCounters.getDirectoryCounter(), "getDirectoryCounter"); assertCounter(expectedFileCount, actualPathCounters.getFileCounter(), "getFileCounter"); assertCounter(expectedByteCount, actualPathCounters.getByteCounter(), "getByteCounter"); } public static void assertZeroCounters(final PathCounters pathCounters) { assertCounts(0, 0, 0, pathCounters); assertEquals(Counters.longPathCounters(), pathCounters); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/file/CountersEqualsAndHashCodeTest.java0100644 0000000 0000000 00000011407 13612062727 033212 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.file; import org.apache.commons.io.file.Counters.Counter; import org.apache.commons.io.file.Counters.PathCounters; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; public class CountersEqualsAndHashCodeTest { @Test public void testBigIntegerCounterEquals() { testEquals(Counters.bigIntegerCounter(), Counters.bigIntegerCounter()); } @Test public void testBigIntegerHashCode() { testHashCodes(Counters.bigIntegerCounter(), Counters.bigIntegerCounter()); } private void testEquals(final Counter counter1, final Counter counter2) { Assertions.assertEquals(counter1, counter2); counter1.increment(); Assertions.assertNotEquals(counter1, counter2); counter2.increment(); Assertions.assertEquals(counter1, counter2); } private void testEqualsByteCounters(final PathCounters counter1, final PathCounters counter2) { Assertions.assertEquals(counter1, counter2); counter1.getByteCounter().increment(); Assertions.assertNotEquals(counter1, counter2); counter2.getByteCounter().increment(); Assertions.assertEquals(counter1, counter2); } private void testEqualsDirectoryCounters(final PathCounters counter1, final PathCounters counter2) { Assertions.assertEquals(counter1, counter2); counter1.getDirectoryCounter().increment(); Assertions.assertNotEquals(counter1, counter2); counter2.getDirectoryCounter().increment(); Assertions.assertEquals(counter1, counter2); } private void testEqualsFileCounters(final PathCounters counter1, final PathCounters counter2) { Assertions.assertEquals(counter1, counter2); counter1.getFileCounter().increment(); Assertions.assertNotEquals(counter1, counter2); counter2.getFileCounter().increment(); Assertions.assertEquals(counter1, counter2); } private void testHashCodeFileCounters(final PathCounters counter1, final PathCounters counter2) { Assertions.assertEquals(counter1.hashCode(), counter2.hashCode()); counter1.getFileCounter().increment(); Assertions.assertNotEquals(counter1.hashCode(), counter2.hashCode()); counter2.getFileCounter().increment(); Assertions.assertEquals(counter1.hashCode(), counter2.hashCode()); } private void testHashCodes(final Counter counter1, final Counter counter2) { Assertions.assertEquals(counter1.hashCode(), counter2.hashCode()); counter1.increment(); Assertions.assertNotEquals(counter1.hashCode(), counter2.hashCode()); counter2.increment(); Assertions.assertEquals(counter1.hashCode(), counter2.hashCode()); } @Test public void testLongCounterEquals() { testEquals(Counters.longCounter(), Counters.longCounter()); } @Test public void testLongCounterMixEquals() { testEquals(Counters.longCounter(), Counters.bigIntegerCounter()); testEquals(Counters.bigIntegerCounter(), Counters.longCounter()); } @Test public void testLongCounterHashCodes() { testHashCodes(Counters.longCounter(), Counters.longCounter()); } @Test public void testLongPathCountersEqualsByteCounters() { testEqualsByteCounters(Counters.longPathCounters(), Counters.longPathCounters()); } @Test public void testLongPathCountersEqualsDirectoryCounters() { testEqualsDirectoryCounters(Counters.longPathCounters(), Counters.longPathCounters()); } @Test public void testLongPathCountersEqualsFileCounters() { testEqualsFileCounters(Counters.longPathCounters(), Counters.longPathCounters()); } @Test public void testLongPathCountersHashCodeFileCounters() { testHashCodeFileCounters(Counters.longPathCounters(), Counters.longPathCounters()); } @Test public void testMix() { testHashCodeFileCounters(Counters.longPathCounters(), Counters.bigIntegerPathCounters()); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/file/CountersTest.java0100644 0000000 0000000 00000005424 13612062727 030017 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.file; import static org.apache.commons.io.file.CounterAssertions.assertCounter; import static org.apache.commons.io.file.CounterAssertions.assertCounts; import static org.junit.jupiter.api.Assertions.assertEquals; import org.apache.commons.io.file.Counters.Counter; import org.apache.commons.io.file.Counters.PathCounters; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; public class CountersTest extends TestArguments { @ParameterizedTest @MethodSource("numberCounters") public void testInitialValue(final Counter counter) { assertCounter(0, counter, ""); } @ParameterizedTest @MethodSource("pathCounters") public void testInitialValues(final PathCounters pathCounter) { // Does not blow up assertCounts(0, 0, 0, pathCounter); } @ParameterizedTest @MethodSource("pathCounters") public void testResetCounter(final PathCounters pathCounter) { final Counter byteCounter = pathCounter.getByteCounter(); final long old = byteCounter.get(); byteCounter.add(1); assertEquals(old + 1, byteCounter.get()); byteCounter.reset(); assertEquals(0, byteCounter.get()); } @ParameterizedTest @MethodSource("pathCounters") public void testResetPathCounter(final PathCounters pathCounter) { final Counter byteCounter = pathCounter.getByteCounter(); final long old = byteCounter.get(); byteCounter.add(1); assertEquals(old + 1, byteCounter.get()); pathCounter.reset(); assertEquals(0, byteCounter.get()); } @ParameterizedTest @MethodSource("numberCounters") public void testToString(final Counter counter) { // Does not blow up counter.toString(); } @ParameterizedTest @MethodSource("pathCounters") public void testToString(final PathCounters pathCounter) { // Does not blow up pathCounter.toString(); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/file/CountingPathVisitorTest.java0100644 0000000 0000000 00000006631 13612062727 032201 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.file; import static org.apache.commons.io.file.CounterAssertions.assertCounts; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; /** * Tests {@link CountingPathVisitor}. */ public class CountingPathVisitorTest extends TestArguments { /** * Tests an empty folder. */ @ParameterizedTest @MethodSource("countingPathVisitors") public void testCountEmptyFolder(final CountingPathVisitor visitor) throws IOException { checkZeroCounts(visitor); final Path tempDir = Files.createTempDirectory(getClass().getCanonicalName()); try { assertCounts(1, 0, 0, PathUtils.visitFileTree(visitor, tempDir)); } finally { Files.deleteIfExists(tempDir); } } /** * Tests a directory with one file of size 0. */ @ParameterizedTest @MethodSource("countingPathVisitors") public void testCountFolders1FileSize0(final CountingPathVisitor visitor) throws IOException { checkZeroCounts(visitor); assertCounts(1, 1, 0, PathUtils.visitFileTree(visitor, "src/test/resources/org/apache/commons/io/dirs-1-file-size-0")); } /** * Tests a directory with one file of size 1. */ @ParameterizedTest @MethodSource("countingPathVisitors") public void testCountFolders1FileSize1(final CountingPathVisitor visitor) throws IOException { checkZeroCounts(visitor); assertCounts(1, 1, 1, PathUtils.visitFileTree(visitor, "src/test/resources/org/apache/commons/io/dirs-1-file-size-1")); } /** * Tests a directory with two subdirectories, each containing one file of size 1. */ @ParameterizedTest @MethodSource("countingPathVisitors") public void testCountFolders2FileSize2(final CountingPathVisitor visitor) throws IOException { checkZeroCounts(visitor); assertCounts(3, 2, 2, PathUtils.visitFileTree(visitor, "src/test/resources/org/apache/commons/io/dirs-2-file-size-2")); } private void checkZeroCounts(final CountingPathVisitor visitor) { Assertions.assertEquals(CountingPathVisitor.withLongCounters(), visitor); Assertions.assertEquals(CountingPathVisitor.withBigIntegerCounters(), visitor); } @ParameterizedTest @MethodSource("countingPathVisitors") void testToString(final CountingPathVisitor visitor) { // Make sure it does not blow up visitor.toString(); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/file/DeletingPathVisitorTest.java0100644 0000000 0000000 00000011666 13612062727 032152 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.file; import static org.apache.commons.io.file.CounterAssertions.assertCounts; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import org.apache.commons.io.file.Counters.PathCounters; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; /** * Tests {@link DeletingPathVisitor}. */ public class DeletingPathVisitorTest extends TestArguments { private Path tempDir; @AfterEach public void afterEach() throws IOException { // backstop if (Files.exists(tempDir) && PathUtils.isEmptyDirectory(tempDir)) { Files.deleteIfExists(tempDir); } } private void applyDeleteEmptyDirectory(final DeletingPathVisitor visitor) throws IOException { Files.walkFileTree(tempDir, visitor); assertCounts(1, 0, 0, visitor); } @BeforeEach public void beforeEach() throws IOException { tempDir = Files.createTempDirectory(getClass().getCanonicalName()); } /** * Tests an empty folder. */ @ParameterizedTest @MethodSource("deletingPathVisitors") public void testDeleteEmptyDirectory(final DeletingPathVisitor visitor) throws IOException { applyDeleteEmptyDirectory(visitor); // This will throw if not empty. Files.deleteIfExists(tempDir); } /** * Tests an empty folder. */ @ParameterizedTest @MethodSource("pathCounters") public void testDeleteEmptyDirectoryNullCtorArg(final PathCounters pathCounters) throws IOException { applyDeleteEmptyDirectory(new DeletingPathVisitor(pathCounters, (String[]) null)); // This will throw if not empty. Files.deleteIfExists(tempDir); } /** * Tests a directory with one file of size 0. */ @ParameterizedTest @MethodSource("deletingPathVisitors") public void testDeleteFolders1FileSize0(final DeletingPathVisitor visitor) throws IOException { PathUtils.copyDirectory(Paths.get("src/test/resources/org/apache/commons/io/dirs-1-file-size-0"), tempDir); assertCounts(1, 1, 0, PathUtils.visitFileTree(visitor, tempDir)); // This will throw if not empty. Files.deleteIfExists(tempDir); } /** * Tests a directory with one file of size 1. */ @ParameterizedTest @MethodSource("deletingPathVisitors") public void testDeleteFolders1FileSize1(final DeletingPathVisitor visitor) throws IOException { PathUtils.copyDirectory(Paths.get("src/test/resources/org/apache/commons/io/dirs-1-file-size-1"), tempDir); assertCounts(1, 1, 1, PathUtils.visitFileTree(visitor, tempDir)); // This will throw if not empty. Files.deleteIfExists(tempDir); } /** * Tests a directory with one file of size 1 but skip that file. */ @ParameterizedTest @MethodSource("pathCounters") public void testDeleteFolders1FileSize1Skip(final PathCounters pathCounters) throws IOException { PathUtils.copyDirectory(Paths.get("src/test/resources/org/apache/commons/io/dirs-1-file-size-1"), tempDir); final String skipFileName = "file-size-1.bin"; final CountingPathVisitor visitor = new DeletingPathVisitor(pathCounters, skipFileName); assertCounts(1, 1, 1, PathUtils.visitFileTree(visitor, tempDir)); final Path skippedFile = tempDir.resolve(skipFileName); Assertions.assertTrue(Files.exists(skippedFile)); Files.delete(skippedFile); } /** * Tests a directory with two subdirectories, each containing one file of size 1. */ @ParameterizedTest @MethodSource("deletingPathVisitors") public void testDeleteFolders2FileSize2(final DeletingPathVisitor visitor) throws IOException { PathUtils.copyDirectory(Paths.get("src/test/resources/org/apache/commons/io/dirs-2-file-size-2"), tempDir); assertCounts(3, 2, 2, PathUtils.visitFileTree(visitor, tempDir)); // This will throw if not empty. Files.deleteIfExists(tempDir); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/file/DirectoryStreamFilterTest.java0100644 0000000 0000000 00000005061 13612062727 032500 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.file; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotEquals; import java.nio.file.DirectoryStream; import java.nio.file.Files; import java.nio.file.Path; import java.util.Iterator; import org.apache.commons.io.filefilter.NameFileFilter; import org.junit.jupiter.api.Test; /** * Tests {@link DirectoryStreamFilter}. */ public class DirectoryStreamFilterTest { private static final String PATH_FIXTURE = "NOTICE.txt"; @Test public void testFilterByName() throws Exception { final PathFilter pathFilter = new NameFileFilter(PATH_FIXTURE); final DirectoryStreamFilter streamFilter = new DirectoryStreamFilter(pathFilter); assertEquals(pathFilter, streamFilter.getPathFilter()); try (final DirectoryStream stream = Files.newDirectoryStream(PathUtils.current(), streamFilter)) { final Iterator iterator = stream.iterator(); final Path path = iterator.next(); assertEquals(PATH_FIXTURE, path.getFileName().toString()); assertFalse(iterator.hasNext()); } } @Test public void testFilterByNameNot() throws Exception { final PathFilter pathFilter = new NameFileFilter(PATH_FIXTURE).negate(); final DirectoryStreamFilter streamFilter = new DirectoryStreamFilter(pathFilter); assertEquals(pathFilter, streamFilter.getPathFilter()); try (final DirectoryStream stream = Files.newDirectoryStream(PathUtils.current(), streamFilter)) { for (final Path path : stream) { assertNotEquals(PATH_FIXTURE, path.getFileName().toString()); } } } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/file/PathUtilsCleanDirectoryTest.java0100644 0000000 0000000 00000005737 13612062727 032771 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.file; import static org.apache.commons.io.file.CounterAssertions.assertCounts; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Tests {@link DeletingPathVisitor}. */ public class PathUtilsCleanDirectoryTest { private Path tempDir; @AfterEach public void afterEach() throws IOException { // temp dir should still exist since we are cleaning and not deleting. assertTrue(Files.exists(tempDir)); // backstop if (Files.exists(tempDir) && PathUtils.isEmptyDirectory(tempDir)) { Files.deleteIfExists(tempDir); } } @BeforeEach public void beforeEach() throws IOException { tempDir = Files.createTempDirectory(getClass().getCanonicalName()); } /** * Tests a directory with one file of size 0. */ @Test public void testCleanDirectory1FileSize0() throws IOException { PathUtils.copyDirectory(Paths.get("src/test/resources/org/apache/commons/io/dirs-1-file-size-0"), tempDir); assertCounts(1, 1, 0, PathUtils.cleanDirectory(tempDir)); } /** * Tests a directory with one file of size 1. */ @Test public void testCleanDirectory1FileSize1() throws IOException { PathUtils.copyDirectory(Paths.get("src/test/resources/org/apache/commons/io/dirs-1-file-size-1"), tempDir); assertCounts(1, 1, 1, PathUtils.cleanDirectory(tempDir)); } /** * Tests a directory with two subdirectories, each containing one file of size 1. */ @Test public void testCleanDirectory2FileSize2() throws IOException { PathUtils.copyDirectory(Paths.get("src/test/resources/org/apache/commons/io/dirs-2-file-size-2"), tempDir); assertCounts(3, 2, 2, PathUtils.cleanDirectory(tempDir)); } /** * Tests an empty folder. */ @Test public void testCleanEmptyDirectory() throws IOException { assertCounts(1, 0, 0, PathUtils.cleanDirectory(tempDir)); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/file/PathUtilsContentEqualsTest.java0100644 0000000 0000000 00000025171 13612062727 032641 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.file; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; public class PathUtilsContentEqualsTest { @TempDir public File temporaryFolder; private String getName() { return this.getClass().getSimpleName(); } @Test public void testFileContentEquals() throws Exception { // Non-existent files final Path path1 = new File(temporaryFolder, getName()).toPath(); final Path path2 = new File(temporaryFolder, getName() + "2").toPath(); assertTrue(PathUtils.fileContentEquals(null, null)); assertFalse(PathUtils.fileContentEquals(null, path1)); assertFalse(PathUtils.fileContentEquals(path1, null)); // both don't exist assertTrue(PathUtils.fileContentEquals(path1, path1)); assertTrue(PathUtils.fileContentEquals(path1, path2)); assertTrue(PathUtils.fileContentEquals(path2, path2)); assertTrue(PathUtils.fileContentEquals(path2, path1)); // Directories try { PathUtils.fileContentEquals(temporaryFolder.toPath(), temporaryFolder.toPath()); fail("Comparing directories should fail with an IOException"); } catch (final IOException ioe) { // expected } // Different files final Path objFile1 = Paths.get(temporaryFolder.getAbsolutePath(), getName() + ".object"); objFile1.toFile().deleteOnExit(); PathUtils.copyFile(getClass().getResource("/java/lang/Object.class"), objFile1); final Path objFile1b = Paths.get(temporaryFolder.getAbsolutePath(), getName() + ".object2"); objFile1b.toFile().deleteOnExit(); PathUtils.copyFile(getClass().getResource("/java/lang/Object.class"), objFile1b); final Path objFile2 = Paths.get(temporaryFolder.getAbsolutePath(), getName() + ".collection"); objFile2.toFile().deleteOnExit(); PathUtils.copyFile(getClass().getResource("/java/util/Collection.class"), objFile2); assertFalse(PathUtils.fileContentEquals(objFile1, objFile2)); assertFalse(PathUtils.fileContentEquals(objFile1b, objFile2)); assertTrue(PathUtils.fileContentEquals(objFile1, objFile1b)); assertTrue(PathUtils.fileContentEquals(objFile1, objFile1)); assertTrue(PathUtils.fileContentEquals(objFile1b, objFile1b)); assertTrue(PathUtils.fileContentEquals(objFile2, objFile2)); // Equal files Files.createFile(path1); Files.createFile(path2); assertTrue(PathUtils.fileContentEquals(path1, path1)); assertTrue(PathUtils.fileContentEquals(path1, path2)); } @Test public void testDirectoryContentEquals() throws Exception { // Non-existent files final Path path1 = new File(temporaryFolder, getName()).toPath(); final Path path2 = new File(temporaryFolder, getName() + "2").toPath(); assertTrue(PathUtils.directoryContentEquals(null, null)); assertFalse(PathUtils.directoryContentEquals(null, path1)); assertFalse(PathUtils.directoryContentEquals(path1, null)); // both don't exist assertTrue(PathUtils.directoryContentEquals(path1, path1)); assertTrue(PathUtils.directoryContentEquals(path1, path2)); assertTrue(PathUtils.directoryContentEquals(path2, path2)); assertTrue(PathUtils.directoryContentEquals(path2, path1)); // Tree equals true tests { // Trees of files only that contain the same files. final Path dir1 = Paths.get("src/test/resources/dir-equals-tests/dir-equals-files-only/directory-files-only1"); final Path dir2 = Paths.get("src/test/resources/dir-equals-tests/dir-equals-files-only/directory-files-only2"); assertTrue(PathUtils.directoryContentEquals(dir1, dir2)); assertTrue(PathUtils.directoryContentEquals(dir2, dir2)); assertTrue(PathUtils.directoryContentEquals(dir1, dir1)); assertTrue(PathUtils.directoryContentEquals(dir2, dir2)); } { // Trees of directories containing other directories. final Path dir1 = Paths.get("src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/dir1"); final Path dir2 = Paths.get("src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/dir2"); assertTrue(PathUtils.directoryContentEquals(dir1, dir2)); assertTrue(PathUtils.directoryContentEquals(dir2, dir2)); assertTrue(PathUtils.directoryContentEquals(dir1, dir1)); assertTrue(PathUtils.directoryContentEquals(dir2, dir2)); } { // Trees of directories containing other directories and files. final Path dir1 = Paths.get("src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files1"); final Path dir2 = Paths.get("src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files1"); assertTrue(PathUtils.directoryContentEquals(dir1, dir2)); assertTrue(PathUtils.directoryContentEquals(dir2, dir2)); assertTrue(PathUtils.directoryContentEquals(dir1, dir1)); assertTrue(PathUtils.directoryContentEquals(dir2, dir2)); } // Tree equals false tests { final Path dir1 = Paths.get("src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files1/directory-files-only1"); final Path dir2 = Paths.get("src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files1/"); assertFalse(PathUtils.directoryContentEquals(dir1, dir2)); assertFalse(PathUtils.directoryContentEquals(dir2, dir1)); } { final Path dir1 = Paths.get("src/test/resources/dir-equals-tests/dir-equals-dirs-and-files"); final Path dir2 = Paths.get("src/test/resources/dir-equals-tests/dir-equals-dirs-then-files"); assertFalse(PathUtils.directoryContentEquals(dir1, dir2)); assertFalse(PathUtils.directoryContentEquals(dir2, dir1)); } } @Test public void testDirectoryAndFileContentEquals() throws Exception { // Non-existent files final Path path1 = new File(temporaryFolder, getName()).toPath(); final Path path2 = new File(temporaryFolder, getName() + "2").toPath(); assertTrue(PathUtils.directoryAndFileContentEquals(null, null)); assertFalse(PathUtils.directoryAndFileContentEquals(null, path1)); assertFalse(PathUtils.directoryAndFileContentEquals(path1, null)); // both don't exist assertTrue(PathUtils.directoryAndFileContentEquals(path1, path1)); assertTrue(PathUtils.directoryAndFileContentEquals(path1, path2)); assertTrue(PathUtils.directoryAndFileContentEquals(path2, path2)); assertTrue(PathUtils.directoryAndFileContentEquals(path2, path1)); // Tree equals true tests { // Trees of files only that contain the same files. final Path dir1 = Paths.get("src/test/resources/dir-equals-tests/dir-equals-files-only/directory-files-only1"); final Path dir2 = Paths.get("src/test/resources/dir-equals-tests/dir-equals-files-only/directory-files-only2"); assertTrue(PathUtils.directoryAndFileContentEquals(dir1, dir2)); assertTrue(PathUtils.directoryAndFileContentEquals(dir2, dir2)); assertTrue(PathUtils.directoryAndFileContentEquals(dir1, dir1)); assertTrue(PathUtils.directoryAndFileContentEquals(dir2, dir2)); } { // Trees of directories containing other directories. final Path dir1 = Paths.get("src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/dir1"); final Path dir2 = Paths.get("src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/dir2"); assertTrue(PathUtils.directoryAndFileContentEquals(dir1, dir2)); assertTrue(PathUtils.directoryAndFileContentEquals(dir2, dir2)); assertTrue(PathUtils.directoryAndFileContentEquals(dir1, dir1)); assertTrue(PathUtils.directoryAndFileContentEquals(dir2, dir2)); } { // Trees of directories containing other directories and files. final Path dir1 = Paths.get("src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files1"); final Path dir2 = Paths.get("src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files1"); assertTrue(PathUtils.directoryAndFileContentEquals(dir1, dir2)); assertTrue(PathUtils.directoryAndFileContentEquals(dir2, dir2)); assertTrue(PathUtils.directoryAndFileContentEquals(dir1, dir1)); assertTrue(PathUtils.directoryAndFileContentEquals(dir2, dir2)); } // Tree equals false tests { final Path dir1 = Paths.get("src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files1/directory-files-only1"); final Path dir2 = Paths.get("src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files1/"); assertFalse(PathUtils.directoryAndFileContentEquals(dir1, dir2)); assertFalse(PathUtils.directoryAndFileContentEquals(dir2, dir1)); } { final Path dir1 = Paths.get("src/test/resources/dir-equals-tests/dir-equals-dirs-and-files"); final Path dir2 = Paths.get("src/test/resources/dir-equals-tests/dir-equals-dirs-then-files"); assertFalse(PathUtils.directoryAndFileContentEquals(dir1, dir2)); assertFalse(PathUtils.directoryAndFileContentEquals(dir2, dir1)); } } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/file/PathUtilsCountingTest.java0100644 0000000 0000000 00000005207 13612062727 031640 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.file; import static org.apache.commons.io.file.CounterAssertions.assertCounts; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import org.apache.commons.io.file.Counters.PathCounters; import org.junit.jupiter.api.Test; /** * Tests {@link PathUtils}. */ public class PathUtilsCountingTest { /** * Tests an empty folder. */ @Test public void testCountEmptyFolder() throws IOException { final Path tempDir = Files.createTempDirectory(getClass().getCanonicalName()); try { final PathCounters pathCounts = PathUtils.countDirectory(tempDir); assertCounts(1, 0, 0, pathCounts); } finally { Files.deleteIfExists(tempDir); } } /** * Tests a directory with one file of size 0. */ @Test public void testCountFolders1FileSize0() throws IOException { final PathCounters pathCounts = PathUtils .countDirectory(Paths.get("src/test/resources/org/apache/commons/io/dirs-1-file-size-0")); assertCounts(1, 1, 0, pathCounts); } /** * Tests a directory with one file of size 1. */ @Test public void testCountFolders1FileSize1() throws IOException { final PathCounters visitor = PathUtils .countDirectory(Paths.get("src/test/resources/org/apache/commons/io/dirs-1-file-size-1")); assertCounts(1, 1, 1, visitor); } /** * Tests a directory with two subdirectories, each containing one file of size 1. */ @Test public void testCountFolders2FileSize2() throws IOException { final PathCounters pathCounts = PathUtils .countDirectory(Paths.get("src/test/resources/org/apache/commons/io/dirs-2-file-size-2")); assertCounts(3, 2, 2, pathCounts); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/file/PathUtilsDeleteDirectoryTest.java0100644 0000000 0000000 00000007707 13612062727 033150 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.file; import static org.apache.commons.io.file.CounterAssertions.assertCounts; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Tests {@link DeletingPathVisitor}. */ public class PathUtilsDeleteDirectoryTest { private Path tempDir; @AfterEach public void afterEach() throws IOException { // backstop if (Files.exists(tempDir) && PathUtils.isEmptyDirectory(tempDir)) { Files.deleteIfExists(tempDir); } } @BeforeEach public void beforeEach() throws IOException { tempDir = Files.createTempDirectory(getClass().getCanonicalName()); } /** * Tests a directory with one file of size 0. */ @Test public void testDeleteDirectory1FileSize0() throws IOException { PathUtils.copyDirectory(Paths.get("src/test/resources/org/apache/commons/io/dirs-1-file-size-0"), tempDir); assertCounts(1, 1, 0, PathUtils.deleteDirectory(tempDir)); // This will throw if not empty. Files.deleteIfExists(tempDir); } /** * Tests a directory with one file of size 0. */ private void testDeleteDirectory1FileSize0(final DeleteOption... options) throws IOException { // TODO Setup the test to use FileVisitOption. PathUtils.copyDirectory(Paths.get("src/test/resources/org/apache/commons/io/dirs-1-file-size-0"), tempDir); assertCounts(1, 1, 0, PathUtils.deleteDirectory(tempDir, options)); // This will throw if not empty. Files.deleteIfExists(tempDir); } @Test public void testDeleteDirectory1FileSize0NoOptions() throws IOException { testDeleteDirectory1FileSize0(PathUtils.EMPTY_DELETE_OPTION_ARRAY); } @Test public void testDeleteDirectory1FileSize0OverrideReadOnly() throws IOException { testDeleteDirectory1FileSize0(StandardDeleteOption.OVERRIDE_READ_ONLY); } /** * Tests a directory with one file of size 1. */ @Test public void testDeleteDirectory1FileSize1() throws IOException { PathUtils.copyDirectory(Paths.get("src/test/resources/org/apache/commons/io/dirs-1-file-size-1"), tempDir); assertCounts(1, 1, 1, PathUtils.deleteDirectory(tempDir)); // This will throw if not empty. Files.deleteIfExists(tempDir); } /** * Tests a directory with two subdirectories, each containing one file of size 1. */ @Test public void testDeleteDirectory2FileSize2() throws IOException { PathUtils.copyDirectory(Paths.get("src/test/resources/org/apache/commons/io/dirs-2-file-size-2"), tempDir); assertCounts(3, 2, 2, PathUtils.deleteDirectory(tempDir)); // This will throw if not empty. Files.deleteIfExists(tempDir); } /** * Tests an empty folder. */ @Test public void testDeleteEmptyDirectory() throws IOException { assertCounts(1, 0, 0, PathUtils.deleteDirectory(tempDir)); // This will throw if not empty. Files.deleteIfExists(tempDir); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/file/PathUtilsDeleteFileTest.java0100644 0000000 0000000 00000014156 13612062727 032057 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.file; import static org.apache.commons.io.file.CounterAssertions.assertCounts; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assumptions.assumeFalse; import java.io.IOException; import java.nio.file.Files; import java.nio.file.LinkOption; import java.nio.file.NoSuchFileException; import java.nio.file.Path; import java.nio.file.Paths; import org.apache.commons.io.file.Counters.PathCounters; import org.apache.commons.lang3.SystemUtils; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Tests {@link DeletingPathVisitor}. */ public class PathUtilsDeleteFileTest { private Path tempDir; @AfterEach public void afterEach() throws IOException { // backstop if (Files.exists(tempDir) && PathUtils.isEmptyDirectory(tempDir)) { Files.deleteIfExists(tempDir); } } @BeforeEach public void beforeEach() throws IOException { tempDir = Files.createTempDirectory(getClass().getCanonicalName()); } /** * Tests a directory with one file of size 0. */ @Test public void testDeleteFileDirectory1FileSize0() throws IOException { final String fileName = "file-size-0.bin"; PathUtils.copyFileToDirectory( Paths.get("src/test/resources/org/apache/commons/io/dirs-1-file-size-0/" + fileName), tempDir); assertCounts(0, 1, 0, PathUtils.deleteFile(tempDir.resolve(fileName))); // This will throw if not empty. Files.deleteIfExists(tempDir); } /** * Tests a directory with one file of size 1. */ @Test public void testDeleteFileDirectory1FileSize1() throws IOException { final String fileName = "file-size-1.bin"; PathUtils.copyFileToDirectory( Paths.get("src/test/resources/org/apache/commons/io/dirs-1-file-size-1/" + fileName), tempDir); assertCounts(0, 1, 1, PathUtils.deleteFile(tempDir.resolve(fileName))); // This will throw if not empty. Files.deleteIfExists(tempDir); } /** * Tests a file that does not exist. */ @Test public void testDeleteFileDoesNotExist() throws IOException { testDeleteFileEmpty(PathUtils.deleteFile(tempDir.resolve("file-does-not-exist.bin"))); // This will throw if not empty. Files.deleteIfExists(tempDir); } private void testDeleteFileEmpty(final PathCounters pathCounts) { assertCounts(0, 0, 0, pathCounts); } /** * Tests an empty folder. */ @Test public void testDeleteFileEmptyDirectory() throws IOException { Assertions.assertThrows(NoSuchFileException.class, () -> testDeleteFileEmpty(PathUtils.deleteFile(tempDir))); // This will throw if not empty. Files.deleteIfExists(tempDir); } /** * Tests a directory with one file of size 1. */ @Test public void testDeleteReadOnlyFileDirectory1FileSize1() throws IOException { final String fileName = "file-size-1.bin"; PathUtils.copyFileToDirectory( Paths.get("src/test/resources/org/apache/commons/io/dirs-1-file-size-1/" + fileName), tempDir); final Path resolved = tempDir.resolve(fileName); PathUtils.setReadOnly(resolved, true); if (SystemUtils.IS_OS_WINDOWS) { // Fails on Windows's Ubuntu subsystem. assertFalse(Files.isWritable(resolved)); assertThrows(IOException.class, () -> PathUtils.deleteFile(resolved)); } assertCounts(0, 1, 1, PathUtils.deleteFile(resolved, StandardDeleteOption.OVERRIDE_READ_ONLY)); // This will throw if not empty. Files.deleteIfExists(tempDir); } /** * Tests a directory with one file of size 1. */ @Test public void testSetReadOnlyFileDirectory1FileSize1() throws IOException { final String fileName = "file-size-1.bin"; PathUtils.copyFileToDirectory( Paths.get("src/test/resources/org/apache/commons/io/dirs-1-file-size-1/" + fileName), tempDir); final Path resolved = tempDir.resolve(fileName); PathUtils.setReadOnly(resolved, true); if (SystemUtils.IS_OS_WINDOWS) { // Fails on Windows's Ubuntu subsystem. assertFalse(Files.isWritable(resolved)); assertThrows(IOException.class, () -> PathUtils.deleteFile(resolved)); } PathUtils.setReadOnly(resolved, false); PathUtils.deleteFile(resolved); // This will throw if not empty. Files.deleteIfExists(tempDir); } @Test public void testDeleteBrokenLink() throws IOException { assumeFalse(SystemUtils.IS_OS_WINDOWS); final Path missingFile = tempDir.resolve("missing.txt"); final Path brokenLink = tempDir.resolve("broken.txt"); Files.createSymbolicLink(brokenLink, missingFile); assertTrue(Files.exists(brokenLink, LinkOption.NOFOLLOW_LINKS)); assertFalse(Files.exists(missingFile, LinkOption.NOFOLLOW_LINKS)); PathUtils.deleteFile(brokenLink); assertFalse(Files.exists(brokenLink, LinkOption.NOFOLLOW_LINKS), "Symbolic link not removed"); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/file/PathUtilsDeleteTest.java0100644 0000000 0000000 00000015356 13612062727 031262 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.file; import static org.apache.commons.io.file.CounterAssertions.assertCounts; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import org.apache.commons.io.FileUtils; import org.apache.commons.io.file.Counters.PathCounters; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Tests {@link DeletingPathVisitor}. */ public class PathUtilsDeleteTest { private Path tempDir; @AfterEach public void afterEach() throws IOException { // backstop if (Files.exists(tempDir) && PathUtils.isEmptyDirectory(tempDir)) { Files.deleteIfExists(tempDir); } } @BeforeEach public void beforeEach() throws IOException { tempDir = Files.createTempDirectory(getClass().getCanonicalName()); } @Test public void testDeleteDirectory1FileSize0() throws IOException { final String fileName = "file-size-0.bin"; FileUtils.copyFileToDirectory( Paths.get("src/test/resources/org/apache/commons/io/dirs-1-file-size-0/" + fileName).toFile(), tempDir.toFile()); assertCounts(0, 1, 0, PathUtils.delete(tempDir.resolve(fileName))); // This will throw if not empty. Files.deleteIfExists(tempDir); } private void testDeleteDirectory1FileSize0(final DeleteOption... options) throws IOException { final String fileName = "file-size-0.bin"; FileUtils.copyFileToDirectory( Paths.get("src/test/resources/org/apache/commons/io/dirs-1-file-size-0/" + fileName).toFile(), tempDir.toFile()); assertCounts(0, 1, 0, PathUtils.delete(tempDir.resolve(fileName), options)); // This will throw if not empty. Files.deleteIfExists(tempDir); } /** * Tests a directory with one file of size 0. */ @Test public void testDeleteDirectory1FileSize0ForceOff() throws IOException { testDeleteDirectory1FileSize0(); } /** * Tests a directory with one file of size 0. */ @Test public void testDeleteDirectory1FileSize0ForceOn() throws IOException { testDeleteDirectory1FileSize0(); } @Test public void testDeleteDirectory1FileSize0NoOption() throws IOException { testDeleteDirectory1FileSize0(PathUtils.EMPTY_DELETE_OPTION_ARRAY); } @Test public void testDeleteDirectory1FileSize0OverrideReadonly() throws IOException { testDeleteDirectory1FileSize0(StandardDeleteOption.OVERRIDE_READ_ONLY); } @Test public void testDeleteDirectory1FileSize1() throws IOException { final String fileName = "file-size-1.bin"; FileUtils.copyFileToDirectory( Paths.get("src/test/resources/org/apache/commons/io/dirs-1-file-size-1/" + fileName).toFile(), tempDir.toFile()); assertCounts(0, 1, 1, PathUtils.delete(tempDir.resolve(fileName))); // This will throw if not empty. Files.deleteIfExists(tempDir); } private void testDeleteDirectory1FileSize1(final DeleteOption... options) throws IOException { // TODO Setup the test to use LinkOption. final String fileName = "file-size-1.bin"; FileUtils.copyFileToDirectory( Paths.get("src/test/resources/org/apache/commons/io/dirs-1-file-size-1/" + fileName).toFile(), tempDir.toFile()); assertCounts(0, 1, 1, PathUtils.delete(tempDir.resolve(fileName), options)); // This will throw if not empty. Files.deleteIfExists(tempDir); } /** * Tests a directory with one file of size 1. */ @Test public void testDeleteDirectory1FileSize1ForceOff() throws IOException { testDeleteDirectory1FileSize1(); } /** * Tests a directory with one file of size 1. */ @Test public void testDeleteDirectory1FileSize1ForceOn() throws IOException { testDeleteDirectory1FileSize1(); } @Test public void testDeleteDirectory1FileSize1NoOption() throws IOException { testDeleteDirectory1FileSize1(PathUtils.EMPTY_DELETE_OPTION_ARRAY); } @Test public void testDeleteDirectory1FileSize1OverrideReadOnly() throws IOException { testDeleteDirectory1FileSize1(StandardDeleteOption.OVERRIDE_READ_ONLY); } /** * Tests an empty folder. */ @Test public void testDeleteEmptyDirectory() throws IOException { testDeleteEmptyDirectory(PathUtils.delete(tempDir)); // This will throw if not empty. Files.deleteIfExists(tempDir); } /** * Tests an empty folder. */ private void testDeleteEmptyDirectory(final DeleteOption... options) throws IOException { testDeleteEmptyDirectory(PathUtils.delete(tempDir, options)); // This will throw if not empty. Files.deleteIfExists(tempDir); } private void testDeleteEmptyDirectory(final PathCounters pathCounts) { assertCounts(1, 0, 0, pathCounts); } /** * Tests an empty folder. */ @Test public void testDeleteEmptyDirectoryForceOff() throws IOException { testDeleteEmptyDirectory(); } /** * Tests an empty folder. */ @Test public void testDeleteEmptyDirectoryForceOn() throws IOException { testDeleteEmptyDirectory(); } @Test public void testDeleteEmptyDirectoryNoOption() throws IOException { testDeleteEmptyDirectory(PathUtils.EMPTY_DELETE_OPTION_ARRAY); } @Test public void testDeleteEmptyDirectoryOverrideReadOnly() throws IOException { testDeleteEmptyDirectory(StandardDeleteOption.OVERRIDE_READ_ONLY); } /** * Tests a file that does not exist. */ @Test public void testDeleteFileDoesNotExist() throws IOException { assertCounts(0, 0, 0, PathUtils.deleteFile(tempDir.resolve("file-does-not-exist.bin"))); // This will throw if not empty. Files.deleteIfExists(tempDir); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/file/PathUtilsIsEmptyTest.java0100644 0000000 0000000 00000005046 13612062727 031445 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.file; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; /** * Tests {@link PathUtils}. */ public class PathUtilsIsEmptyTest { public static final Path DIR_SIZE_1 = Paths.get("src/test/resources/org/apache/commons/io/dirs-1-file-size-1"); private static final Path FILE_SIZE_0 = Paths .get("src/test/resources/org/apache/commons/io/dirs-1-file-size-0/file-size-0.bin"); private static final Path FILE_SIZE_1 = Paths .get("src/test/resources/org/apache/commons/io/dirs-1-file-size-1/file-size-1.bin"); @Test public void testIsEmpty() throws IOException { Assertions.assertTrue(PathUtils.isEmpty(FILE_SIZE_0)); Assertions.assertFalse(PathUtils.isEmpty(FILE_SIZE_1)); final Path tempDir = Files.createTempDirectory(getClass().getCanonicalName()); try { Assertions.assertTrue(PathUtils.isEmpty(tempDir)); } finally { Files.delete(tempDir); } Assertions.assertFalse(PathUtils.isEmpty(DIR_SIZE_1)); } @Test public void testIsEmptyDirectory() throws IOException { final Path tempDir = Files.createTempDirectory(getClass().getCanonicalName()); try { Assertions.assertTrue(PathUtils.isEmptyDirectory(tempDir)); } finally { Files.delete(tempDir); } Assertions.assertFalse(PathUtils.isEmptyDirectory(DIR_SIZE_1)); } @Test public void testisEmptyFile() throws IOException { Assertions.assertTrue(PathUtils.isEmptyFile(FILE_SIZE_0)); Assertions.assertFalse(PathUtils.isEmptyFile(FILE_SIZE_1)); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/file/PathUtilsTest.java0100644 0000000 0000000 00000021555 13612062727 030135 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.file; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; import java.net.URI; import java.nio.file.DirectoryStream; import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import org.apache.commons.io.filefilter.NameFileFilter; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; /** * Tests {@link PathUtils}. */ public class PathUtilsTest extends TestArguments { private static final String TEST_JAR_NAME = "test.jar"; private static final String TEST_JAR_PATH = "src/test/resources/org/apache/commons/io/test.jar"; private static final String PATH_FIXTURE = "NOTICE.txt"; /** * A temporary directory managed by JUnit. */ @TempDir public Path tempDir; private FileSystem openArchive(final Path p, final boolean createNew) throws IOException { final FileSystem archive; if (createNew) { final Map env = new HashMap<>(); env.put("create", "true"); final URI fileUri = p.toAbsolutePath().toUri(); final URI uri = URI.create("jar:" + fileUri.toASCIIString()); archive = FileSystems.newFileSystem(uri, env, null); } else { archive = FileSystems.newFileSystem(p, (ClassLoader) null); } return archive; } @Test public void testCopyDirectoryForDifferentFilesystemsWithAbsolutePath() throws IOException { final Path tempDir = Files.createTempDirectory(getClass().getCanonicalName()).toAbsolutePath(); try { final Path archivePath = Paths.get(TEST_JAR_PATH); try (final FileSystem archive = openArchive(archivePath, false)) { // relative jar -> absolute dir Path sourceDir = archive.getPath("dir1"); PathUtils.copyDirectory(sourceDir, tempDir); assertTrue(Files.exists(tempDir.resolve("f1"))); // absolute jar -> absolute dir sourceDir = archive.getPath("/next"); PathUtils.copyDirectory(sourceDir, tempDir); assertTrue(Files.exists(tempDir.resolve("dir"))); } } finally { PathUtils.deleteDirectory(tempDir); } } @Test public void testCopyDirectoryForDifferentFilesystemsWithAbsolutePathReverse() throws IOException { final Path tempDir = Files.createTempDirectory(getClass().getCanonicalName()); try { try (final FileSystem archive = openArchive(tempDir.resolve(TEST_JAR_NAME), true)) { // absolute dir -> relative jar Path targetDir = archive.getPath("target"); Files.createDirectory(targetDir); final Path sourceDir = Paths.get("src/test/resources/org/apache/commons/io/dirs-2-file-size-2") .toAbsolutePath(); PathUtils.copyDirectory(sourceDir, targetDir); assertTrue(Files.exists(targetDir.resolve("dirs-a-file-size-1"))); // absolute dir -> absolute jar targetDir = archive.getPath("/"); PathUtils.copyDirectory(sourceDir, targetDir); assertTrue(Files.exists(targetDir.resolve("dirs-a-file-size-1"))); } } finally { PathUtils.deleteDirectory(tempDir); } } @Test public void testCopyDirectoryForDifferentFilesystemsWithRelativePath() throws IOException { final Path tempDir = Files.createTempDirectory(getClass().getCanonicalName()); try { final Path archivePath = Paths.get(TEST_JAR_PATH); try (final FileSystem archive = openArchive(archivePath, false); final FileSystem targetArchive = openArchive(tempDir.resolve(TEST_JAR_NAME), true)) { final Path targetDir = targetArchive.getPath("targetDir"); Files.createDirectory(targetDir); // relative jar -> relative dir Path sourceDir = archive.getPath("next"); PathUtils.copyDirectory(sourceDir, targetDir); assertTrue(Files.exists(targetDir.resolve("dir"))); // absolute jar -> relative dir sourceDir = archive.getPath("/dir1"); PathUtils.copyDirectory(sourceDir, targetDir); assertTrue(Files.exists(targetDir.resolve("f1"))); } } finally { PathUtils.deleteDirectory(tempDir); } } @Test public void testCopyDirectoryForDifferentFilesystemsWithRelativePathReverse() throws IOException { final Path tempDir = Files.createTempDirectory(getClass().getCanonicalName()); try { try (final FileSystem archive = openArchive(tempDir.resolve(TEST_JAR_NAME), true)) { // relative dir -> relative jar Path targetDir = archive.getPath("target"); Files.createDirectory(targetDir); final Path sourceDir = Paths.get("src/test/resources/org/apache/commons/io/dirs-2-file-size-2"); PathUtils.copyDirectory(sourceDir, targetDir); assertTrue(Files.exists(targetDir.resolve("dirs-a-file-size-1"))); // relative dir -> absolute jar targetDir = archive.getPath("/"); PathUtils.copyDirectory(sourceDir, targetDir); assertTrue(Files.exists(targetDir.resolve("dirs-a-file-size-1"))); } } finally { PathUtils.deleteDirectory(tempDir); } } @Test public void testCopyFile() throws IOException { final Path tempDir = Files.createTempDirectory(getClass().getCanonicalName()); try { final Path sourceFile = Paths .get("src/test/resources/org/apache/commons/io/dirs-1-file-size-1/file-size-1.bin"); final Path targetFile = PathUtils.copyFileToDirectory(sourceFile, tempDir); assertTrue(Files.exists(targetFile)); assertEquals(Files.size(sourceFile), Files.size(targetFile)); } finally { PathUtils.deleteDirectory(tempDir); } } @Test public void testCreateDirectoriesAlreadyExists() throws IOException { assertEquals(tempDir.getParent(), PathUtils.createParentDirectories(tempDir)); } @Test public void testCreateDirectoriesNew() throws IOException { assertEquals(tempDir, PathUtils.createParentDirectories(tempDir.resolve("child"))); } @Test public void testIsDirectory() throws IOException { assertFalse(PathUtils.isDirectory(null)); assertTrue(PathUtils.isDirectory(tempDir)); final Path testFile1 = Files.createTempFile(tempDir, "prefix", null); assertFalse(PathUtils.isDirectory(testFile1)); final Path tempDir = Files.createTempDirectory(getClass().getCanonicalName()); Files.delete(tempDir); assertFalse(PathUtils.isDirectory(tempDir)); } @Test public void testIsRegularFile() throws IOException { assertFalse(PathUtils.isRegularFile(null)); assertFalse(PathUtils.isRegularFile(tempDir)); final Path testFile1 = Files.createTempFile(tempDir, "prefix", null); assertTrue(PathUtils.isRegularFile(testFile1)); Files.delete(testFile1); assertFalse(PathUtils.isRegularFile(testFile1)); } @Test public void testNewDirectoryStream() throws Exception { final PathFilter pathFilter = new NameFileFilter(PATH_FIXTURE); try (final DirectoryStream stream = PathUtils.newDirectoryStream(PathUtils.current(), pathFilter)) { final Iterator iterator = stream.iterator(); final Path path = iterator.next(); assertEquals(PATH_FIXTURE, path.getFileName().toString()); assertFalse(iterator.hasNext()); } } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/file/PathUtilsVisitorTest.java0100644 0000000 0000000 00000010535 13612062727 031511 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.file; import static org.apache.commons.io.file.CounterAssertions.assertCounts; import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.function.Supplier; import java.util.stream.Stream; import org.apache.commons.io.filefilter.AndFileFilter; import org.apache.commons.io.filefilter.DirectoryFileFilter; import org.apache.commons.io.filefilter.EmptyFileFilter; import org.apache.commons.io.filefilter.PathVisitorFileFilter; import org.junit.jupiter.api.io.TempDir; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; /** * Tests {@link PathUtils}. */ public class PathUtilsVisitorTest { static Stream testParameters() { return AccumulatorPathVisitorTest.testParameters(); } @TempDir File tempDirFile; /** * Tests an empty folder. */ @ParameterizedTest @MethodSource("testParameters") public void testCountEmptyFolder(final Supplier supplier) throws IOException { final Path tempDir = tempDirFile.toPath(); final CountingPathVisitor countingPathVisitor = CountingPathVisitor.withLongCounters(); final PathVisitorFileFilter countingFileFilter = new PathVisitorFileFilter(countingPathVisitor); Files.walkFileTree(tempDir, new AndFileFilter(countingFileFilter, DirectoryFileFilter.INSTANCE, EmptyFileFilter.EMPTY)); assertCounts(1, 0, 0, countingPathVisitor.getPathCounters()); } /** * Tests a directory with one file of size 0. */ @ParameterizedTest @MethodSource("testParameters") public void testCountFolders1FileSize0(final Supplier supplier) throws IOException { final CountingPathVisitor countingPathVisitor = CountingPathVisitor.withLongCounters(); final PathVisitorFileFilter countingFileFilter = new PathVisitorFileFilter(countingPathVisitor); Files.walkFileTree(Paths.get("src/test/resources/org/apache/commons/io/dirs-1-file-size-0"), countingFileFilter); assertCounts(1, 1, 0, countingPathVisitor.getPathCounters()); } /** * Tests a directory with one file of size 1. */ @ParameterizedTest @MethodSource("testParameters") public void testCountFolders1FileSize1(final Supplier supplier) throws IOException { final CountingPathVisitor countingPathVisitor = CountingPathVisitor.withLongCounters(); final PathVisitorFileFilter countingFileFilter = new PathVisitorFileFilter(countingPathVisitor); Files.walkFileTree(Paths.get("src/test/resources/org/apache/commons/io/dirs-1-file-size-1"), countingFileFilter); assertCounts(1, 1, 1, countingPathVisitor.getPathCounters()); } /** * Tests a directory with two subdirectories, each containing one file of size 1. */ @ParameterizedTest @MethodSource("testParameters") public void testCountFolders2FileSize2(final Supplier supplier) throws IOException { final CountingPathVisitor countingPathVisitor = CountingPathVisitor.withLongCounters(); final PathVisitorFileFilter countingFileFilter = new PathVisitorFileFilter(countingPathVisitor); Files.walkFileTree(Paths.get("src/test/resources/org/apache/commons/io/dirs-2-file-size-2"), countingFileFilter); assertCounts(3, 2, 2, countingPathVisitor.getPathCounters()); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/file/TestArguments.java0100644 0000000 0000000 00000004310 13612062727 030153 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.file; import java.util.stream.Stream; import org.junit.jupiter.params.provider.Arguments; class TestArguments { static Stream cleaningPathVisitors() { // @formatter:off return Stream.of( Arguments.of(CleaningPathVisitor.withBigIntegerCounters()), Arguments.of(CleaningPathVisitor.withLongCounters())); // @formatter:on } static Stream countingPathVisitors() { // @formatter:off return Stream.of( Arguments.of(CountingPathVisitor.withBigIntegerCounters()), Arguments.of(CountingPathVisitor.withLongCounters())); // @formatter:on } static Stream deletingPathVisitors() { // @formatter:off return Stream.of( Arguments.of(DeletingPathVisitor.withBigIntegerCounters()), Arguments.of(DeletingPathVisitor.withLongCounters())); // @formatter:on } static Stream numberCounters() { // @formatter:off return Stream.of( Arguments.of(Counters.longCounter()), Arguments.of(Counters.bigIntegerCounter())); // @formatter:on } static Stream pathCounters() { // @formatter:off return Stream.of( Arguments.of(Counters.longPathCounters()), Arguments.of(Counters.bigIntegerPathCounters())); // @formatter:on } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/file/spi/FileSystemProvidersTest.java0100644 0000000 0000000 00000004764 13612062727 033000 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.file.spi; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.nio.file.Paths; import java.nio.file.spi.FileSystemProvider; import java.util.List; import org.junit.jupiter.api.Test; public class FileSystemProvidersTest { private static final String FILE_PATH = "file:///foo.txt"; @Test public void testGetFileSystemProvider_all() throws URISyntaxException { final List installedProviders = FileSystemProvider.installedProviders(); for (final FileSystemProvider fileSystemProvider : installedProviders) { final String scheme = fileSystemProvider.getScheme(); final URI uri = new URI(scheme, "ssp", "fragment"); assertEquals(scheme, FileSystemProviders.installed().getFileSystemProvider(uri).getScheme()); } } @Test public void testGetFileSystemProvider_filePath() { assertNotNull(FileSystemProviders.getFileSystemProvider(Paths.get(URI.create(FILE_PATH)))); } @Test public void testGetFileSystemProvider_fileScheme() { assertNotNull(FileSystemProviders.installed().getFileSystemProvider("file")); } @Test public void testGetFileSystemProvider_fileURI() { assertNotNull(FileSystemProviders.installed().getFileSystemProvider(URI.create(FILE_PATH))); } @Test public void testGetFileSystemProvider_fileURL() throws MalformedURLException { assertNotNull(FileSystemProviders.installed().getFileSystemProvider(new URL(FILE_PATH))); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/filefilter/AgeFileFilterTest.java0100644 0000000 0000000 00000010407 13612062727 032062 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.filefilter; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Collections; import org.apache.commons.io.file.AccumulatorPathVisitor; import org.apache.commons.io.file.CounterAssertions; import org.apache.commons.io.file.Counters; import org.junit.jupiter.api.Test; /** * Tests {@link AgeFileFilter}. */ public class AgeFileFilterTest { /** * Javadoc example. * * System.out calls are commented out here but not in the Javadoc. */ @Test public void testJavadocExampleUsingIo() { final File dir = new File("."); // We are interested in files older than one day final long cutoffMillis = System.currentTimeMillis(); final String[] files = dir.list(new AgeFileFilter(cutoffMillis)); for (final String file : files) { // System.out.println(files[i]); } // End of Javadoc example assertTrue(files.length > 0); } /** * Javadoc example. * * System.out calls are commented out here but not in the Javadoc. */ @Test public void testJavadocExampleUsingNio() throws IOException { final Path dir = Paths.get(""); // We are interested in files older than one day final long cutoffMillis = System.currentTimeMillis(); final AccumulatorPathVisitor visitor = AccumulatorPathVisitor.withLongCounters(new AgeFileFilter(cutoffMillis), TrueFileFilter.INSTANCE); // // Walk one dir Files.walkFileTree(dir, Collections.emptySet(), 1, visitor); // System.out.println(visitor.getPathCounters()); // System.out.println(visitor.getFileList()); // visitor.getPathCounters().reset(); // // Walk dir tree Files.walkFileTree(dir, visitor); // System.out.println(visitor.getPathCounters()); // System.out.println(visitor.getDirList()); // System.out.println(visitor.getFileList()); // // End of Javadoc example assertTrue(visitor.getPathCounters().getFileCounter().get() > 0); assertTrue(visitor.getPathCounters().getDirectoryCounter().get() > 0); assertTrue(visitor.getPathCounters().getByteCounter().get() > 0); // We counted and accumulated assertFalse(visitor.getDirList().isEmpty()); assertFalse(visitor.getFileList().isEmpty()); // assertNotEquals(Counters.noopPathCounters(), visitor.getPathCounters()); visitor.getPathCounters().reset(); CounterAssertions.assertZeroCounters(visitor.getPathCounters()); } @Test public void testNoCounting() throws IOException { final Path dir = Paths.get(""); final long cutoffMillis = System.currentTimeMillis(); final AccumulatorPathVisitor visitor = new AccumulatorPathVisitor(Counters.noopPathCounters(), new AgeFileFilter(cutoffMillis), TrueFileFilter.INSTANCE); Files.walkFileTree(dir, Collections.emptySet(), 1, visitor); // CounterAssertions.assertZeroCounters(visitor.getPathCounters()); // We did not count, but we still accumulated assertFalse(visitor.getDirList().isEmpty()); assertFalse(visitor.getFileList().isEmpty()); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/filefilter/AndFileFilterTestCase.java0100644 0000000 0000000 00000024775 13612062727 032701 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.filefilter; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; /** * Tests {@link AndFileFilter}. */ public class AndFileFilterTestCase extends ConditionalFileFilterAbstractTestCase { private static final String DEFAULT_WORKING_PATH = "./AndFileFilterTestCase/"; private static final String WORKING_PATH_NAME_PROPERTY_KEY = AndFileFilterTestCase.class.getName() + ".workingDirectory"; private List> testFilters; private List testTrueResults; private List testFalseResults; private List testFileResults; private List testFilenameResults; @Override protected IOFileFilter buildFilterUsingAdd(final List filters) { final AndFileFilter filter = new AndFileFilter(); for (final IOFileFilter filter1 : filters) { filter.addFileFilter(filter1); } return filter; } @Override protected IOFileFilter buildFilterUsingConstructor(final List filters) { return new AndFileFilter(filters); } @Override protected ConditionalFileFilter getConditionalFileFilter() { return new AndFileFilter(); } @Override protected String getDefaultWorkingPath() { return DEFAULT_WORKING_PATH; } @Override protected List getFalseResults() { return this.testFalseResults; } @Override protected List getFileResults() { return this.testFileResults; } @Override protected List getFilenameResults() { return this.testFilenameResults; } @Override protected List> getTestFilters() { return this.testFilters; } @Override protected List getTrueResults() { return this.testTrueResults; } @Override protected String getWorkingPathNamePropertyKey() { return WORKING_PATH_NAME_PROPERTY_KEY; } @BeforeEach public void setUpTestFilters() { // filters //tests this.testFilters = new ArrayList<>(); this.testTrueResults = new ArrayList<>(); this.testFalseResults = new ArrayList<>(); this.testFileResults = new ArrayList<>(); this.testFilenameResults = new ArrayList<>(); // test 0 - add empty elements { testFilters.add(0, null); testTrueResults.add(0, null); testFalseResults.add(0, null); testFileResults.add(0, null); testFilenameResults.add(0, null); } // test 1 - Test conditional and with all filters returning true { // test 1 filters final List filters = new ArrayList<>(); filters.add(trueFilters[1]); filters.add(trueFilters[2]); filters.add(trueFilters[3]); // test 1 true results final boolean[] trueResults = {true, true, true}; // test 1 false results final boolean[] falseResults = {false, false, false}; testFilters.add(1, filters); testTrueResults.add(1, trueResults); testFalseResults.add(1, falseResults); testFileResults.add(1, Boolean.TRUE); testFilenameResults.add(1, Boolean.TRUE); } // test 2 - Test conditional and with first filter returning false { // test 2 filters final List filters = new ArrayList<>(); filters.add(falseFilters[1]); filters.add(trueFilters[1]); filters.add(trueFilters[2]); filters.add(trueFilters[3]); filters.add(falseFilters[2]); filters.add(falseFilters[3]); // test 2 true results final boolean[] trueResults = {false, false, false}; // test 2 false results final boolean[] falseResults = {true, false, false}; testFilters.add(2, filters); testTrueResults.add(2, trueResults); testFalseResults.add(2, falseResults); testFileResults.add(2, Boolean.FALSE); testFilenameResults.add(2, Boolean.FALSE); } // test 3 - Test conditional and with second filter returning false { // test 3 filters final List filters = new ArrayList<>(); filters.add(trueFilters[1]); filters.add(falseFilters[1]); filters.add(trueFilters[2]); filters.add(trueFilters[3]); filters.add(falseFilters[2]); filters.add(falseFilters[3]); // test 3 true results final boolean[] trueResults = {true, false, false}; // test 3 false results final boolean[] falseResults = {true, false, false}; testFilters.add(3, filters); testTrueResults.add(3, trueResults); testFalseResults.add(3, falseResults); testFileResults.add(3, Boolean.FALSE); testFilenameResults.add(3, Boolean.FALSE); } // test 4 - Test conditional and with third filter returning false { // test 4 filters final List filters = new ArrayList<>(); filters.add(trueFilters[1]); filters.add(trueFilters[2]); filters.add(falseFilters[1]); filters.add(trueFilters[3]); filters.add(falseFilters[2]); filters.add(falseFilters[3]); // test 4 true results final boolean[] trueResults = {true, true, false}; // test 4 false results final boolean[] falseResults = {true, false, false}; testFilters.add(4, filters); testTrueResults.add(4, trueResults); testFalseResults.add(4, falseResults); testFileResults.add(4, Boolean.FALSE); testFilenameResults.add(4, Boolean.FALSE); } // test 5 - Test conditional and with first and third filters returning false { // test 5 filters final List filters = new ArrayList<>(); filters.add(falseFilters[1]); filters.add(trueFilters[1]); filters.add(falseFilters[2]); filters.add(falseFilters[3]); filters.add(trueFilters[2]); filters.add(trueFilters[3]); // test 5 true results final boolean[] trueResults = {false, false, false}; // test 5 false results final boolean[] falseResults = {true, false, false}; testFilters.add(5, filters); testTrueResults.add(5, trueResults); testFalseResults.add(5, falseResults); testFileResults.add(5, Boolean.FALSE); testFilenameResults.add(5, Boolean.FALSE); } // test 6 - Test conditional and with second and third filters returning false { final List filters = new ArrayList<>(); filters.add(trueFilters[1]); filters.add(falseFilters[1]); filters.add(falseFilters[2]); filters.add(trueFilters[2]); filters.add(trueFilters[3]); filters.add(falseFilters[3]); // test 6 true results final boolean[] trueResults = {true, false, false}; // test 6 false results final boolean[] falseResults = {true, false, false}; testFilters.add(6, filters); testTrueResults.add(6, trueResults); testFalseResults.add(6, falseResults); testFileResults.add(6, Boolean.FALSE); testFilenameResults.add(6, Boolean.FALSE); } // test 7 - Test conditional and with first and second filters returning false { final List filters = new ArrayList<>(); filters.add(falseFilters[1]); filters.add(falseFilters[2]); filters.add(trueFilters[3]); filters.add(falseFilters[3]); filters.add(trueFilters[2]); filters.add(trueFilters[3]); // test 7 true results final boolean[] trueResults = {false, false, false}; // test 7 false results final boolean[] falseResults = {true, false, false}; testFilters.add(7, filters); testTrueResults.add(7, trueResults); testFalseResults.add(7, falseResults); testFileResults.add(7, Boolean.FALSE); testFilenameResults.add(7, Boolean.FALSE); } // test 8 - Test conditional and with fourth filters returning false { final List filters = new ArrayList<>(); filters.add(trueFilters[1]); filters.add(trueFilters[2]); filters.add(trueFilters[3]); filters.add(falseFilters[1]); // test 8 true results final boolean[] trueResults = {true, true, true}; // test 8 false results final boolean[] falseResults = {true, false, false}; testFilters.add(8, filters); testTrueResults.add(8, trueResults); testFalseResults.add(8, falseResults); testFileResults.add(8, Boolean.FALSE); testFilenameResults.add(8, Boolean.FALSE); } // test 9 - Test conditional and with all filters returning false { final List filters = new ArrayList<>(); filters.add(falseFilters[1]); filters.add(falseFilters[2]); filters.add(falseFilters[3]); // test 9 true results final boolean[] trueResults = {false, false, false}; // test 9 false results final boolean[] falseResults = {true, false, false}; testFilters.add(9, filters); testTrueResults.add(9, trueResults); testFalseResults.add(9, falseResults); testFileResults.add(9, Boolean.FALSE); testFilenameResults.add(9, Boolean.FALSE); } } @Test public void setTestFiltersClearsOld() { // test that new filters correctly clear old filters final List simpleEmptyFileFilter = Collections.singletonList(EmptyFileFilter.EMPTY); final AndFileFilter andFileFilter = new AndFileFilter(simpleEmptyFileFilter); // make sure the filters at this point are the same assertEquals(simpleEmptyFileFilter, andFileFilter.getFileFilters()); final List simpleNonEmptyFilter = Collections.singletonList(EmptyFileFilter.NOT_EMPTY); // when calling the setter the filters should reference the new filters andFileFilter.setFileFilters(simpleNonEmptyFilter); assertEquals(simpleNonEmptyFilter, andFileFilter.getFileFilters()); } } ././@LongLink0100644 0000000 0000000 00000000160 13612062727 011636 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/java/org/apache/commons/io/filefilter/ConditionalFileFilterAbstractTestCase.javacommons-io-2.11.0-src/src/test/java/org/apache/commons/io/filefilter/ConditionalFileFilterAbstractTe0100644 0000000 0000000 00000020266 13612062727 034032 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.filefilter; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.File; import java.util.ArrayList; import java.util.List; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; public abstract class ConditionalFileFilterAbstractTestCase extends IOFileFilterAbstractTestCase { private static final String TEST_FILE_NAME_PREFIX = "TestFile"; private static final String TEST_FILE_TYPE = ".tst"; protected TesterTrueFileFilter[] trueFilters; protected TesterFalseFileFilter[] falseFilters; private File file; private File workingPath; @BeforeEach public void setUp() { this.workingPath = determineWorkingDirectoryPath(this.getWorkingPathNamePropertyKey(), this.getDefaultWorkingPath()); this.file = new File(this.workingPath, TEST_FILE_NAME_PREFIX + 1 + TEST_FILE_TYPE); this.trueFilters = new TesterTrueFileFilter[4]; this.falseFilters = new TesterFalseFileFilter[4]; this.trueFilters[1] = new TesterTrueFileFilter(); this.trueFilters[2] = new TesterTrueFileFilter(); this.trueFilters[3] = new TesterTrueFileFilter(); this.falseFilters[1] = new TesterFalseFileFilter(); this.falseFilters[2] = new TesterFalseFileFilter(); this.falseFilters[3] = new TesterFalseFileFilter(); } @Test public void testAdd() { final List filters = new ArrayList<>(); final ConditionalFileFilter fileFilter = this.getConditionalFileFilter(); filters.add(new TesterTrueFileFilter()); filters.add(new TesterTrueFileFilter()); filters.add(new TesterTrueFileFilter()); filters.add(new TesterTrueFileFilter()); for (int i = 0; i < filters.size(); i++) { assertEquals(i, fileFilter.getFileFilters().size(), "file filters count: "); fileFilter.addFileFilter(filters.get(i)); assertEquals(i + 1, fileFilter.getFileFilters().size(), "file filters count: "); } for (final IOFileFilter filter : fileFilter.getFileFilters()) { assertTrue(filters.contains(filter), "found file filter"); } assertEquals(filters.size(), fileFilter.getFileFilters().size(), "file filters count"); } @Test public void testRemove() { final List filters = new ArrayList<>(); final ConditionalFileFilter fileFilter = this.getConditionalFileFilter(); filters.add(new TesterTrueFileFilter()); filters.add(new TesterTrueFileFilter()); filters.add(new TesterTrueFileFilter()); filters.add(new TesterTrueFileFilter()); for (final TesterTrueFileFilter filter : filters) { fileFilter.removeFileFilter(filter); assertFalse(fileFilter.getFileFilters().contains(filter), "file filter removed"); } assertEquals(0, fileFilter.getFileFilters().size(), "file filters count"); } @Test public void testNoFilters() { final ConditionalFileFilter fileFilter = this.getConditionalFileFilter(); final File file = new File(this.workingPath, TEST_FILE_NAME_PREFIX + 1 + TEST_FILE_TYPE); assertFileFiltering(1, (IOFileFilter) fileFilter, file, false); assertFilenameFiltering(1, (IOFileFilter) fileFilter, file, false); } @Test public void testFilterBuiltUsingConstructor() { final List> testFilters = this.getTestFilters(); final List testTrueResults = this.getTrueResults(); final List testFalseResults = this.getFalseResults(); final List testFileResults = this.getFileResults(); final List testFilenameResults = this.getFilenameResults(); for (int i = 1; i < testFilters.size(); i++) { final List filters = testFilters.get(i); final boolean[] trueResults = testTrueResults.get(i); final boolean[] falseResults = testFalseResults.get(i); final boolean fileResults = testFileResults.get(i); final boolean filenameResults = testFilenameResults.get(i); // Test conditional AND filter created by passing filters to the constructor final IOFileFilter filter = this.buildFilterUsingConstructor(filters); // Test as a file filter resetTrueFilters(this.trueFilters); resetFalseFilters(this.falseFilters); assertFileFiltering(i, filter, this.file, fileResults); assertTrueFiltersInvoked(i, trueFilters, trueResults); assertFalseFiltersInvoked(i, falseFilters, falseResults); // Test as a filename filter resetTrueFilters(this.trueFilters); resetFalseFilters(this.falseFilters); assertFilenameFiltering(i, filter, this.file, filenameResults); assertTrueFiltersInvoked(i, trueFilters, trueResults); assertFalseFiltersInvoked(i, falseFilters, falseResults); } } @Test public void testFilterBuiltUsingAdd() { final List> testFilters = this.getTestFilters(); final List testTrueResults = this.getTrueResults(); final List testFalseResults = this.getFalseResults(); final List testFileResults = this.getFileResults(); final List testFilenameResults = this.getFilenameResults(); for (int i = 1; i < testFilters.size(); i++) { final List filters = testFilters.get(i); final boolean[] trueResults = testTrueResults.get(i); final boolean[] falseResults = testFalseResults.get(i); final boolean fileResults = testFileResults.get(i); final boolean filenameResults = testFilenameResults.get(i); // Test conditional AND filter created by passing filters to the constructor final IOFileFilter filter = this.buildFilterUsingAdd(filters); // Test as a file filter resetTrueFilters(this.trueFilters); resetFalseFilters(this.falseFilters); assertFileFiltering(i, filter, this.file, fileResults); assertTrueFiltersInvoked(i, trueFilters, trueResults); assertFalseFiltersInvoked(i, falseFilters, falseResults); // Test as a filename filter resetTrueFilters(this.trueFilters); resetFalseFilters(this.falseFilters); assertFilenameFiltering(i, filter, this.file, filenameResults); assertTrueFiltersInvoked(i, trueFilters, trueResults); assertFalseFiltersInvoked(i, falseFilters, falseResults); } } protected abstract ConditionalFileFilter getConditionalFileFilter(); protected abstract IOFileFilter buildFilterUsingAdd(List filters); protected abstract IOFileFilter buildFilterUsingConstructor(List filters); protected abstract List> getTestFilters(); protected abstract List getTrueResults(); protected abstract List getFalseResults(); protected abstract List getFileResults(); protected abstract List getFilenameResults(); protected abstract String getWorkingPathNamePropertyKey(); protected abstract String getDefaultWorkingPath(); } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/filefilter/DirectoryFileFilterTest.java0100644 0000000 0000000 00000006712 13612062727 033336 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.filefilter; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Collections; import org.apache.commons.io.file.AccumulatorPathVisitor; import org.apache.commons.io.file.CounterAssertions; import org.apache.commons.io.file.Counters; import org.junit.jupiter.api.Test; /** * Tests {@link DirectoryFileFilter}. */ public class DirectoryFileFilterTest { /** * Javadoc example. * * System.out calls are commented out here but not in the Javadoc. */ @Test public void testJavadocExampleUsingIo() { final File dir = new File("."); final String[] files = dir.list(DirectoryFileFilter.INSTANCE); for (final String file : files) { // System.out.println(files[i]); } // End of Javadoc example assertTrue(files.length > 0); } /** * Javadoc example. * * System.out calls are commented out here but not in the Javadoc. */ @Test public void testJavadocExampleUsingNio() throws IOException { final Path dir = Paths.get(""); final AccumulatorPathVisitor visitor = AccumulatorPathVisitor.withLongCounters(DirectoryFileFilter.INSTANCE, TrueFileFilter.INSTANCE); // // Walk one dir Files.walkFileTree(dir, Collections.emptySet(), 1, visitor); // System.out.println(visitor.getPathCounters()); // System.out.println(visitor.getFileList()); // visitor.getPathCounters().reset(); // // Walk dir tree Files.walkFileTree(dir, visitor); // System.out.println(visitor.getPathCounters()); // System.out.println(visitor.getDirList()); // System.out.println(visitor.getFileList()); // // End of Javadoc example assertEquals(0, visitor.getPathCounters().getFileCounter().get()); assertTrue(visitor.getPathCounters().getDirectoryCounter().get() > 0); assertEquals(0, visitor.getPathCounters().getByteCounter().get()); // We counted and accumulated assertFalse(visitor.getDirList().isEmpty()); assertFalse(visitor.getFileList().isEmpty()); // assertNotEquals(Counters.noopPathCounters(), visitor.getPathCounters()); visitor.getPathCounters().reset(); CounterAssertions.assertZeroCounters(visitor.getPathCounters()); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/filefilter/FileFilterTestCase.java0100644 0000000 0000000 00000242466 13612062727 032255 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.filefilter; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.Assumptions.assumeTrue; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileFilter; import java.io.FilenameFilter; import java.io.IOException; import java.io.OutputStream; import java.nio.charset.StandardCharsets; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Set; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOCase; import org.apache.commons.io.IOUtils; import org.apache.commons.io.file.PathUtils; import org.apache.commons.io.test.TestUtils; import org.apache.commons.lang3.SystemUtils; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; /** * Used to test FileFilterUtils. */ public class FileFilterTestCase { /** * The subversion directory name. */ static final String SVN_DIR_NAME = ".svn"; private static final boolean WINDOWS = File.separatorChar == '\\'; @TempDir public File temporaryFolder; void assertFiltering(final IOFileFilter filter, final File file, final boolean expected) { // Note. This only tests the (File, String) version if the parent of // the File passed in is not null assertEquals(expected, filter.accept(file), "Filter(File) " + filter.getClass().getName() + " not " + expected + " for " + file); if (file != null && file.getParentFile() != null) { assertEquals(expected, filter.accept(file.getParentFile(), file.getName()), "Filter(File, String) " + filter.getClass().getName() + " not " + expected + " for " + file); } else if (file == null) { assertEquals(expected, filter.accept(file), "Filter(File, String) " + filter.getClass().getName() + " not " + expected + " for null"); } assertNotNull(filter.toString()); } void assertFiltering(final IOFileFilter filter, final Path path, final boolean expected) { // Note. This only tests the (Path, Path) version if the parent of // the File passed in is not null final FileVisitResult expectedFileVisitResult = AbstractFileFilter.toFileVisitResult(expected, path); assertEquals(expectedFileVisitResult, filter.accept(path, null), "Filter(Path) " + filter.getClass().getName() + " not " + expectedFileVisitResult + " for " + path); if (path != null && path.getParent() != null) { assertEquals(expectedFileVisitResult, filter.accept(path, null), "Filter(Path, Path) " + filter.getClass().getName() + " not " + expectedFileVisitResult + " for " + path); } else if (path == null) { assertEquals(expectedFileVisitResult, filter.accept(path, null), "Filter(Path, Path) " + filter.getClass().getName() + " not " + expectedFileVisitResult + " for null"); } assertNotNull(filter.toString()); } private void assertFooBarFileFiltering(IOFileFilter filter) { assertFiltering(filter, new File("foo"), true); assertFiltering(filter, new File("foo"), true); assertFiltering(filter, new File("bar"), true); assertFiltering(filter, new File("fred"), false); assertFiltering(filter, new File("foo").toPath(), true); assertFiltering(filter, new File("foo").toPath(), true); assertFiltering(filter, new File("bar").toPath(), true); assertFiltering(filter, new File("fred").toPath(), false); filter = new NameFileFilter(new String[] {"foo", "bar"}, IOCase.SENSITIVE); assertFiltering(filter, new File("foo"), true); assertFiltering(filter, new File("bar"), true); assertFiltering(filter, new File("FOO"), false); assertFiltering(filter, new File("BAR"), false); assertFiltering(filter, new File("foo").toPath(), true); assertFiltering(filter, new File("bar").toPath(), true); assertFiltering(filter, new File("FOO").toPath(), false); assertFiltering(filter, new File("BAR").toPath(), false); filter = new NameFileFilter(new String[] {"foo", "bar"}, IOCase.INSENSITIVE); assertFiltering(filter, new File("foo"), true); assertFiltering(filter, new File("bar"), true); assertFiltering(filter, new File("FOO"), true); assertFiltering(filter, new File("BAR"), true); assertFiltering(filter, new File("foo").toPath(), true); assertFiltering(filter, new File("bar").toPath(), true); assertFiltering(filter, new File("FOO").toPath(), true); assertFiltering(filter, new File("BAR").toPath(), true); filter = new NameFileFilter(new String[] {"foo", "bar"}, IOCase.SYSTEM); assertFiltering(filter, new File("foo"), true); assertFiltering(filter, new File("bar"), true); assertFiltering(filter, new File("FOO"), WINDOWS); assertFiltering(filter, new File("BAR"), WINDOWS); assertFiltering(filter, new File("foo").toPath(), true); assertFiltering(filter, new File("bar").toPath(), true); assertFiltering(filter, new File("FOO").toPath(), WINDOWS); assertFiltering(filter, new File("BAR").toPath(), WINDOWS); filter = new NameFileFilter(new String[] {"foo", "bar"}, null); assertFiltering(filter, new File("foo"), true); assertFiltering(filter, new File("bar"), true); assertFiltering(filter, new File("FOO"), false); assertFiltering(filter, new File("BAR"), false); assertFiltering(filter, new File("foo").toPath(), true); assertFiltering(filter, new File("bar").toPath(), true); assertFiltering(filter, new File("FOO").toPath(), false); assertFiltering(filter, new File("BAR").toPath(), false); // repeat for a List final java.util.ArrayList list = new java.util.ArrayList<>(); list.add("foo"); list.add("bar"); filter = new NameFileFilter(list); assertFiltering(filter, new File("foo"), true); assertFiltering(filter, new File("bar"), true); assertFiltering(filter, new File("fred"), false); assertFiltering(filter, new File("foo").toPath(), true); assertFiltering(filter, new File("bar").toPath(), true); assertFiltering(filter, new File("fred").toPath(), false); filter = new NameFileFilter("foo"); assertFiltering(filter, new File("foo"), true); assertFiltering(filter, new File("FOO"), false); // case-sensitive assertFiltering(filter, new File("barfoo"), false); assertFiltering(filter, new File("foobar"), false); assertFiltering(filter, new File("fred"), false); assertFiltering(filter, new File("foo").toPath(), true); assertFiltering(filter, new File("FOO").toPath(), false); // case-sensitive assertFiltering(filter, new File("barfoo").toPath(), false); assertFiltering(filter, new File("foobar").toPath(), false); assertFiltering(filter, new File("fred").toPath(), false); // FileFilterUtils.nameFileFilter(String, IOCase) tests filter = FileFilterUtils.nameFileFilter("foo", IOCase.INSENSITIVE); assertFiltering(filter, new File("foo"), true); assertFiltering(filter, new File("FOO"), true); // case-insensitive assertFiltering(filter, new File("barfoo"), false); assertFiltering(filter, new File("foobar"), false); assertFiltering(filter, new File("fred"), false); assertFiltering(filter, new File("foo").toPath(), true); assertFiltering(filter, new File("FOO").toPath(), true); // case-insensitive assertFiltering(filter, new File("barfoo").toPath(), false); assertFiltering(filter, new File("foobar").toPath(), false); assertFiltering(filter, new File("fred").toPath(), false); } private boolean equalsLastModified(final File left, final File right) throws IOException { return Files.getLastModifiedTime(left.toPath()).equals(Files.getLastModifiedTime(right.toPath())); } @Test public void testAgeFilter() throws Exception { final File oldFile = new File(temporaryFolder, "old.txt"); final Path oldPath = oldFile.toPath(); final File reference = new File(temporaryFolder, "reference.txt"); final File newFile = new File(temporaryFolder, "new.txt"); final Path newPath = newFile.toPath(); if (!oldFile.getParentFile().exists()) { fail("Cannot create file " + oldFile + " as the parent directory does not exist"); } try (final BufferedOutputStream output1 = new BufferedOutputStream(Files.newOutputStream(oldFile.toPath()))) { TestUtils.generateTestData(output1, 0); } do { try { TestUtils.sleep(1000); } catch (final InterruptedException ie) { // ignore } if (!reference.getParentFile().exists()) { fail("Cannot create file " + reference + " as the parent directory does not exist"); } try (final BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(reference.toPath()))) { TestUtils.generateTestData(output, 0); } } while (equalsLastModified(oldFile, reference)); final Date date = new Date(); final long now = date.getTime(); do { try { TestUtils.sleep(1000); } catch (final InterruptedException ie) { // ignore } if (!newFile.getParentFile().exists()) { fail("Cannot create file " + newFile + " as the parent directory does not exist"); } try (final BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(newFile.toPath()))) { TestUtils.generateTestData(output, 0); } } while (equalsLastModified(reference, newFile)); final IOFileFilter filter1 = FileFilterUtils.ageFileFilter(now); final IOFileFilter filter2 = FileFilterUtils.ageFileFilter(now, true); final IOFileFilter filter3 = FileFilterUtils.ageFileFilter(now, false); final IOFileFilter filter4 = FileFilterUtils.ageFileFilter(date); final IOFileFilter filter5 = FileFilterUtils.ageFileFilter(date, true); final IOFileFilter filter6 = FileFilterUtils.ageFileFilter(date, false); final IOFileFilter filter7 = FileFilterUtils.ageFileFilter(reference); final IOFileFilter filter8 = FileFilterUtils.ageFileFilter(reference, true); final IOFileFilter filter9 = FileFilterUtils.ageFileFilter(reference, false); assertFiltering(filter1, oldFile, true); assertFiltering(filter2, oldFile, true); assertFiltering(filter3, oldFile, false); assertFiltering(filter4, oldFile, true); assertFiltering(filter5, oldFile, true); assertFiltering(filter6, oldFile, false); assertFiltering(filter7, oldFile, true); assertFiltering(filter8, oldFile, true); assertFiltering(filter9, oldFile, false); assertFiltering(filter1, newFile, false); assertFiltering(filter2, newFile, false); assertFiltering(filter3, newFile, true); assertFiltering(filter4, newFile, false); assertFiltering(filter5, newFile, false); assertFiltering(filter6, newFile, true); assertFiltering(filter7, newFile, false); assertFiltering(filter8, newFile, false); assertFiltering(filter9, newFile, true); // assertFiltering(filter1, oldPath, true); assertFiltering(filter2, oldPath, true); assertFiltering(filter3, oldPath, false); assertFiltering(filter4, oldPath, true); assertFiltering(filter5, oldPath, true); assertFiltering(filter6, oldPath, false); assertFiltering(filter7, oldPath, true); assertFiltering(filter8, oldPath, true); assertFiltering(filter9, oldPath, false); assertFiltering(filter1, newPath, false); assertFiltering(filter2, newPath, false); assertFiltering(filter3, newPath, true); assertFiltering(filter4, newPath, false); assertFiltering(filter5, newPath, false); assertFiltering(filter6, newPath, true); assertFiltering(filter7, newPath, false); assertFiltering(filter8, newPath, false); assertFiltering(filter9, newPath, true); } @Test public void testAnd() { final IOFileFilter trueFilter = TrueFileFilter.INSTANCE; final IOFileFilter falseFilter = FalseFileFilter.INSTANCE; assertFiltering(trueFilter.and(trueFilter), new File("foo.test"), true); assertFiltering(trueFilter.and(falseFilter), new File("foo.test"), false); assertFiltering(falseFilter.and(trueFilter), new File("foo.test"), false); assertFiltering(falseFilter.and(trueFilter), new File("foo.test"), false); } @Test public void testAnd2() { final IOFileFilter trueFilter = TrueFileFilter.INSTANCE; final IOFileFilter falseFilter = FalseFileFilter.INSTANCE; assertFiltering(new AndFileFilter(trueFilter, trueFilter), new File("foo.test"), true); assertFiltering(new AndFileFilter(trueFilter, falseFilter), new File("foo.test"), false); assertFiltering(new AndFileFilter(falseFilter, trueFilter), new File("foo.test"), false); assertFiltering(new AndFileFilter(falseFilter, falseFilter), new File("foo.test"), false); final List filters = new ArrayList<>(); assertFiltering(new AndFileFilter(filters), new File("test"), false); assertFiltering(new AndFileFilter(), new File("test"), false); assertThrows(NullPointerException.class, () -> new AndFileFilter(falseFilter, (IOFileFilter) null)); assertThrows(NullPointerException.class, () -> new AndFileFilter(null, falseFilter)); assertThrows(NullPointerException.class, () -> new AndFileFilter((List) null)); } @Test public void testAndArray() { final IOFileFilter trueFilter = TrueFileFilter.INSTANCE; final IOFileFilter falseFilter = FalseFileFilter.INSTANCE; assertFiltering(new AndFileFilter(trueFilter, trueFilter, trueFilter), new File("foo.test"), true); assertFiltering(new AndFileFilter(trueFilter, falseFilter, falseFilter), new File("foo.test"), false); assertFiltering(new AndFileFilter(falseFilter, trueFilter, trueFilter), new File("foo.test"), false); assertFiltering(new AndFileFilter(falseFilter, falseFilter, falseFilter), new File("foo.test"), false); final List filters = new ArrayList<>(); assertFiltering(new AndFileFilter(filters), new File("test"), false); assertFiltering(new AndFileFilter(), new File("test"), false); } @Test public void testCanExecute() throws Exception { assumeTrue(SystemUtils.IS_OS_WINDOWS); final File executableFile = File.createTempFile(getClass().getSimpleName(), ".temp"); final Path executablePath = executableFile.toPath(); try { try (final BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(executableFile.toPath()))) { TestUtils.generateTestData(output, 32); } assertTrue(executableFile.setExecutable(true)); assertFiltering(CanExecuteFileFilter.CAN_EXECUTE, executableFile, true); assertFiltering(CanExecuteFileFilter.CAN_EXECUTE, executablePath, true); executableFile.setExecutable(false); assertFiltering(CanExecuteFileFilter.CANNOT_EXECUTE, executableFile, false); assertFiltering(CanExecuteFileFilter.CANNOT_EXECUTE, executablePath, false); } finally { executableFile.delete(); } } @Test public void testCanRead() throws Exception { final File readOnlyFile = new File(temporaryFolder, "read-only-file1.txt"); final Path readOnlyPath = readOnlyFile.toPath(); if (!readOnlyFile.getParentFile().exists()) { fail("Cannot create file " + readOnlyFile + " as the parent directory does not exist"); } try (final BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(readOnlyFile.toPath()))) { TestUtils.generateTestData(output, 32); } assertTrue(readOnlyFile.setReadOnly()); assertFiltering(CanReadFileFilter.CAN_READ, readOnlyFile, true); assertFiltering(CanReadFileFilter.CAN_READ, readOnlyPath, true); assertFiltering(CanReadFileFilter.CANNOT_READ, readOnlyFile, false); assertFiltering(CanReadFileFilter.CANNOT_READ, readOnlyPath, false); assertFiltering(CanReadFileFilter.READ_ONLY, readOnlyFile, true); assertFiltering(CanReadFileFilter.READ_ONLY, readOnlyPath, true); readOnlyFile.delete(); } @Test public void testCanWrite() throws Exception { final File readOnlyFile = new File(temporaryFolder, "read-only-file2.txt"); final Path readOnlyPath = readOnlyFile.toPath(); if (!readOnlyFile.getParentFile().exists()) { fail("Cannot create file " + readOnlyFile + " as the parent directory does not exist"); } try (final BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(readOnlyFile.toPath()))) { TestUtils.generateTestData(output, 32); } assertTrue(readOnlyFile.setReadOnly()); assertFiltering(CanWriteFileFilter.CAN_WRITE, temporaryFolder, true); assertFiltering(CanWriteFileFilter.CANNOT_WRITE, temporaryFolder, false); assertFiltering(CanWriteFileFilter.CAN_WRITE, readOnlyFile, false); assertFiltering(CanWriteFileFilter.CAN_WRITE, readOnlyPath, false); assertFiltering(CanWriteFileFilter.CANNOT_WRITE, readOnlyFile, true); assertFiltering(CanWriteFileFilter.CANNOT_WRITE, readOnlyPath, true); readOnlyFile.delete(); } @Test public void testDelegateFileFilter() { final OrFileFilter orFilter = new OrFileFilter(); final File testFile = new File("test.txt"); IOFileFilter filter = new DelegateFileFilter((FileFilter) orFilter); assertFiltering(filter, testFile, false); assertNotNull(filter.toString()); // TODO better test filter = new DelegateFileFilter((FilenameFilter) orFilter); assertFiltering(filter, testFile, false); assertNotNull(filter.toString()); // TODO better test try { new DelegateFileFilter((FileFilter) null); fail(); } catch (final IllegalArgumentException ignore) { } try { new DelegateFileFilter((FilenameFilter) null); fail(); } catch (final IllegalArgumentException ignore) { } } @Test public void testDelegation() { // TODO improve these tests assertNotNull(FileFilterUtils.asFileFilter((FileFilter) FalseFileFilter.INSTANCE)); assertNotNull(FileFilterUtils.asFileFilter((FilenameFilter) FalseFileFilter.INSTANCE).toString()); } @SuppressWarnings("deprecation") @Test public void testDeprecatedWildcard() { IOFileFilter filter = new WildcardFilter("*.txt"); final List patternList = Arrays.asList("*.txt", "*.xml", "*.gif"); final IOFileFilter listFilter = new WildcardFilter(patternList); final File txtFile = new File("test.txt"); final Path txtPath = txtFile.toPath(); final File bmpFile = new File("test.bmp"); final Path bmpPath = bmpFile.toPath(); final File dirFile = new File("src/java"); final Path dirPath = dirFile.toPath(); assertFiltering(filter, new File("log.txt"), true); // assertFiltering(filter, new File("log.txt.bak"), false); assertFiltering(filter, new File("log.txt").toPath(), true); filter = new WildcardFilter("log?.txt"); assertFiltering(filter, new File("log1.txt"), true); assertFiltering(filter, new File("log12.txt"), false); // assertFiltering(filter, new File("log1.txt").toPath(), true); assertFiltering(filter, new File("log12.txt").toPath(), false); filter = new WildcardFilter("open??.????04"); assertFiltering(filter, new File("openAB.102504"), true); assertFiltering(filter, new File("openA.102504"), false); assertFiltering(filter, new File("openXY.123103"), false); // assertFiltering(filter, new File("openAB.102504.old"), false); // assertFiltering(filter, new File("openAB.102504").toPath(), true); assertFiltering(filter, new File("openA.102504").toPath(), false); assertFiltering(filter, new File("openXY.123103").toPath(), false); // assertFiltering(filter, new File("openAB.102504.old").toPath(), false); filter = new WildcardFilter("*.java", "*.class"); assertFiltering(filter, new File("Test.java"), true); assertFiltering(filter, new File("Test.class"), true); assertFiltering(filter, new File("Test.jsp"), false); // assertFiltering(filter, new File("Test.java").toPath(), true); assertFiltering(filter, new File("Test.class").toPath(), true); assertFiltering(filter, new File("Test.jsp").toPath(), false); assertFiltering(listFilter, new File("Test.txt"), true); assertFiltering(listFilter, new File("Test.xml"), true); assertFiltering(listFilter, new File("Test.gif"), true); assertFiltering(listFilter, new File("Test.bmp"), false); // assertFiltering(listFilter, new File("Test.txt").toPath(), true); assertFiltering(listFilter, new File("Test.xml").toPath(), true); assertFiltering(listFilter, new File("Test.gif").toPath(), true); assertFiltering(listFilter, new File("Test.bmp").toPath(), false); assertTrue(listFilter.accept(txtFile)); assertFalse(listFilter.accept(bmpFile)); assertFalse(listFilter.accept(dirFile)); // assertEquals(FileVisitResult.CONTINUE, listFilter.accept(txtPath, null)); assertEquals(FileVisitResult.TERMINATE, listFilter.accept(bmpPath, null)); assertEquals(FileVisitResult.TERMINATE, listFilter.accept(dirPath, null)); assertTrue(listFilter.accept(txtFile.getParentFile(), txtFile.getName())); assertFalse(listFilter.accept(bmpFile.getParentFile(), bmpFile.getName())); assertFalse(listFilter.accept(dirFile.getParentFile(), dirFile.getName())); // assertEquals(FileVisitResult.CONTINUE, listFilter.accept(txtPath, null)); assertEquals(FileVisitResult.TERMINATE, listFilter.accept(bmpPath, null)); assertEquals(FileVisitResult.TERMINATE, listFilter.accept(dirPath, null)); try { new WildcardFilter((String) null); fail(); } catch (final IllegalArgumentException ex) { // expected } try { new WildcardFilter((String[]) null); fail(); } catch (final IllegalArgumentException ex) { // expected } try { new WildcardFilter((List) null); fail(); } catch (final IllegalArgumentException ex) { // expected } } @Test public void testDirectory() { // XXX: This test presumes the current working dir is the base dir of the source checkout. final IOFileFilter filter = new DirectoryFileFilter(); assertFiltering(filter, new File("src/"), true); assertFiltering(filter, new File("src/").toPath(), true); assertFiltering(filter, new File("src/main/java/"), true); assertFiltering(filter, new File("src/main/java/").toPath(), true); assertFiltering(filter, new File("pom.xml"), false); assertFiltering(filter, new File("pom.xml").toPath(), false); assertFiltering(filter, new File("imaginary"), false); assertFiltering(filter, new File("imaginary").toPath(), false); assertFiltering(filter, new File("imaginary/"), false); assertFiltering(filter, new File("imaginary/").toPath(), false); assertFiltering(filter, new File("LICENSE.txt"), false); assertFiltering(filter, new File("LICENSE.txt").toPath(), false); assertSame(DirectoryFileFilter.DIRECTORY, DirectoryFileFilter.INSTANCE); } @Test public void testEmpty() throws Exception { // Empty Dir final File emptyDirFile = new File(temporaryFolder, "empty-dir"); final Path emptyDirPath = emptyDirFile.toPath(); emptyDirFile.mkdirs(); assertFiltering(EmptyFileFilter.EMPTY, emptyDirFile, true); assertFiltering(EmptyFileFilter.EMPTY, emptyDirPath, true); assertFiltering(EmptyFileFilter.NOT_EMPTY, emptyDirFile, false); assertFiltering(EmptyFileFilter.NOT_EMPTY, emptyDirPath, false); // Empty File final File emptyFile = new File(emptyDirFile, "empty-file.txt"); final Path emptyPath = emptyFile.toPath(); if (!emptyFile.getParentFile().exists()) { fail("Cannot create file " + emptyFile + " as the parent directory does not exist"); } try (final BufferedOutputStream output1 = new BufferedOutputStream(Files.newOutputStream(emptyFile.toPath()))) { TestUtils.generateTestData(output1, 0); } assertFiltering(EmptyFileFilter.EMPTY, emptyFile, true); assertFiltering(EmptyFileFilter.EMPTY, emptyPath, true); assertFiltering(EmptyFileFilter.NOT_EMPTY, emptyFile, false); assertFiltering(EmptyFileFilter.NOT_EMPTY, emptyPath, false); // Not Empty Dir assertFiltering(EmptyFileFilter.EMPTY, emptyDirFile, false); assertFiltering(EmptyFileFilter.EMPTY, emptyDirPath, false); assertFiltering(EmptyFileFilter.NOT_EMPTY, emptyDirFile, true); assertFiltering(EmptyFileFilter.NOT_EMPTY, emptyDirPath, true); // Not Empty File final File notEmptyFile = new File(emptyDirFile, "not-empty-file.txt"); final Path notEmptyPath = notEmptyFile.toPath(); if (!notEmptyFile.getParentFile().exists()) { fail("Cannot create file " + notEmptyFile + " as the parent directory does not exist"); } try (final BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(notEmptyFile.toPath()))) { TestUtils.generateTestData(output, 32); } assertFiltering(EmptyFileFilter.EMPTY, notEmptyFile, false); assertFiltering(EmptyFileFilter.EMPTY, notEmptyPath, false); assertFiltering(EmptyFileFilter.NOT_EMPTY, notEmptyFile, true); assertFiltering(EmptyFileFilter.NOT_EMPTY, notEmptyPath, true); FileUtils.forceDelete(emptyDirFile); } @Test public void testEnsureTestCoverage() { assertNotNull(new FileFilterUtils()); // dummy for test coverage } @Test public void testFalse() { final IOFileFilter filter = FileFilterUtils.falseFileFilter(); assertFiltering(filter, new File("foo.test"), false); assertFiltering(filter, new File("foo.test").toPath(), false); assertFiltering(filter, new File("foo"), false); assertFiltering(filter, new File("foo").toPath(), false); assertFiltering(filter, (File) null, false); assertFiltering(filter, (Path) null, false); assertSame(FalseFileFilter.FALSE, FalseFileFilter.INSTANCE); assertSame(TrueFileFilter.TRUE, FalseFileFilter.INSTANCE.negate()); assertSame(TrueFileFilter.INSTANCE, FalseFileFilter.INSTANCE.negate()); assertNotNull(FalseFileFilter.INSTANCE.toString()); } @Test public void testFileEqualsFilter() { assertFooBarFileFiltering( new FileEqualsFileFilter(new File("foo")).or(new FileEqualsFileFilter(new File("bar")))); } @Test public void testFileFilterUtils_and() { final IOFileFilter trueFilter = TrueFileFilter.INSTANCE; final IOFileFilter falseFilter = FalseFileFilter.INSTANCE; assertFiltering(FileFilterUtils.and(trueFilter, trueFilter, trueFilter), new File("foo.test"), true); assertFiltering(FileFilterUtils.and(trueFilter, falseFilter, trueFilter), new File("foo.test"), false); assertFiltering(FileFilterUtils.and(falseFilter, trueFilter), new File("foo.test"), false); assertFiltering(FileFilterUtils.and(falseFilter, falseFilter), new File("foo.test"), false); } @Test public void testFileFilterUtils_or() { final IOFileFilter trueFilter = TrueFileFilter.INSTANCE; final IOFileFilter falseFilter = FalseFileFilter.INSTANCE; final File testFile = new File("foo.test"); assertFiltering(FileFilterUtils.or(trueFilter, trueFilter), testFile, true); assertFiltering(FileFilterUtils.or(trueFilter, trueFilter, falseFilter), testFile, true); assertFiltering(FileFilterUtils.or(falseFilter, trueFilter), testFile, true); assertFiltering(FileFilterUtils.or(falseFilter, falseFilter, falseFilter), testFile, false); } @Test public void testFiles() { // XXX: This test presumes the current working dir is the base dir of the source checkout. final IOFileFilter filter = FileFileFilter.INSTANCE; assertFiltering(filter, new File("src/"), false); assertFiltering(filter, new File("src/").toPath(), false); assertFiltering(filter, new File("src/java/"), false); assertFiltering(filter, new File("src/java/").toPath(), false); assertFiltering(filter, new File("pom.xml"), true); assertFiltering(filter, new File("pom.xml").toPath(), true); assertFiltering(filter, new File("imaginary"), false); assertFiltering(filter, new File("imaginary").toPath(), false); assertFiltering(filter, new File("imaginary/"), false); assertFiltering(filter, new File("imaginary/").toPath(), false); assertFiltering(filter, new File("LICENSE.txt"), true); assertFiltering(filter, new File("LICENSE.txt").toPath(), true); } /* * Test method for {@link FileFilterUtils#filter(IOFileFilter, java.lang.Iterable)} that tests that the method * properly filters files from the list. */ @Test public void testFilterArray_fromList() throws Exception { final File fileA = TestUtils.newFile(temporaryFolder, "A"); final File fileB = TestUtils.newFile(temporaryFolder, "B"); final List fileList = Arrays.asList(fileA, fileB); final IOFileFilter filter = FileFilterUtils.nameFileFilter("A"); final File[] filtered = FileFilterUtils.filter(filter, fileList); assertEquals(1, filtered.length); assertEquals(fileA, filtered[0]); } /* * Test method for {@link FileFilterUtils#filter(IOFileFilter, File...)} that tests that the method properly filters * files from the list. */ @Test public void testFilterArray_IOFileFilter() throws Exception { final File fileA = TestUtils.newFile(temporaryFolder, "A"); final File fileB = TestUtils.newFile(temporaryFolder, "B"); final IOFileFilter filter = FileFilterUtils.nameFileFilter("A"); final File[] filtered = FileFilterUtils.filter(filter, fileA, fileB); assertEquals(1, filtered.length); assertEquals(fileA, filtered[0]); } /* * Test method for {@link FileFilterUtils#filter(IOFileFilter, File...)} that tests that the method properly filters * files from the list. */ @Test public void testFilterArray_PathVisitorFileFilter_FileExistsNo() throws Exception { final File fileA = TestUtils.newFile(temporaryFolder, "A"); final File fileB = TestUtils.newFile(temporaryFolder, "B"); final IOFileFilter filter = new PathVisitorFileFilter(new NameFileFilter("A")); final File[] filtered = FileFilterUtils.filter(filter, fileA, fileB); assertEquals(1, filtered.length); assertEquals(fileA, filtered[0]); } /* * Test method for {@link FileFilterUtils#filter(IOFileFilter, File...)} that tests that the method properly filters * files from the list. */ @Test public void testFilterArray_PathVisitorFileFilter_FileExistsYes() throws Exception { final File fileA = TestUtils.newFile(temporaryFolder, "A"); final File fileB = TestUtils.newFile(temporaryFolder, "B"); FileUtils.write(fileA, "test", StandardCharsets.US_ASCII); final IOFileFilter filter = new PathVisitorFileFilter(new NameFileFilter("A")); final File[] filtered = FileFilterUtils.filter(filter, fileA, fileB); assertEquals(1, filtered.length); assertEquals(fileA, filtered[0]); } /* * Test method for {@link FileFilterUtils#filter(IOFileFilter, File...)} that tests {@code null} parameters. */ @Test public void testFilterFilesArrayNullParameters() throws Exception { final File fileA = TestUtils.newFile(temporaryFolder, "A"); final File fileB = TestUtils.newFile(temporaryFolder, "B"); try { FileFilterUtils.filter(null, fileA, fileB); fail(); } catch (final IllegalArgumentException iae) { // Test passes, exception thrown for null filter } final IOFileFilter filter = FileFilterUtils.trueFileFilter(); FileFilterUtils.filter(filter, fileA, null); final File[] filtered = FileFilterUtils.filter(filter, (File[]) null); assertEquals(0, filtered.length); } /* * Test method for {@link FileFilterUtils#filterList(IOFileFilter, java.lang.Iterable)} that tests that the method * properly filters files from the list. */ @Test public void testFilterList() throws Exception { final File fileA = TestUtils.newFile(temporaryFolder, "A"); final File fileB = TestUtils.newFile(temporaryFolder, "B"); final List fileList = Arrays.asList(fileA, fileB); final IOFileFilter filter = FileFilterUtils.nameFileFilter("A"); final List filteredList = FileFilterUtils.filterList(filter, fileList); assertTrue(filteredList.contains(fileA)); assertFalse(filteredList.contains(fileB)); } /* * Test method for {@link FileFilterUtils#filterList(IOFileFilter, File...)} that tests that the method properly * filters files from the list. */ @Test public void testFilterList_fromArray() throws Exception { final File fileA = TestUtils.newFile(temporaryFolder, "A"); final File fileB = TestUtils.newFile(temporaryFolder, "B"); final IOFileFilter filter = FileFilterUtils.nameFileFilter("A"); final List filteredList = FileFilterUtils.filterList(filter, fileA, fileB); assertTrue(filteredList.contains(fileA)); assertFalse(filteredList.contains(fileB)); } /* * Test method for {@link FileFilterUtils#filterList(IOFileFilter, java.lang.Iterable)} that tests {@code null} * parameters and {@code null} elements in the provided list. */ @Test public void testFilterListNullParameters() { try { FileFilterUtils.filterList(null, Collections.emptyList()); fail(); } catch (final IllegalArgumentException iae) { // Test passes, exception thrown for null filter } final IOFileFilter filter = FileFilterUtils.trueFileFilter(); try { FileFilterUtils.filterList(filter, Collections.singletonList((File) null)); } catch (final IllegalArgumentException iae) { // Test passes, exception thrown for list containing null } final List filteredList = FileFilterUtils.filterList(filter, (List) null); assertEquals(0, filteredList.size()); } /* * Test method for {@link FileFilterUtils#filter(IOFileFilter, Path...)}. */ @Test public void testFilterPathsArrayNullParameters() throws Exception { final Path fileA = TestUtils.newFile(temporaryFolder, "A").toPath(); final Path fileB = TestUtils.newFile(temporaryFolder, "B").toPath(); try { PathUtils.filter(null, fileA, fileB); fail(); } catch (final NullPointerException iae) { // Test passes, exception thrown for null filter } final IOFileFilter filter = FileFilterUtils.trueFileFilter(); PathUtils.filter(filter, fileA, null); final File[] filtered = FileFilterUtils.filter(filter, (File[]) null); assertEquals(0, filtered.length); } /* * Test method for {@link FileFilterUtils#filterSet(IOFileFilter, java.lang.Iterable)} that tests that the method * properly filters files from the set. */ @Test public void testFilterSet() throws Exception { final File fileA = TestUtils.newFile(temporaryFolder, "A"); final File fileB = TestUtils.newFile(temporaryFolder, "B"); final Set fileList = new HashSet<>(Arrays.asList(fileA, fileB)); final IOFileFilter filter = FileFilterUtils.nameFileFilter("A"); final Set filteredSet = FileFilterUtils.filterSet(filter, fileList); assertTrue(filteredSet.contains(fileA)); assertFalse(filteredSet.contains(fileB)); } /* * Test method for {@link FileFilterUtils#filterSet(IOFileFilter, File...)} that tests that the method properly * filters files from the set. */ @Test public void testFilterSet_fromArray() throws Exception { final File fileA = TestUtils.newFile(temporaryFolder, "A"); final File fileB = TestUtils.newFile(temporaryFolder, "B"); final IOFileFilter filter = FileFilterUtils.nameFileFilter("A"); final Set filteredSet = FileFilterUtils.filterSet(filter, fileA, fileB); assertTrue(filteredSet.contains(fileA)); assertFalse(filteredSet.contains(fileB)); } /* * Test method for {@link FileFilterUtils#filterSet(IOFileFilter, java.lang.Iterable)} that tests {@code null} * parameters and {@code null} elements in the provided set. */ @Test public void testFilterSetNullParameters() { try { FileFilterUtils.filterSet(null, Collections.emptySet()); fail(); } catch (final IllegalArgumentException iae) { // Test passes, exception thrown for null filter } final IOFileFilter filter = FileFilterUtils.trueFileFilter(); try { FileFilterUtils.filterSet(filter, new HashSet<>(Collections.singletonList((File) null))); } catch (final IllegalArgumentException iae) { // Test passes, exception thrown for set containing null } final Set filteredSet = FileFilterUtils.filterSet(filter, (Set) null); assertEquals(0, filteredSet.size()); } @Test public void testHidden() { final File hiddenDirFile = new File(SVN_DIR_NAME); final Path hiddenDirPath = hiddenDirFile.toPath(); if (hiddenDirFile.exists()) { assertFiltering(HiddenFileFilter.HIDDEN, hiddenDirFile, hiddenDirFile.isHidden()); assertFiltering(HiddenFileFilter.HIDDEN, hiddenDirPath, hiddenDirFile.isHidden()); assertFiltering(HiddenFileFilter.VISIBLE, hiddenDirFile, !hiddenDirFile.isHidden()); assertFiltering(HiddenFileFilter.VISIBLE, hiddenDirPath, !hiddenDirFile.isHidden()); } final Path path = temporaryFolder.toPath(); assertFiltering(HiddenFileFilter.HIDDEN, temporaryFolder, false); assertFiltering(HiddenFileFilter.HIDDEN, path, false); assertFiltering(HiddenFileFilter.VISIBLE, temporaryFolder, true); assertFiltering(HiddenFileFilter.VISIBLE, path, true); } @Test public void testMagicNumberFileFilterBytes() throws Exception { final byte[] classFileMagicNumber = {(byte) 0xCA, (byte) 0xFE, (byte) 0xBA, (byte) 0xBE}; final String xmlFileContent = "\n" + "text"; final File classAFile = new File(temporaryFolder, "A.class"); final Path classAPath = classAFile.toPath(); final File xmlBFile = new File(temporaryFolder, "B.xml"); final Path xmlBPath = xmlBFile.toPath(); final File emptyFile = new File(temporaryFolder, "C.xml"); final Path emptyPath = emptyFile.toPath(); final File dirFile = new File(temporaryFolder, "D"); final Path dirPath = dirFile.toPath(); dirFile.mkdirs(); try (final OutputStream classFileAStream = FileUtils.openOutputStream(classAFile)) { IOUtils.write(classFileMagicNumber, classFileAStream); TestUtils.generateTestData(classFileAStream, 32); } FileUtils.write(xmlBFile, xmlFileContent, StandardCharsets.UTF_8); FileUtils.touch(emptyFile); IOFileFilter filter = new MagicNumberFileFilter(classFileMagicNumber); assertFiltering(filter, classAFile, true); assertFiltering(filter, classAPath, true); assertFiltering(filter, xmlBFile, false); assertFiltering(filter, xmlBPath, false); assertFiltering(filter, emptyFile, false); assertFiltering(filter, emptyPath, false); assertFiltering(filter, dirFile, false); assertFiltering(filter, dirPath, false); filter = FileFilterUtils.magicNumberFileFilter(classFileMagicNumber); assertFiltering(filter, classAFile, true); assertFiltering(filter, classAPath, true); assertFiltering(filter, xmlBFile, false); assertFiltering(filter, xmlBPath, false); assertFiltering(filter, emptyFile, false); assertFiltering(filter, emptyPath, false); assertFiltering(filter, dirFile, false); assertFiltering(filter, dirPath, false); } @Test public void testMagicNumberFileFilterBytesOffset() throws Exception { final byte[] tarMagicNumber = {0x75, 0x73, 0x74, 0x61, 0x72}; final long tarMagicNumberOffset = 257; final File tarFileA = new File(temporaryFolder, "A.tar"); final File randomFileB = new File(temporaryFolder, "B.txt"); final File dir = new File(temporaryFolder, "D"); dir.mkdirs(); try (final OutputStream tarFileAStream = FileUtils.openOutputStream(tarFileA)) { TestUtils.generateTestData(tarFileAStream, tarMagicNumberOffset); IOUtils.write(tarMagicNumber, tarFileAStream); } if (!randomFileB.getParentFile().exists()) { fail("Cannot create file " + randomFileB + " as the parent directory does not exist"); } try (final BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(randomFileB.toPath()))) { TestUtils.generateTestData(output, 2 * tarMagicNumberOffset); } IOFileFilter filter = new MagicNumberFileFilter(tarMagicNumber, tarMagicNumberOffset); assertFiltering(filter, tarFileA, true); assertFiltering(filter, randomFileB, false); assertFiltering(filter, dir, false); filter = FileFilterUtils.magicNumberFileFilter(tarMagicNumber, tarMagicNumberOffset); assertFiltering(filter, tarFileA, true); assertFiltering(filter, randomFileB, false); assertFiltering(filter, dir, false); } // ----------------------------------------------------------------------- @Test public void testMagicNumberFileFilterString() throws Exception { final byte[] classFileMagicNumber = {(byte) 0xCA, (byte) 0xFE, (byte) 0xBA, (byte) 0xBE}; final String xmlFileContent = "\n" + "text"; final String xmlMagicNumber = " new NameFileFilter((String[]) null)); } @Test public void testNameFilterNullListArgument() { final List test = null; assertThrows(IllegalArgumentException.class, () -> new NameFileFilter(test)); } @Test public void testNegate() { final IOFileFilter filter = FileFilterUtils.notFileFilter(FileFilterUtils.trueFileFilter()); assertFiltering(filter, new File("foo.test"), false); assertFiltering(filter, new File("foo"), false); assertFiltering(filter.negate(), new File("foo"), true); assertFiltering(filter, (File) null, false); assertThrows(IllegalArgumentException.class, () -> new NotFileFilter(null)); } @Test public void testNullFilters() { try { FileFilterUtils.toList((IOFileFilter) null); fail("Expected IllegalArgumentException"); } catch (final IllegalArgumentException ignore) { // expected } try { FileFilterUtils.toList(new IOFileFilter[] {null}); fail("Expected IllegalArgumentException"); } catch (final IllegalArgumentException ignore) { // expected } } @Test public void testOr() { final IOFileFilter trueFilter = TrueFileFilter.INSTANCE; final IOFileFilter falseFilter = FalseFileFilter.INSTANCE; final File testFile = new File("foo.test"); final Path testPath = testFile.toPath(); assertFiltering(new OrFileFilter(trueFilter, trueFilter), testFile, true); assertFiltering(new OrFileFilter(trueFilter, falseFilter), testFile, true); assertFiltering(new OrFileFilter(falseFilter, trueFilter), testFile, true); assertFiltering(new OrFileFilter(falseFilter, falseFilter), testFile, false); assertFiltering(new OrFileFilter(), testFile, false); // assertFiltering(new OrFileFilter(trueFilter, trueFilter), testPath, true); assertFiltering(new OrFileFilter(trueFilter, falseFilter), testPath, true); assertFiltering(new OrFileFilter(falseFilter, trueFilter), testPath, true); assertFiltering(new OrFileFilter(falseFilter, falseFilter), testPath, false); assertFiltering(new OrFileFilter(), testPath, false); // assertFiltering(falseFilter.or(trueFilter), testPath, true); final List filters = new ArrayList<>(); filters.add(trueFilter); filters.add(falseFilter); final OrFileFilter orFilter = new OrFileFilter(filters); assertFiltering(orFilter, testFile, true); assertFiltering(orFilter, testPath, true); assertEquals(orFilter.getFileFilters(), filters); orFilter.removeFileFilter(trueFilter); assertFiltering(orFilter, testFile, false); assertFiltering(orFilter, testPath, false); orFilter.setFileFilters(filters); assertFiltering(orFilter, testFile, true); assertFiltering(orFilter, testPath, true); assertTrue(orFilter.accept(testFile.getParentFile(), testFile.getName())); assertEquals(FileVisitResult.CONTINUE, orFilter.accept(testPath, null)); orFilter.removeFileFilter(trueFilter); assertFalse(orFilter.accept(testFile.getParentFile(), testFile.getName())); assertEquals(FileVisitResult.TERMINATE, orFilter.accept(testPath, null)); assertThrows(NullPointerException.class, () -> new OrFileFilter(falseFilter, (IOFileFilter) null)); } @Test public void testPathEqualsFilter() { assertFooBarFileFiltering( new PathEqualsFileFilter(Paths.get("foo")).or(new PathEqualsFileFilter(Paths.get("bar")))); } @Test public void testPrefix() { IOFileFilter filter = new PrefixFileFilter("foo", "bar"); final File testFile = new File("test"); final Path testPath = testFile.toPath(); final File fredFile = new File("fred"); final Path fredPath = fredFile.toPath(); assertFiltering(filter, new File("foo.test"), true); assertFiltering(filter, new File("FOO.test"), false); // case-sensitive assertFiltering(filter, new File("foo"), true); assertFiltering(filter, new File("bar"), true); assertFiltering(filter, new File("food/"), true); // assertFiltering(filter, new File("foo.test").toPath(), true); assertFiltering(filter, new File("FOO.test").toPath(), false); // case-sensitive assertFiltering(filter, new File("foo").toPath(), true); assertFiltering(filter, new File("bar").toPath(), true); assertFiltering(filter, new File("food/").toPath(), true); filter = FileFilterUtils.prefixFileFilter("bar"); assertFiltering(filter, new File("barred\\"), true); assertFiltering(filter, new File("test"), false); assertFiltering(filter, new File("fo_o.test"), false); assertFiltering(filter, new File("abar.exe"), false); // assertFiltering(filter, new File("barred\\").toPath(), true); assertFiltering(filter, new File("test").toPath(), false); assertFiltering(filter, new File("fo_o.test").toPath(), false); assertFiltering(filter, new File("abar.exe").toPath(), false); filter = new PrefixFileFilter("tes"); assertFiltering(filter, new File("test"), true); assertFiltering(filter, new File("fred"), false); // assertFiltering(filter, new File("test").toPath(), true); assertFiltering(filter, new File("fred").toPath(), false); assertTrue(filter.accept(testFile.getParentFile(), testFile.getName())); assertFalse(filter.accept(fredFile.getParentFile(), fredFile.getName())); // assertEquals(FileVisitResult.CONTINUE, filter.accept(testPath, null)); assertEquals(FileVisitResult.TERMINATE, filter.accept(fredPath, null)); final List prefixes = Arrays.asList("foo", "fre"); final IOFileFilter listFilter = new PrefixFileFilter(prefixes); assertFalse(listFilter.accept(testFile.getParentFile(), testFile.getName())); assertTrue(listFilter.accept(fredFile.getParentFile(), fredFile.getName())); // assertEquals(FileVisitResult.TERMINATE, listFilter.accept(testPath, null)); assertEquals(FileVisitResult.CONTINUE, listFilter.accept(fredPath, null)); try { new PrefixFileFilter((String) null); fail(); } catch (final IllegalArgumentException ignore) { } try { new PrefixFileFilter((String[]) null); fail(); } catch (final IllegalArgumentException ignore) { } try { new PrefixFileFilter((List) null); fail(); } catch (final IllegalArgumentException ignore) { } } @Test public void testPrefixCaseInsensitive() { IOFileFilter filter = new PrefixFileFilter(new String[] {"foo", "bar"}, IOCase.INSENSITIVE); assertFiltering(filter, new File("foo.test1"), true); assertFiltering(filter, new File("bar.test1"), true); assertFiltering(filter, new File("FOO.test1"), true); // case-sensitive assertFiltering(filter, new File("BAR.test1"), true); // case-sensitive filter = new PrefixFileFilter("bar", IOCase.INSENSITIVE); assertFiltering(filter, new File("foo.test2"), false); assertFiltering(filter, new File("bar.test2"), true); assertFiltering(filter, new File("FOO.test2"), false); // case-sensitive assertFiltering(filter, new File("BAR.test2"), true); // case-sensitive final List prefixes = Arrays.asList("foo", "bar"); filter = new PrefixFileFilter(prefixes, IOCase.INSENSITIVE); assertFiltering(filter, new File("foo.test3"), true); assertFiltering(filter, new File("bar.test3"), true); assertFiltering(filter, new File("FOO.test3"), true); // case-sensitive assertFiltering(filter, new File("BAR.test3"), true); // case-sensitive try { new PrefixFileFilter((String) null, IOCase.INSENSITIVE); fail(); } catch (final IllegalArgumentException ignore) { } try { new PrefixFileFilter((String[]) null, IOCase.INSENSITIVE); fail(); } catch (final IllegalArgumentException ignore) { } try { new PrefixFileFilter((List) null, IOCase.INSENSITIVE); fail(); } catch (final IllegalArgumentException ignore) { } // FileFilterUtils.prefixFileFilter(String, IOCase) tests filter = FileFilterUtils.prefixFileFilter("bar", IOCase.INSENSITIVE); assertFiltering(filter, new File("foo.test2"), false); assertFiltering(filter, new File("bar.test2"), true); assertFiltering(filter, new File("FOO.test2"), false); // case-sensitive assertFiltering(filter, new File("BAR.test2"), true); // case-sensitive try { FileFilterUtils.prefixFileFilter(null, IOCase.INSENSITIVE); fail(); } catch (final IllegalArgumentException ignore) { } } @Test public void testSizeFilterOnFiles() throws Exception { final File smallFile = new File(temporaryFolder, "small.txt"); if (!smallFile.getParentFile().exists()) { fail("Cannot create file " + smallFile + " as the parent directory does not exist"); } try (final BufferedOutputStream output1 = new BufferedOutputStream(Files.newOutputStream(smallFile.toPath()))) { TestUtils.generateTestData(output1, 32); } final File largeFile = new File(temporaryFolder, "large.txt"); if (!largeFile.getParentFile().exists()) { fail("Cannot create file " + largeFile + " as the parent directory does not exist"); } try (final BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(largeFile.toPath()))) { TestUtils.generateTestData(output, 128); } final IOFileFilter filter1 = FileFilterUtils.sizeFileFilter(64); final IOFileFilter filter2 = FileFilterUtils.sizeFileFilter(64, true); final IOFileFilter filter3 = FileFilterUtils.sizeFileFilter(64, false); assertFiltering(filter1, smallFile, false); assertFiltering(filter2, smallFile, false); assertFiltering(filter3, smallFile, true); assertFiltering(filter1, largeFile, true); assertFiltering(filter2, largeFile, true); assertFiltering(filter3, largeFile, false); // size range tests final IOFileFilter filter4 = FileFilterUtils.sizeRangeFileFilter(33, 127); final IOFileFilter filter5 = FileFilterUtils.sizeRangeFileFilter(32, 127); final IOFileFilter filter6 = FileFilterUtils.sizeRangeFileFilter(33, 128); final IOFileFilter filter7 = FileFilterUtils.sizeRangeFileFilter(31, 129); final IOFileFilter filter8 = FileFilterUtils.sizeRangeFileFilter(128, 128); assertFiltering(filter4, smallFile, false); assertFiltering(filter4, largeFile, false); assertFiltering(filter5, smallFile, true); assertFiltering(filter5, largeFile, false); assertFiltering(filter6, smallFile, false); assertFiltering(filter6, largeFile, true); assertFiltering(filter7, smallFile, true); assertFiltering(filter7, largeFile, true); assertFiltering(filter8, largeFile, true); try { FileFilterUtils.sizeFileFilter(-1); fail(); } catch (final IllegalArgumentException ex) { // expected } } @Test public void testSizeFilterOnPaths() throws Exception { final Path smallFile = Paths.get(temporaryFolder.toString(), "small.txt"); if (Files.notExists(smallFile.getParent())) { fail("Cannot create file " + smallFile + " as the parent directory does not exist"); } try (OutputStream output = Files.newOutputStream(smallFile)) { TestUtils.generateTestData(output, 32); } final Path largeFile = Paths.get(temporaryFolder.toString(), "large.txt"); if (Files.notExists(largeFile.getParent())) { fail("Cannot create file " + largeFile + " as the parent directory does not exist"); } try (OutputStream output = Files.newOutputStream(largeFile)) { TestUtils.generateTestData(output, 128); } final IOFileFilter filter1 = FileFilterUtils.sizeFileFilter(64); final IOFileFilter filter2 = FileFilterUtils.sizeFileFilter(64, true); final IOFileFilter filter3 = FileFilterUtils.sizeFileFilter(64, false); assertFiltering(filter1, smallFile, false); assertFiltering(filter2, smallFile, false); assertFiltering(filter3, smallFile, true); assertFiltering(filter1, largeFile, true); assertFiltering(filter2, largeFile, true); assertFiltering(filter3, largeFile, false); // size range tests final IOFileFilter filter4 = FileFilterUtils.sizeRangeFileFilter(33, 127); final IOFileFilter filter5 = FileFilterUtils.sizeRangeFileFilter(32, 127); final IOFileFilter filter6 = FileFilterUtils.sizeRangeFileFilter(33, 128); final IOFileFilter filter7 = FileFilterUtils.sizeRangeFileFilter(31, 129); final IOFileFilter filter8 = FileFilterUtils.sizeRangeFileFilter(128, 128); assertFiltering(filter4, smallFile, false); assertFiltering(filter4, largeFile, false); assertFiltering(filter5, smallFile, true); assertFiltering(filter5, largeFile, false); assertFiltering(filter6, smallFile, false); assertFiltering(filter6, largeFile, true); assertFiltering(filter7, smallFile, true); assertFiltering(filter7, largeFile, true); assertFiltering(filter8, largeFile, true); try { FileFilterUtils.sizeFileFilter(-1); fail(); } catch (final IllegalArgumentException ex) { // expected } } @Test public void testSuffix() { IOFileFilter filter = new SuffixFileFilter("tes", "est"); final File testFile = new File("test"); final Path testPath = testFile.toPath(); final File fredFile = new File("fred"); final Path fredPath = fredFile.toPath(); // assertFiltering(filter, new File("fred.tes"), true); assertFiltering(filter, new File("fred.est"), true); assertFiltering(filter, new File("fred.EST"), false); // case-sensitive assertFiltering(filter, new File("fred.exe"), false); // assertFiltering(filter, new File("fred.tes").toPath(), true); assertFiltering(filter, new File("fred.est").toPath(), true); assertFiltering(filter, new File("fred.EST").toPath(), false); // case-sensitive assertFiltering(filter, new File("fred.exe").toPath(), false); filter = FileFilterUtils.or(FileFilterUtils.suffixFileFilter("tes"), FileFilterUtils.suffixFileFilter("est")); assertFiltering(filter, new File("fred"), false); assertFiltering(filter, new File(".tes"), true); assertFiltering(filter, new File("fred.test"), true); // assertFiltering(filter, new File("fred").toPath(), false); assertFiltering(filter, new File(".tes").toPath(), true); assertFiltering(filter, new File("fred.test").toPath(), true); filter = new SuffixFileFilter("est"); assertFiltering(filter, new File("test"), true); assertFiltering(filter, new File("fred"), false); // assertFiltering(filter, new File("test").toPath(), true); assertFiltering(filter, new File("fred").toPath(), false); assertTrue(filter.accept(testFile.getParentFile(), testFile.getName())); assertFalse(filter.accept(fredFile.getParentFile(), fredFile.getName())); // assertEquals(FileVisitResult.CONTINUE, filter.accept(testPath, null)); assertEquals(FileVisitResult.TERMINATE, filter.accept(fredPath, null)); final List prefixes = Arrays.asList("ood", "red"); final IOFileFilter listFilter = new SuffixFileFilter(prefixes); assertFalse(listFilter.accept(testFile.getParentFile(), testFile.getName())); assertTrue(listFilter.accept(fredFile.getParentFile(), fredFile.getName())); // assertEquals(FileVisitResult.TERMINATE, listFilter.accept(testPath, null)); assertEquals(FileVisitResult.CONTINUE, listFilter.accept(fredPath, null)); try { new SuffixFileFilter((String) null); fail(); } catch (final IllegalArgumentException ignore) { } try { new SuffixFileFilter((String[]) null); fail(); } catch (final IllegalArgumentException ignore) { } try { new SuffixFileFilter((List) null); fail(); } catch (final IllegalArgumentException ignore) { } } @Test public void testSuffixCaseInsensitive() { IOFileFilter filter = new SuffixFileFilter(new String[] {"tes", "est"}, IOCase.INSENSITIVE); assertFiltering(filter, new File("foo.tes"), true); assertFiltering(filter, new File("foo.est"), true); assertFiltering(filter, new File("foo.EST"), true); // case-sensitive assertFiltering(filter, new File("foo.TES"), true); // case-sensitive assertFiltering(filter, new File("foo.exe"), false); filter = new SuffixFileFilter("est", IOCase.INSENSITIVE); assertFiltering(filter, new File("test"), true); assertFiltering(filter, new File("TEST"), true); final List suffixes = Arrays.asList("tes", "est"); filter = new SuffixFileFilter(suffixes, IOCase.INSENSITIVE); assertFiltering(filter, new File("bar.tes"), true); assertFiltering(filter, new File("bar.est"), true); assertFiltering(filter, new File("bar.EST"), true); // case-sensitive assertFiltering(filter, new File("bar.TES"), true); // case-sensitive assertFiltering(filter, new File("bar.exe"), false); try { new SuffixFileFilter((String) null, IOCase.INSENSITIVE); fail(); } catch (final IllegalArgumentException ignore) { } try { new SuffixFileFilter((String[]) null, IOCase.INSENSITIVE); fail(); } catch (final IllegalArgumentException ignore) { } try { new SuffixFileFilter((List) null, IOCase.INSENSITIVE); fail(); } catch (final IllegalArgumentException ignore) { } // FileFilterUtils.suffixFileFilter(String, IOCase) tests filter = FileFilterUtils.suffixFileFilter("est", IOCase.INSENSITIVE); assertFiltering(filter, new File("test"), true); assertFiltering(filter, new File("TEST"), true); try { FileFilterUtils.suffixFileFilter(null, IOCase.INSENSITIVE); fail(); } catch (final IllegalArgumentException ex) { } } @Test public void testTrue() { final IOFileFilter filter = FileFilterUtils.trueFileFilter(); assertFiltering(filter, new File("foo.test"), true); assertFiltering(filter, new File("foo"), true); assertFiltering(filter, (File) null, true); // assertFiltering(filter, new File("foo.test").toPath(), true); assertFiltering(filter, new File("foo").toPath(), true); assertFiltering(filter, (Path) null, true); // assertSame(TrueFileFilter.TRUE, TrueFileFilter.INSTANCE); assertSame(FalseFileFilter.FALSE, TrueFileFilter.INSTANCE.negate()); assertSame(FalseFileFilter.INSTANCE, TrueFileFilter.INSTANCE.negate()); assertNotNull(TrueFileFilter.INSTANCE.toString()); } @Test public void testWildcard() { IOFileFilter filter = new WildcardFileFilter("*.txt"); assertFiltering(filter, new File("log.txt"), true); assertFiltering(filter, new File("log.TXT"), false); // assertFiltering(filter, new File("log.txt").toPath(), true); assertFiltering(filter, new File("log.TXT").toPath(), false); filter = new WildcardFileFilter("*.txt", IOCase.SENSITIVE); assertFiltering(filter, new File("log.txt"), true); assertFiltering(filter, new File("log.TXT"), false); // assertFiltering(filter, new File("log.txt").toPath(), true); assertFiltering(filter, new File("log.TXT").toPath(), false); filter = new WildcardFileFilter("*.txt", IOCase.INSENSITIVE); assertFiltering(filter, new File("log.txt"), true); assertFiltering(filter, new File("log.TXT"), true); // assertFiltering(filter, new File("log.txt").toPath(), true); assertFiltering(filter, new File("log.TXT").toPath(), true); filter = new WildcardFileFilter("*.txt", IOCase.SYSTEM); assertFiltering(filter, new File("log.txt"), true); assertFiltering(filter, new File("log.TXT"), WINDOWS); // assertFiltering(filter, new File("log.txt").toPath(), true); assertFiltering(filter, new File("log.TXT").toPath(), WINDOWS); filter = new WildcardFileFilter("*.txt", null); assertFiltering(filter, new File("log.txt"), true); assertFiltering(filter, new File("log.TXT"), false); // assertFiltering(filter, new File("log.txt").toPath(), true); assertFiltering(filter, new File("log.TXT").toPath(), false); filter = new WildcardFileFilter("*.java", "*.class"); assertFiltering(filter, new File("Test.java"), true); assertFiltering(filter, new File("Test.class"), true); assertFiltering(filter, new File("Test.jsp"), false); // assertFiltering(filter, new File("Test.java").toPath(), true); assertFiltering(filter, new File("Test.class").toPath(), true); assertFiltering(filter, new File("Test.jsp").toPath(), false); filter = new WildcardFileFilter(new String[] {"*.java", "*.class"}, IOCase.SENSITIVE); assertFiltering(filter, new File("Test.java"), true); assertFiltering(filter, new File("Test.JAVA"), false); // assertFiltering(filter, new File("Test.java").toPath(), true); assertFiltering(filter, new File("Test.JAVA").toPath(), false); filter = new WildcardFileFilter(new String[] {"*.java", "*.class"}, IOCase.INSENSITIVE); assertFiltering(filter, new File("Test.java"), true); assertFiltering(filter, new File("Test.JAVA"), true); // assertFiltering(filter, new File("Test.java").toPath(), true); assertFiltering(filter, new File("Test.JAVA").toPath(), true); filter = new WildcardFileFilter(new String[] {"*.java", "*.class"}, IOCase.SYSTEM); assertFiltering(filter, new File("Test.java"), true); assertFiltering(filter, new File("Test.JAVA"), WINDOWS); // assertFiltering(filter, new File("Test.java").toPath(), true); assertFiltering(filter, new File("Test.JAVA").toPath(), WINDOWS); filter = new WildcardFileFilter(new String[] {"*.java", "*.class"}, null); assertFiltering(filter, new File("Test.java"), true); assertFiltering(filter, new File("Test.JAVA"), false); // assertFiltering(filter, new File("Test.java").toPath(), true); assertFiltering(filter, new File("Test.JAVA").toPath(), false); final List patternList = Arrays.asList("*.txt", "*.xml", "*.gif"); final IOFileFilter listFilter = new WildcardFileFilter(patternList); assertFiltering(listFilter, new File("Test.txt"), true); assertFiltering(listFilter, new File("Test.xml"), true); assertFiltering(listFilter, new File("Test.gif"), true); assertFiltering(listFilter, new File("Test.bmp"), false); // assertFiltering(listFilter, new File("Test.txt").toPath(), true); assertFiltering(listFilter, new File("Test.xml").toPath(), true); assertFiltering(listFilter, new File("Test.gif").toPath(), true); assertFiltering(listFilter, new File("Test.bmp").toPath(), false); final File txtFile = new File("test.txt"); final Path txtPath = txtFile.toPath(); final File bmpFile = new File("test.bmp"); final Path bmpPath = bmpFile.toPath(); final File dirFile = new File("src/java"); final Path dirPath = dirFile.toPath(); assertTrue(listFilter.accept(txtFile)); assertFalse(listFilter.accept(bmpFile)); assertFalse(listFilter.accept(dirFile)); // assertEquals(FileVisitResult.CONTINUE, listFilter.accept(txtFile.toPath(), null)); assertEquals(FileVisitResult.TERMINATE, listFilter.accept(bmpFile.toPath(), null)); assertEquals(FileVisitResult.TERMINATE, listFilter.accept(dirFile.toPath(), null)); assertTrue(listFilter.accept(txtFile.getParentFile(), txtFile.getName())); assertFalse(listFilter.accept(bmpFile.getParentFile(), bmpFile.getName())); assertFalse(listFilter.accept(dirFile.getParentFile(), dirFile.getName())); // assertEquals(FileVisitResult.CONTINUE, listFilter.accept(txtPath, null)); assertEquals(FileVisitResult.TERMINATE, listFilter.accept(bmpPath, null)); assertEquals(FileVisitResult.TERMINATE, listFilter.accept(dirPath, null)); try { new WildcardFileFilter((String) null); fail(); } catch (final IllegalArgumentException ignore) { } try { new WildcardFileFilter((String[]) null); fail(); } catch (final IllegalArgumentException ignore) { } try { new WildcardFileFilter((List) null); fail(); } catch (final IllegalArgumentException ignore) { } } } ././@LongLink0100644 0000000 0000000 00000000147 13612062727 011643 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/java/org/apache/commons/io/filefilter/IOFileFilterAbstractTestCase.javacommons-io-2.11.0-src/src/test/java/org/apache/commons/io/filefilter/IOFileFilterAbstractTestCase.ja0100644 0000000 0000000 00000013235 13612062727 033630 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.filefilter; import static org.junit.jupiter.api.Assertions.assertEquals; import java.io.File; public abstract class IOFileFilterAbstractTestCase { public static void assertFileFiltering(final int testNumber, final IOFileFilter filter, final File file, final boolean expected) { assertEquals(expected, filter.accept(file), "test " + testNumber + " Filter(File) " + filter.getClass().getName() + " not " + expected + " for " + file); } public static void assertFilenameFiltering(final int testNumber, final IOFileFilter filter, final File file, final boolean expected) { // Assumes file has parent and is not passed as null assertEquals(expected, filter.accept(file.getParentFile(), file.getName()), "test " + testNumber + " Filter(File, String) " + filter.getClass().getName() + " not " + expected + " for " + file); } public static void assertFiltering(final int testNumber, final IOFileFilter filter, final File file, final boolean expected) { // Note. This only tests the (File, String) version if the parent of // the File passed in is not null assertEquals(expected, filter.accept(file), "test " + testNumber + " Filter(File) " + filter.getClass().getName() + " not " + expected + " for " + file); assertEquals(expected, filter.accept(file.toPath(), null), "test " + testNumber + " Filter(File) " + filter.getClass().getName() + " not " + expected + " for " + file); if (file != null && file.getParentFile() != null) { assertEquals(expected, filter.accept(file.getParentFile(), file.getName()), "test " + testNumber + " Filter(File, String) " + filter.getClass().getName() + " not " + expected + " for " + file); } else if (file == null) { assertEquals(expected, filter.accept(file), "test " + testNumber + " Filter(File, String) " + filter.getClass().getName() + " not " + expected + " for null"); } } public static void assertTrueFiltersInvoked(final int testNumber, final TesterTrueFileFilter[] filters, final boolean[] invoked) { for (int i = 1; i < filters.length; i++) { assertEquals(invoked[i - 1], filters[i].isInvoked(), "test " + testNumber + " filter " + i + " invoked"); } } public static void assertFalseFiltersInvoked(final int testNumber, final TesterFalseFileFilter[] filters, final boolean[] invoked) { for (int i = 1; i < filters.length; i++) { assertEquals(invoked[i - 1], filters[i].isInvoked(), "test " + testNumber + " filter " + i + " invoked"); } } public static File determineWorkingDirectoryPath(final String key, final String defaultPath) { // Look for a system property to specify the working directory final String workingPathName = System.getProperty(key, defaultPath); return new File(workingPathName); } public static void resetFalseFilters(final TesterFalseFileFilter[] filters) { for (final TesterFalseFileFilter filter : filters) { if (filter != null) { filter.reset(); } } } public static void resetTrueFilters(final TesterTrueFileFilter[] filters) { for (final TesterTrueFileFilter filter : filters) { if (filter != null) { filter.reset(); } } } class TesterTrueFileFilter extends TrueFileFilter { private static final long serialVersionUID = 1828930358172422914L; private boolean invoked; @Override public boolean accept(final File file) { setInvoked(true); return super.accept(file); } @Override public boolean accept(final File file, final String str) { setInvoked(true); return super.accept(file, str); } public boolean isInvoked() { return this.invoked; } public void setInvoked(final boolean invoked) { this.invoked = invoked; } public void reset() { setInvoked(false); } } class TesterFalseFileFilter extends FalseFileFilter { private static final long serialVersionUID = -3603047664010401872L; private boolean invoked; @Override public boolean accept(final File file) { setInvoked(true); return super.accept(file); } @Override public boolean accept(final File file, final String str) { setInvoked(true); return super.accept(file, str); } public boolean isInvoked() { return this.invoked; } public void setInvoked(final boolean invoked) { this.invoked = invoked; } public void reset() { setInvoked(false); } } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/filefilter/NameFileFilterTest.java0100644 0000000 0000000 00000011017 13612062727 032244 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.filefilter; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Collections; import org.apache.commons.io.file.AccumulatorPathVisitor; import org.apache.commons.io.file.CounterAssertions; import org.apache.commons.io.file.Counters; import org.junit.jupiter.api.Test; /** * Tests {@link NameFileFilter}. */ public class NameFileFilterTest { /** * Javadoc example. * * System.out calls are commented out here but not in the Javadoc. */ @Test public void testJavadocExampleUsingIo() { final File dir = new File("."); final String[] files = dir.list(new NameFileFilter("NOTICE.txt")); for (final String file : files) { // System.out.println(file); } // End of Javadoc example assertEquals(1, files.length); } /** * Javadoc example. * * System.out calls are commented out here but not in the Javadoc. */ @Test public void testJavadocExampleUsingNio() throws IOException { final Path dir = Paths.get(""); // We are interested in files older than one day final AccumulatorPathVisitor visitor = AccumulatorPathVisitor.withLongCounters(new NameFileFilter("NOTICE.txt"), TrueFileFilter.INSTANCE); // // Walk one dir Files.walkFileTree(dir, Collections.emptySet(), 1, visitor); // System.out.println(visitor.getPathCounters()); // System.out.println(visitor.getFileList()); // System.out.println(visitor.getDirList()); assertEquals(1, visitor.getPathCounters().getFileCounter().get()); assertEquals(1, visitor.getPathCounters().getDirectoryCounter().get()); assertTrue(visitor.getPathCounters().getByteCounter().get() > 0); assertFalse(visitor.getDirList().isEmpty()); assertFalse(visitor.getFileList().isEmpty()); assertEquals(1, visitor.getFileList().size()); // visitor.getPathCounters().reset(); // // Walk dir tree Files.walkFileTree(dir, visitor); // System.out.println(visitor.getPathCounters()); // System.out.println(visitor.getDirList()); // System.out.println(visitor.getFileList()); // // End of Javadoc example assertTrue(visitor.getPathCounters().getFileCounter().get() > 0); assertTrue(visitor.getPathCounters().getDirectoryCounter().get() > 0); assertTrue(visitor.getPathCounters().getByteCounter().get() > 0); // We counted and accumulated assertFalse(visitor.getDirList().isEmpty()); assertFalse(visitor.getFileList().isEmpty()); // assertNotEquals(Counters.noopPathCounters(), visitor.getPathCounters()); visitor.getPathCounters().reset(); CounterAssertions.assertZeroCounters(visitor.getPathCounters()); } @Test public void testNoCounting() throws IOException { final Path dir = Paths.get(""); final AccumulatorPathVisitor visitor = new AccumulatorPathVisitor(Counters.noopPathCounters(), new NameFileFilter("NOTICE.txt"), TrueFileFilter.INSTANCE); Files.walkFileTree(dir, Collections.emptySet(), 1, visitor); // CounterAssertions.assertZeroCounters(visitor.getPathCounters()); // We did not count, but we still accumulated assertFalse(visitor.getDirList().isEmpty()); assertFalse(visitor.getFileList().isEmpty()); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/filefilter/OrFileFilterTestCase.java0100644 0000000 0000000 00000023201 13612062727 032536 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.filefilter; import java.util.ArrayList; import java.util.List; import org.junit.jupiter.api.BeforeEach; /** * Tests {@link IOFileFilter}. */ public class OrFileFilterTestCase extends ConditionalFileFilterAbstractTestCase { private static final String DEFAULT_WORKING_PATH = "./OrFileFilterTestCase/"; private static final String WORKING_PATH_NAME_PROPERTY_KEY = OrFileFilterTestCase.class.getName() + ".workingDirectory"; private List> testFilters; private List testTrueResults; private List testFalseResults; private List testFileResults; private List testFilenameResults; @Override protected IOFileFilter buildFilterUsingAdd(final List filters) { final OrFileFilter filter = new OrFileFilter(); for (final IOFileFilter filter1 : filters) { filter.addFileFilter(filter1); } return filter; } @Override protected IOFileFilter buildFilterUsingConstructor(final List filters) { return new OrFileFilter(filters); } @Override protected ConditionalFileFilter getConditionalFileFilter() { return new OrFileFilter(); } @Override protected String getDefaultWorkingPath() { return DEFAULT_WORKING_PATH; } @Override protected List getFalseResults() { return this.testFalseResults; } @Override protected List getFileResults() { return this.testFileResults; } @Override protected List getFilenameResults() { return this.testFilenameResults; } @Override protected List> getTestFilters() { return this.testFilters; } @Override protected List getTrueResults() { return this.testTrueResults; } @Override protected String getWorkingPathNamePropertyKey() { return WORKING_PATH_NAME_PROPERTY_KEY; } @BeforeEach public void setUpTestFilters() { // filters //tests this.testFilters = new ArrayList<>(); this.testTrueResults = new ArrayList<>(); this.testFalseResults = new ArrayList<>(); this.testFileResults = new ArrayList<>(); this.testFilenameResults = new ArrayList<>(); // test 0 - add empty elements { testFilters.add(0, null); testTrueResults.add(0, null); testFalseResults.add(0, null); testFileResults.add(0, null); testFilenameResults.add(0, null); } // test 1 - Test conditional or with all filters returning true { // test 1 filters final List filters = new ArrayList<>(); filters.add(trueFilters[1]); filters.add(trueFilters[2]); filters.add(trueFilters[3]); // test 1 true results final boolean[] trueResults = {true, false, false}; // test 1 false results final boolean[] falseResults = {false, false, false}; testFilters.add(1, filters); testTrueResults.add(1, trueResults); testFalseResults.add(1, falseResults); testFileResults.add(1, Boolean.TRUE); testFilenameResults.add(1, Boolean.TRUE); } // test 2 - Test conditional or with first filter returning false { // test 2 filters final List filters = new ArrayList<>(); filters.add(falseFilters[1]); filters.add(trueFilters[1]); filters.add(trueFilters[2]); filters.add(trueFilters[3]); filters.add(falseFilters[2]); filters.add(falseFilters[3]); // test 2 true results final boolean[] trueResults = {true, false, false}; // test 2 false results final boolean[] falseResults = {true, false, false}; testFilters.add(2, filters); testTrueResults.add(2, trueResults); testFalseResults.add(2, falseResults); testFileResults.add(2, Boolean.TRUE); testFilenameResults.add(2, Boolean.TRUE); } // test 3 - Test conditional or with second filter returning false { // test 3 filters final List filters = new ArrayList<>(); filters.add(trueFilters[1]); filters.add(falseFilters[1]); filters.add(trueFilters[2]); filters.add(trueFilters[3]); filters.add(falseFilters[2]); filters.add(falseFilters[3]); // test 3 true results final boolean[] trueResults = {true, false, false}; // test 3 false results final boolean[] falseResults = {false, false, false}; testFilters.add(3, filters); testTrueResults.add(3, trueResults); testFalseResults.add(3, falseResults); testFileResults.add(3, Boolean.TRUE); testFilenameResults.add(3, Boolean.TRUE); } // test 4 - Test conditional or with third filter returning false { // test 4 filters final List filters = new ArrayList<>(); filters.add(trueFilters[1]); filters.add(trueFilters[2]); filters.add(falseFilters[1]); filters.add(trueFilters[3]); filters.add(falseFilters[2]); filters.add(falseFilters[3]); // test 4 true results final boolean[] trueResults = {true, false, false}; // test 4 false results final boolean[] falseResults = {false, false, false}; testFilters.add(4, filters); testTrueResults.add(4, trueResults); testFalseResults.add(4, falseResults); testFileResults.add(4, Boolean.TRUE); testFilenameResults.add(4, Boolean.TRUE); } // test 5 - Test conditional or with first and third filters returning false { // test 5 filters final List filters = new ArrayList<>(); filters.add(falseFilters[1]); filters.add(trueFilters[1]); filters.add(falseFilters[2]); filters.add(falseFilters[3]); filters.add(trueFilters[2]); filters.add(trueFilters[3]); // test 5 true results final boolean[] trueResults = {true, false, false}; // test 5 false results final boolean[] falseResults = {true, false, false}; testFilters.add(5, filters); testTrueResults.add(5, trueResults); testFalseResults.add(5, falseResults); testFileResults.add(5, Boolean.TRUE); testFilenameResults.add(5, Boolean.TRUE); } // test 6 - Test conditional or with second and third filters returning false { final List filters = new ArrayList<>(); filters.add(trueFilters[1]); filters.add(falseFilters[1]); filters.add(falseFilters[2]); filters.add(trueFilters[2]); filters.add(trueFilters[3]); filters.add(falseFilters[3]); // test 6 true results final boolean[] trueResults = {true, false, false}; // test 6 false results final boolean[] falseResults = {false, false, false}; testFilters.add(6, filters); testTrueResults.add(6, trueResults); testFalseResults.add(6, falseResults); testFileResults.add(6, Boolean.TRUE); testFilenameResults.add(6, Boolean.TRUE); } // test 7 - Test conditional or with first and second filters returning false { final List filters = new ArrayList<>(); filters.add(falseFilters[1]); filters.add(falseFilters[2]); filters.add(trueFilters[1]); filters.add(falseFilters[3]); filters.add(trueFilters[2]); filters.add(trueFilters[3]); // test 7 true results final boolean[] trueResults = {true, false, false}; // test 7 false results final boolean[] falseResults = {true, true, false}; testFilters.add(7, filters); testTrueResults.add(7, trueResults); testFalseResults.add(7, falseResults); testFileResults.add(7, Boolean.TRUE); testFilenameResults.add(7, Boolean.TRUE); } // test 8 - Test conditional or with fourth filter returning false { final List filters = new ArrayList<>(); filters.add(trueFilters[1]); filters.add(trueFilters[2]); filters.add(trueFilters[3]); filters.add(falseFilters[1]); // test 8 true results final boolean[] trueResults = {true, false, false}; // test 8 false results final boolean[] falseResults = {false, false, false}; testFilters.add(8, filters); testTrueResults.add(8, trueResults); testFalseResults.add(8, falseResults); testFileResults.add(8, Boolean.TRUE); testFilenameResults.add(8, Boolean.TRUE); } // test 9 - Test conditional or with all filters returning false { final List filters = new ArrayList<>(); filters.add(falseFilters[1]); filters.add(falseFilters[2]); filters.add(falseFilters[3]); // test 9 true results final boolean[] trueResults = {false, false, false}; // test 9 false results final boolean[] falseResults = {true, true, true}; testFilters.add(9, filters); testTrueResults.add(9, trueResults); testFalseResults.add(9, falseResults); testFileResults.add(9, Boolean.FALSE); testFilenameResults.add(9, Boolean.FALSE); } } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/filefilter/RegexFileFilterTestCase.java0100644 0000000 0000000 00000015335 13612062727 033241 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.filefilter; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; import java.io.File; import java.nio.file.FileVisitResult; import java.nio.file.Path; import java.nio.file.Paths; import java.util.regex.Pattern; import org.apache.commons.io.IOCase; import org.junit.jupiter.api.Test; /** * Tests {@link RegexFileFilter}. */ public class RegexFileFilterTestCase { public void assertFiltering(final IOFileFilter filter, final File file, final boolean expected) { // Note. This only tests the (File, String) version if the parent of // the File passed in is not null assertEquals(expected, filter.accept(file), "Filter(File) " + filter.getClass().getName() + " not " + expected + " for " + file); if (file != null && file.getParentFile() != null) { assertEquals(expected, filter.accept(file.getParentFile(), file.getName()), "Filter(File, String) " + filter.getClass().getName() + " not " + expected + " for " + file); } else if (file == null) { assertEquals(expected, filter.accept(file), "Filter(File, String) " + filter.getClass().getName() + " not " + expected + " for null"); } } public void assertFiltering(final IOFileFilter filter, final Path path, final boolean expected) { // Note. This only tests the (Path, Path) version if the parent of // the Path passed in is not null final FileVisitResult expectedFileVisitResult = AbstractFileFilter.toFileVisitResult(expected, path); assertEquals(expectedFileVisitResult, filter.accept(path, null), "Filter(Path) " + filter.getClass().getName() + " not " + expectedFileVisitResult + " for " + path); if (path != null && path.getParent() != null) { assertEquals(expectedFileVisitResult, filter.accept(path, null), "Filter(Path, Path) " + filter.getClass().getName() + " not " + expectedFileVisitResult + " for " + path); } else if (path == null) { assertEquals(expectedFileVisitResult, filter.accept(path, null), "Filter(Path, Path) " + filter.getClass().getName() + " not " + expectedFileVisitResult + " for null"); } } @Test public void testRegex() { IOFileFilter filter = new RegexFileFilter("^.*[tT]est(-\\d+)?\\.java$"); assertFiltering(filter, new File("Test.java"), true); assertFiltering(filter, new File("test-10.java"), true); assertFiltering(filter, new File("test-.java"), false); // assertFiltering(filter, new File("Test.java").toPath(), true); assertFiltering(filter, new File("test-10.java").toPath(), true); assertFiltering(filter, new File("test-.java").toPath(), false); filter = new RegexFileFilter("^[Tt]est.java$"); assertFiltering(filter, new File("Test.java"), true); assertFiltering(filter, new File("test.java"), true); assertFiltering(filter, new File("tEST.java"), false); // assertFiltering(filter, new File("Test.java").toPath(), true); assertFiltering(filter, new File("test.java").toPath(), true); assertFiltering(filter, new File("tEST.java").toPath(), false); filter = new RegexFileFilter(Pattern.compile("^test.java$", Pattern.CASE_INSENSITIVE)); assertFiltering(filter, new File("Test.java"), true); assertFiltering(filter, new File("test.java"), true); assertFiltering(filter, new File("tEST.java"), true); // assertFiltering(filter, new File("Test.java").toPath(), true); assertFiltering(filter, new File("test.java").toPath(), true); assertFiltering(filter, new File("tEST.java").toPath(), true); filter = new RegexFileFilter("^test.java$", Pattern.CASE_INSENSITIVE); assertFiltering(filter, new File("Test.java"), true); assertFiltering(filter, new File("test.java"), true); assertFiltering(filter, new File("tEST.java"), true); // assertFiltering(filter, new File("Test.java").toPath(), true); assertFiltering(filter, new File("test.java").toPath(), true); assertFiltering(filter, new File("tEST.java").toPath(), true); filter = new RegexFileFilter("^test.java$", IOCase.INSENSITIVE); assertFiltering(filter, new File("Test.java"), true); assertFiltering(filter, new File("test.java"), true); assertFiltering(filter, new File("tEST.java"), true); // assertFiltering(filter, new File("Test.java").toPath(), true); assertFiltering(filter, new File("test.java").toPath(), true); assertFiltering(filter, new File("tEST.java").toPath(), true); } @Test public void testRegexEdgeCases() { try { new RegexFileFilter((String) null); fail(); } catch (final IllegalArgumentException ignore) { // expected } try { new RegexFileFilter(null, Pattern.CASE_INSENSITIVE); fail(); } catch (final IllegalArgumentException ignore) { // expected } try { new RegexFileFilter(null, IOCase.INSENSITIVE); fail(); } catch (final IllegalArgumentException ignore) { // expected } try { new RegexFileFilter((java.util.regex.Pattern) null); fail(); } catch (final IllegalArgumentException ignore) { // expected } } /** * Tests https://issues.apache.org/jira/browse/IO-733. */ @Test public void testRegexFileNameOnly() { final Path path = Paths.get("folder", "Foo.java"); final String patternStr = "Foo.*"; assertFiltering(new RegexFileFilter(patternStr), path, true); assertFiltering(new RegexFileFilter(Pattern.compile(patternStr), Path::toString), path, false); } } ././@LongLink0100644 0000000 0000000 00000000145 13612062727 011641 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/java/org/apache/commons/io/filefilter/SymbolicLinkFileFilterTest.javacommons-io-2.11.0-src/src/test/java/org/apache/commons/io/filefilter/SymbolicLinkFileFilterTest.java0100644 0000000 0000000 00000002427 13612062727 033770 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.filefilter; import static org.junit.jupiter.api.Assertions.assertEquals; import java.nio.file.FileVisitResult; import org.apache.commons.io.file.PathUtils; import org.junit.jupiter.api.Test; /** * Tests {@link SymbolicLinkFileFilter}. */ public class SymbolicLinkFileFilterTest { @Test public void testSymbolicLinkFileFilter() { assertEquals(FileVisitResult.TERMINATE, SymbolicLinkFileFilter.INSTANCE.accept(PathUtils.current(), null)); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/function/IOConsumerTest.java0100644 0000000 0000000 00000003213 13612062727 031140 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.function; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import java.io.Closeable; import java.io.IOException; import java.io.StringReader; import org.apache.commons.io.IOUtils; import org.apache.commons.io.test.ThrowOnCloseReader; import org.junit.jupiter.api.Test; /** * Tests {@linnk IOConsumer}. */ public class IOConsumerTest { @Test public void testNoopIOConsumer() { final Closeable nullCloseable = null; final IOConsumer noopConsumer = IOConsumer.noop(); // noop consumer doesn't throw assertDoesNotThrow(() -> IOUtils.close(nullCloseable, noopConsumer)); assertDoesNotThrow(() -> IOUtils.close(new StringReader("s"), noopConsumer)); assertDoesNotThrow(() -> IOUtils.close(new ThrowOnCloseReader(new StringReader("s")), noopConsumer)); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/function/IOFunctionTest.java0100644 0000000 0000000 00000014665 13612062727 031147 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.function; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Supplier; import org.junit.jupiter.api.Test; public class IOFunctionTest { private static class Holder { T value; } @Test public void testAndThenConsumer() throws IOException { final Holder holder = new Holder<>(); final IOFunction readByte = InputStream::read; final Consumer sinkInteger = i -> { holder.value = i * i; }; final IOConsumer productFunction = readByte.andThen(sinkInteger); final InputStream is = new ByteArrayInputStream(new byte[] {2, 3}); productFunction.accept(is); assertEquals(4, holder.value); productFunction.accept(is); assertEquals(9, holder.value); } @Test public void testAndThenFunction() throws IOException { final IOFunction readByte = InputStream::read; final Function squareInteger = i -> i * i; final IOFunction productFunction = readByte.andThen(squareInteger); final InputStream is = new ByteArrayInputStream(new byte[] {2, 3}); assertEquals(4, productFunction.apply(is)); assertEquals(9, productFunction.apply(is)); } @Test public void testAndThenIOConsumer() throws IOException { final Holder holder = new Holder<>(); final IOFunction readByte = InputStream::read; final IOConsumer sinkInteger = i -> { holder.value = i * i; }; final IOConsumer productFunction = readByte.andThen(sinkInteger); final InputStream is = new ByteArrayInputStream(new byte[] {2, 3}); productFunction.accept(is); assertEquals(4, holder.value); productFunction.accept(is); assertEquals(9, holder.value); } @Test public void testAndThenIOFunction() throws IOException { final IOFunction readByte = InputStream::read; final IOFunction squareInteger = i -> i * i; final IOFunction productFunction = readByte.andThen(squareInteger); final InputStream is = new ByteArrayInputStream(new byte[] {2, 3}); assertEquals(4, productFunction.apply(is)); assertEquals(9, productFunction.apply(is)); } @Test public void testApply() throws IOException { final IOFunction readByte = InputStream::read; final InputStream is = new ByteArrayInputStream(new byte[] { (byte)0xa, (byte)0xb, (byte)0xc}); assertEquals(0xa, readByte.apply(is)); assertEquals(0xb, readByte.apply(is)); assertEquals(0xc, readByte.apply(is)); assertEquals(-1, readByte.apply(is)); } @Test public void testApplyRaisesException() { final IOFunction raiseException = is -> { throw new IOException("Boom!"); }; final InputStream is = new ByteArrayInputStream(new byte[] { (byte)0xa, (byte)0xb, (byte)0xc}); assertThrows(IOException.class, () -> { raiseException.apply(is); }); } @Test public void testComposeFunction() throws IOException { final Function alwaysSeven = is -> 7; final IOFunction squareInteger = i -> i * i; final IOFunction productFunction = squareInteger.compose(alwaysSeven); final InputStream is = new ByteArrayInputStream(new byte[] {2, 3}); assertEquals(49, productFunction.apply(is)); assertEquals(49, productFunction.apply(is)); } @Test public void testComposeIOFunction() throws IOException { final IOFunction readByte = InputStream::read; final IOFunction squareInteger = i -> i * i; final IOFunction productFunction = squareInteger.compose(readByte); final InputStream is = new ByteArrayInputStream(new byte[] {2, 3}); assertEquals(4, productFunction.apply(is)); assertEquals(9, productFunction.apply(is)); } @Test public void testComposeIOSupplier() throws IOException { final InputStream is = new ByteArrayInputStream(new byte[] {2, 3}); final IOSupplier readByte = () -> is.read(); final IOFunction squareInteger = i -> i * i; final IOSupplier productFunction = squareInteger.compose(readByte); assertEquals(4, productFunction.get()); assertEquals(9, productFunction.get()); } @Test public void testComposeSupplier() throws IOException { final Supplier alwaysNine = () -> 9; final IOFunction squareInteger = i -> i * i; final IOSupplier productFunction = squareInteger.compose(alwaysNine); assertEquals(81, productFunction.get()); assertEquals(81, productFunction.get()); } @Test public void testIdentity() throws IOException { final IOFunction identityFunction = IOFunction.identity(); try (final InputStream is = new ByteArrayInputStream(new byte[] { (byte) 0xa, (byte) 0xb, (byte) 0xc })) { assertEquals(is, identityFunction.apply(is)); } } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/AbstractInputStreamTest.java0100644 0000000 0000000 00000013405 13612062727 032372 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.junit.jupiter.api.Assertions.assertEquals; import java.io.File; import java.io.IOException; import java.io.InputStream; import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.RandomUtils; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Tests functionality of {@link BufferedFileChannelInputStream}. * * This class was ported and adapted from Apache Spark commit 933dc6cb7b3de1d8ccaf73d124d6eb95b947ed19 where it was * called {@code GenericFileInputStreamSuite}. */ public abstract class AbstractInputStreamTest { private byte[] randomBytes; protected File inputFile; protected InputStream[] inputStreams; @BeforeEach public void setUp() throws IOException { // Create a byte array of size 2 MB with random bytes randomBytes = RandomUtils.nextBytes(2 * 1024 * 1024); inputFile = File.createTempFile("temp-file", ".tmp"); FileUtils.writeByteArrayToFile(inputFile, randomBytes); } @AfterEach public void tearDown() throws IOException { inputFile.delete(); for (final InputStream is : inputStreams) { is.close(); } } @Test public void testBytesSkipped() throws IOException { for (final InputStream inputStream : inputStreams) { assertEquals(1024, inputStream.skip(1024)); for (int i = 1024; i < randomBytes.length; i++) { assertEquals(randomBytes[i], (byte) inputStream.read()); } } } @Test public void testBytesSkippedAfterEOF() throws IOException { for (final InputStream inputStream : inputStreams) { assertEquals(randomBytes.length, inputStream.skip(randomBytes.length + 1)); assertEquals(-1, inputStream.read()); } } @Test public void testBytesSkippedAfterRead() throws IOException { for (final InputStream inputStream : inputStreams) { for (int i = 0; i < 1024; i++) { assertEquals(randomBytes[i], (byte) inputStream.read()); } assertEquals(1024, inputStream.skip(1024)); for (int i = 2048; i < randomBytes.length; i++) { assertEquals(randomBytes[i], (byte) inputStream.read()); } } } @Test public void testNegativeBytesSkippedAfterRead() throws IOException { for (final InputStream inputStream : inputStreams) { for (int i = 0; i < 1024; i++) { assertEquals(randomBytes[i], (byte) inputStream.read()); } // Skipping negative bytes should essential be a no-op assertEquals(0, inputStream.skip(-1)); assertEquals(0, inputStream.skip(-1024)); assertEquals(0, inputStream.skip(Long.MIN_VALUE)); assertEquals(1024, inputStream.skip(1024)); for (int i = 2048; i < randomBytes.length; i++) { assertEquals(randomBytes[i], (byte) inputStream.read()); } } } @Test public void testReadMultipleBytes() throws IOException { for (final InputStream inputStream : inputStreams) { final byte[] readBytes = new byte[8 * 1024]; int i = 0; while (i < randomBytes.length) { final int read = inputStream.read(readBytes, 0, 8 * 1024); for (int j = 0; j < read; j++) { assertEquals(randomBytes[i], readBytes[j]); i++; } } } } @Test public void testReadOneByte() throws IOException { for (final InputStream inputStream : inputStreams) { for (final byte randomByte : randomBytes) { assertEquals(randomByte, (byte) inputStream.read()); } } } @Test public void testReadPastEOF() throws IOException { final InputStream is = inputStreams[0]; final byte[] buf = new byte[1024]; int read; while ((read = is.read(buf, 0, buf.length)) != -1) { } final int readAfterEOF = is.read(buf, 0, buf.length); assertEquals(-1, readAfterEOF); } @Test public void testSkipFromFileChannel() throws IOException { for (final InputStream inputStream : inputStreams) { // Since the buffer is smaller than the skipped bytes, this will guarantee // we skip from underlying file channel. assertEquals(1024, inputStream.skip(1024)); for (int i = 1024; i < 2048; i++) { assertEquals(randomBytes[i], (byte) inputStream.read()); } assertEquals(256, inputStream.skip(256)); assertEquals(256, inputStream.skip(256)); assertEquals(512, inputStream.skip(512)); for (int i = 3072; i < randomBytes.length; i++) { assertEquals(randomBytes[i], (byte) inputStream.read()); } } } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/AutoCloseInputStreamTest.java0100644 0000000 0000000 00000010206 13612062727 032521 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * JUnit Test Case for {@link AutoCloseInputStream}. */ public class AutoCloseInputStreamTest { private byte[] data; private InputStream stream; private boolean closed; @BeforeEach public void setUp() { data = new byte[] {'x', 'y', 'z'}; stream = new AutoCloseInputStream(new ByteArrayInputStream(data) { @Override public void close() { closed = true; } }); closed = false; } @Test public void testClose() throws IOException { stream.close(); assertTrue(closed, "closed"); assertEquals(-1, stream.read(), "read()"); } @Test public void testRead() throws IOException { for (final byte element : data) { assertEquals(element, stream.read(), "read()"); assertFalse(closed, "closed"); } assertEquals(-1, stream.read(), "read()"); assertTrue(closed, "closed"); } @Test public void testReadBuffer() throws IOException { final byte[] b = new byte[data.length * 2]; int total = 0; for (int n = 0; n != -1; n = stream.read(b)) { assertFalse(closed, "closed"); for (int i = 0; i < n; i++) { assertEquals(data[total + i], b[i], "read(b)"); } total += n; } assertEquals(data.length, total, "read(b)"); assertTrue(closed, "closed"); assertEquals(-1, stream.read(b), "read(b)"); } @Test public void testReadBufferOffsetLength() throws IOException { final byte[] b = new byte[data.length * 2]; int total = 0; for (int n = 0; n != -1; n = stream.read(b, total, b.length - total)) { assertFalse(closed, "closed"); total += n; } assertEquals(data.length, total, "read(b, off, len)"); for (int i = 0; i < data.length; i++) { assertEquals(data[i], b[i], "read(b, off, len)"); } assertTrue(closed, "closed"); assertEquals(-1, stream.read(b, 0, b.length), "read(b, off, len)"); } @Test public void testResetBeforeEnd() throws IOException { final String inputStr = "1234"; final AutoCloseInputStream inputStream = new AutoCloseInputStream(new ByteArrayInputStream(inputStr.getBytes())); inputStream.mark(1); assertEquals('1', inputStream.read()); inputStream.reset(); assertEquals('1', inputStream.read()); assertEquals('2', inputStream.read()); inputStream.reset(); assertEquals('1', inputStream.read()); assertEquals('2', inputStream.read()); assertEquals('3', inputStream.read()); inputStream.reset(); assertEquals('1', inputStream.read()); assertEquals('2', inputStream.read()); assertEquals('3', inputStream.read()); assertEquals('4', inputStream.read()); inputStream.reset(); assertEquals('1', inputStream.read()); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/BOMInputStreamTest.java0100644 0000000 0000000 00000075136 13612062727 031255 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.Assumptions.assumeFalse; import static org.junit.jupiter.api.Assumptions.assumeTrue; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.Reader; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.apache.commons.io.ByteOrderMark; import org.junit.jupiter.api.Test; import org.w3c.dom.Document; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; /** * Test case for {@link BOMInputStream}. * */ @SuppressWarnings("ResultOfMethodCallIgnored") public class BOMInputStreamTest { //---------------------------------------------------------------------------- // Support code //---------------------------------------------------------------------------- /** * A mock InputStream that expects {@code close()} to be called. */ private static class ExpectCloseInputStream extends InputStream { private boolean _closeCalled; public void assertCloseCalled() { assertTrue(_closeCalled); } @Override public void close() throws IOException { _closeCalled = true; } @Override public int read() throws IOException { return -1; } } private void assertData(final byte[] expected, final byte[] actual, final int len) { assertEquals(expected.length, len, "length"); for (int ii = 0; ii < expected.length; ii++) { assertEquals(expected[ii], actual[ii], "byte " + ii); } } /** * Creates the underlying data stream, with or without BOM. */ private InputStream createUtf16BeDataStream(final byte[] baseData, final boolean addBOM) { byte[] data = baseData; if (addBOM) { data = new byte[baseData.length + 2]; data[0] = (byte) 0xFE; data[1] = (byte) 0xFF; System.arraycopy(baseData, 0, data, 2, baseData.length); } return new ByteArrayInputStream(data); } /** * Creates the underlying data stream, with or without BOM. */ private InputStream createUtf16LeDataStream(final byte[] baseData, final boolean addBOM) { byte[] data = baseData; if (addBOM) { data = new byte[baseData.length + 2]; data[0] = (byte) 0xFF; data[1] = (byte) 0xFE; System.arraycopy(baseData, 0, data, 2, baseData.length); } return new ByteArrayInputStream(data); } /** * Creates the underlying data stream, with or without BOM. */ private InputStream createUtf32BeDataStream(final byte[] baseData, final boolean addBOM) { byte[] data = baseData; if (addBOM) { data = new byte[baseData.length + 4]; data[0] = 0; data[1] = 0; data[2] = (byte) 0xFE; data[3] = (byte) 0xFF; System.arraycopy(baseData, 0, data, 4, baseData.length); } return new ByteArrayInputStream(data); } /** * Creates the underlying data stream, with or without BOM. */ private InputStream createUtf32LeDataStream(final byte[] baseData, final boolean addBOM) { byte[] data = baseData; if (addBOM) { data = new byte[baseData.length + 4]; data[0] = (byte) 0xFF; data[1] = (byte) 0xFE; data[2] = 0; data[3] = 0; System.arraycopy(baseData, 0, data, 4, baseData.length); } return new ByteArrayInputStream(data); } /** * Creates the underlying data stream, with or without BOM. */ private InputStream createUtf8DataStream(final byte[] baseData, final boolean addBOM) { byte[] data = baseData; if (addBOM) { data = new byte[baseData.length + 3]; data[0] = (byte) 0xEF; data[1] = (byte) 0xBB; data[2] = (byte) 0xBF; System.arraycopy(baseData, 0, data, 3, baseData.length); } return new ByteArrayInputStream(data); } //---------------------------------------------------------------------------- // Test cases //---------------------------------------------------------------------------- private void parseXml(final InputStream in) throws SAXException, IOException, ParserConfigurationException { final Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new InputSource(in)); assertNotNull(doc); assertEquals("X", doc.getFirstChild().getNodeName()); } private void parseXml(final Reader in) throws SAXException, IOException, ParserConfigurationException { final Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new InputSource(in)); assertNotNull(doc); assertEquals("X", doc.getFirstChild().getNodeName()); } private void readBOMInputStreamTwice(final String resource) throws Exception { final InputStream inputStream = this.getClass().getResourceAsStream(resource); assertNotNull(inputStream); final BOMInputStream bomInputStream = new BOMInputStream(inputStream); bomInputStream.mark(1000000); this.readFile(bomInputStream); bomInputStream.reset(); this.readFile(bomInputStream); inputStream.close(); bomInputStream.close(); } private void readFile(final BOMInputStream bomInputStream) throws Exception { int bytes; final byte[] bytesFromStream = new byte[100]; do { bytes = bomInputStream.read(bytesFromStream); } while (bytes > 0); } @Test public void testAvailableWithBOM() throws Exception { final byte[] data = { 'A', 'B', 'C', 'D' }; try (final InputStream in = new BOMInputStream(createUtf8DataStream(data, true))) { assertEquals(7, in.available()); } } @Test public void testAvailableWithoutBOM() throws Exception { final byte[] data = { 'A', 'B', 'C', 'D' }; try (final InputStream in = new BOMInputStream(createUtf8DataStream(data, false))) { assertEquals(4, in.available()); } } @Test // this is here for coverage public void testClose() throws Exception { try (final ExpectCloseInputStream del = new ExpectCloseInputStream()) { try (final InputStream in = new BOMInputStream(del)) { // nothing } del.assertCloseCalled(); } } @Test public void testEmptyBufferWithBOM() throws Exception { final byte[] data = {}; try (final InputStream in = new BOMInputStream(createUtf8DataStream(data, true))) { final byte[] buf = new byte[1024]; assertEquals(-1, in.read(buf)); } } @Test public void testEmptyBufferWithoutBOM() throws Exception { final byte[] data = {}; try (final InputStream in = new BOMInputStream(createUtf8DataStream(data, false))) { final byte[] buf = new byte[1024]; assertEquals(-1, in.read(buf)); } } @Test public void testGetBOMFirstThenRead() throws Exception { final byte[] data = { 'A', 'B', 'C' }; try (final BOMInputStream in = new BOMInputStream(createUtf8DataStream(data, true))) { assertEquals(ByteOrderMark.UTF_8, in.getBOM(), "getBOM"); assertTrue(in.hasBOM(), "hasBOM()"); assertTrue(in.hasBOM(ByteOrderMark.UTF_8), "hasBOM(UTF-8)"); assertEquals('A', in.read()); assertEquals('B', in.read()); assertEquals('C', in.read()); assertEquals(-1, in.read()); } } @Test public void testGetBOMFirstThenReadInclude() throws Exception { final byte[] data = { 'A', 'B', 'C' }; try (final BOMInputStream in = new BOMInputStream(createUtf8DataStream(data, true), true)) { assertTrue(in.hasBOM(), "hasBOM()"); assertTrue(in.hasBOM(ByteOrderMark.UTF_8), "hasBOM(UTF-8)"); assertEquals(ByteOrderMark.UTF_8, in.getBOM(), "getBOM"); assertEquals(0xEF, in.read()); assertEquals(0xBB, in.read()); assertEquals(0xBF, in.read()); assertEquals('A', in.read()); assertEquals('B', in.read()); assertEquals('C', in.read()); assertEquals(-1, in.read()); } } @Test public void testLargeBufferWithBOM() throws Exception { final byte[] data = { 'A', 'B', 'C' }; try (final InputStream in = new BOMInputStream(createUtf8DataStream(data, true))) { final byte[] buf = new byte[1024]; assertData(data, buf, in.read(buf)); } } @Test public void testLargeBufferWithoutBOM() throws Exception { final byte[] data = { 'A', 'B', 'C' }; try (final InputStream in = new BOMInputStream(createUtf8DataStream(data, false))) { final byte[] buf = new byte[1024]; assertData(data, buf, in.read(buf)); } } @Test public void testLeadingNonBOMBufferedRead() throws Exception { final byte[] data = { (byte) 0xEF, (byte) 0xAB, (byte) 0xCD }; try (final InputStream in = new BOMInputStream(createUtf8DataStream(data, false))) { final byte[] buf = new byte[1024]; assertData(data, buf, in.read(buf)); } } @Test public void testLeadingNonBOMSingleRead() throws Exception { final byte[] data = { (byte) 0xEF, (byte) 0xAB, (byte) 0xCD }; try (final InputStream in = new BOMInputStream(createUtf8DataStream(data, false))) { assertEquals(0xEF, in.read()); assertEquals(0xAB, in.read()); assertEquals(0xCD, in.read()); assertEquals(-1, in.read()); } } @Test public void testMarkResetAfterReadWithBOM() throws Exception { final byte[] data = { 'A', 'B', 'C', 'D' }; try (final InputStream in = new BOMInputStream(createUtf8DataStream(data, true))) { assertTrue(in.markSupported()); in.read(); in.mark(10); in.read(); in.read(); in.reset(); assertEquals('B', in.read()); } } @Test public void testMarkResetAfterReadWithoutBOM() throws Exception { final byte[] data = { 'A', 'B', 'C', 'D' }; try (final InputStream in = new BOMInputStream(createUtf8DataStream(data, false))) { assertTrue(in.markSupported()); in.read(); in.mark(10); in.read(); in.read(); in.reset(); assertEquals('B', in.read()); } } @Test public void testMarkResetBeforeReadWithBOM() throws Exception { final byte[] data = { 'A', 'B', 'C', 'D' }; try (final InputStream in = new BOMInputStream(createUtf8DataStream(data, true))) { assertTrue(in.markSupported()); in.mark(10); in.read(); in.read(); in.reset(); assertEquals('A', in.read()); } } @Test public void testMarkResetBeforeReadWithoutBOM() throws Exception { final byte[] data = { 'A', 'B', 'C', 'D' }; try (final InputStream in = new BOMInputStream(createUtf8DataStream(data, false))) { assertTrue(in.markSupported()); in.mark(10); in.read(); in.read(); in.reset(); assertEquals('A', in.read()); } } @Test public void testNoBoms() throws Exception { final byte[] data = { 'A', 'B', 'C' }; try { (new BOMInputStream(createUtf8DataStream(data, true), false, (ByteOrderMark[])null)).close(); fail("Null BOMs, expected IllegalArgumentException"); } catch (final IllegalArgumentException e) { // expected } try { (new BOMInputStream(createUtf8DataStream(data, true), false, new ByteOrderMark[0])).close(); fail("Null BOMs, expected IllegalArgumentException"); } catch (final IllegalArgumentException e) { // expected } } @Test public void testReadEmpty() throws Exception { final byte[] data = {}; try (final BOMInputStream in = new BOMInputStream(createUtf8DataStream(data, false))) { assertEquals(-1, in.read()); assertFalse(in.hasBOM(), "hasBOM()"); assertFalse(in.hasBOM(ByteOrderMark.UTF_8), "hasBOM(UTF-8)"); assertNull(in.getBOM(), "getBOM"); } } @Test public void testReadSmall() throws Exception { final byte[] data = { 'A', 'B' }; try (final BOMInputStream in = new BOMInputStream(createUtf8DataStream(data, false))) { assertEquals('A', in.read()); assertEquals('B', in.read()); assertEquals(-1, in.read()); assertFalse(in.hasBOM(), "hasBOM()"); assertFalse(in.hasBOM(ByteOrderMark.UTF_8), "hasBOM(UTF-8)"); assertNull(in.getBOM(), "getBOM"); } } @Test public void testReadTwiceWithBOM() throws Exception { this.readBOMInputStreamTwice("/org/apache/commons/io/testfileBOM.xml"); } @Test public void testReadTwiceWithoutBOM() throws Exception { this.readBOMInputStreamTwice("/org/apache/commons/io/testfileNoBOM.xml"); } @Test public void testReadWithBOMInclude() throws Exception { final byte[] data = { 'A', 'B', 'C' }; try (final BOMInputStream in = new BOMInputStream(createUtf8DataStream(data, true), true)) { assertEquals(0xEF, in.read()); assertEquals(0xBB, in.read()); assertEquals(0xBF, in.read()); assertEquals('A', in.read()); assertEquals('B', in.read()); assertEquals('C', in.read()); assertEquals(-1, in.read()); assertTrue(in.hasBOM(), "hasBOM()"); assertTrue(in.hasBOM(ByteOrderMark.UTF_8), "hasBOM(UTF-8)"); assertEquals(ByteOrderMark.UTF_8, in.getBOM(), "getBOM"); } } @Test public void testReadWithBOMUtf16Be() throws Exception { final byte[] data = "ABC".getBytes(StandardCharsets.UTF_16BE); try (final BOMInputStream in = new BOMInputStream(createUtf16BeDataStream(data, true), ByteOrderMark.UTF_16BE)) { assertEquals(0, in.read()); assertEquals('A', in.read()); assertEquals(0, in.read()); assertEquals('B', in.read()); assertEquals(0, in.read()); assertEquals('C', in.read()); assertEquals(-1, in.read()); assertTrue(in.hasBOM(), "hasBOM()"); assertTrue(in.hasBOM(ByteOrderMark.UTF_16BE), "hasBOM(UTF-16BE)"); assertEquals(ByteOrderMark.UTF_16BE, in.getBOM(), "getBOM"); try { in.hasBOM(ByteOrderMark.UTF_16LE); fail("Expected IllegalArgumentException"); } catch (final IllegalArgumentException e) { // expected - not configured for UTF-16LE } } } @Test public void testReadWithBOMUtf16Le() throws Exception { final byte[] data = "ABC".getBytes(StandardCharsets.UTF_16LE); try (final BOMInputStream in = new BOMInputStream(createUtf16LeDataStream(data, true), ByteOrderMark.UTF_16LE)) { assertEquals('A', in.read()); assertEquals(0, in.read()); assertEquals('B', in.read()); assertEquals(0, in.read()); assertEquals('C', in.read()); assertEquals(0, in.read()); assertEquals(-1, in.read()); assertTrue(in.hasBOM(), "hasBOM()"); assertTrue(in.hasBOM(ByteOrderMark.UTF_16LE), "hasBOM(UTF-16LE)"); assertEquals(ByteOrderMark.UTF_16LE, in.getBOM(), "getBOM"); try { in.hasBOM(ByteOrderMark.UTF_16BE); fail("Expected IllegalArgumentException"); } catch (final IllegalArgumentException e) { // expected - not configured for UTF-16BE } } } @Test public void testReadWithBOMUtf32Be() throws Exception { assumeTrue(Charset.isSupported("UTF_32BE")); final byte[] data = "ABC".getBytes("UTF_32BE"); try (final BOMInputStream in = new BOMInputStream(createUtf32BeDataStream(data, true), ByteOrderMark.UTF_32BE)) { assertEquals(0, in.read()); assertEquals(0, in.read()); assertEquals(0, in.read()); assertEquals('A', in.read()); assertEquals(0, in.read()); assertEquals(0, in.read()); assertEquals(0, in.read()); assertEquals('B', in.read()); assertEquals(0, in.read()); assertEquals(0, in.read()); assertEquals(0, in.read()); assertEquals('C', in.read()); assertEquals(-1, in.read()); assertTrue(in.hasBOM(), "hasBOM()"); assertTrue(in.hasBOM(ByteOrderMark.UTF_32BE), "hasBOM(UTF-32BE)"); assertEquals(ByteOrderMark.UTF_32BE, in.getBOM(), "getBOM"); try { in.hasBOM(ByteOrderMark.UTF_32LE); fail("Expected IllegalArgumentException"); } catch (final IllegalArgumentException e) { // expected - not configured for UTF-32LE } } } @Test public void testReadWithBOMUtf32Le() throws Exception { assumeTrue(Charset.isSupported("UTF_32LE")); final byte[] data = "ABC".getBytes("UTF_32LE"); try (final BOMInputStream in = new BOMInputStream(createUtf32LeDataStream(data, true), ByteOrderMark.UTF_32LE)) { assertEquals('A', in.read()); assertEquals(0, in.read()); assertEquals(0, in.read()); assertEquals(0, in.read()); assertEquals('B', in.read()); assertEquals(0, in.read()); assertEquals(0, in.read()); assertEquals(0, in.read()); assertEquals('C', in.read()); assertEquals(0, in.read()); assertEquals(0, in.read()); assertEquals(0, in.read()); assertEquals(-1, in.read()); assertTrue(in.hasBOM(), "hasBOM()"); assertTrue(in.hasBOM(ByteOrderMark.UTF_32LE), "hasBOM(UTF-32LE)"); assertEquals(ByteOrderMark.UTF_32LE, in.getBOM(), "getBOM"); try { in.hasBOM(ByteOrderMark.UTF_32BE); fail("Expected IllegalArgumentException"); } catch (final IllegalArgumentException e) { // expected - not configured for UTF-32BE } } } @Test public void testReadWithBOMUtf8() throws Exception { final byte[] data = "ABC".getBytes(StandardCharsets.UTF_8); try (final BOMInputStream in = new BOMInputStream(createUtf8DataStream(data, true), ByteOrderMark.UTF_8)) { assertEquals('A', in.read()); assertEquals('B', in.read()); assertEquals('C', in.read()); assertEquals(-1, in.read()); assertTrue(in.hasBOM(), "hasBOM()"); assertTrue(in.hasBOM(ByteOrderMark.UTF_8), "hasBOM(UTF-8)"); assertEquals(ByteOrderMark.UTF_8, in.getBOM(), "getBOM"); try { in.hasBOM(ByteOrderMark.UTF_16BE); fail("Expected IllegalArgumentException"); } catch (final IllegalArgumentException e) { // expected - not configured for UTF-16BE } } } @Test public void testReadWithMultipleBOM() throws Exception { final byte[] data = { 'A', 'B', 'C' }; try (final BOMInputStream in = new BOMInputStream(createUtf8DataStream(data, true), ByteOrderMark.UTF_16BE, ByteOrderMark.UTF_8)) { assertEquals('A', in.read()); assertEquals('B', in.read()); assertEquals('C', in.read()); assertEquals(-1, in.read()); assertTrue(in.hasBOM(), "hasBOM()"); assertTrue(in.hasBOM(ByteOrderMark.UTF_8), "hasBOM(UTF-8)"); assertFalse(in.hasBOM(ByteOrderMark.UTF_16BE), "hasBOM(UTF-16BE)"); assertEquals(ByteOrderMark.UTF_8, in.getBOM(), "getBOM"); } } @Test public void testReadWithoutBOM() throws Exception { final byte[] data = { 'A', 'B', 'C' }; try (final BOMInputStream in = new BOMInputStream(createUtf8DataStream(data, false))) { assertEquals('A', in.read()); assertEquals('B', in.read()); assertEquals('C', in.read()); assertEquals(-1, in.read()); assertFalse(in.hasBOM(), "hasBOM()"); assertFalse(in.hasBOM(ByteOrderMark.UTF_8), "hasBOM(UTF-8)"); assertNull(in.getBOM(), "getBOM"); } } @Test public void testReadXmlWithBOMUcs2() throws Exception { assumeFalse(System.getProperty("java.vendor").contains("IBM"), "This test does not pass on some IBM VMs xml parsers"); // UCS-2 is BE. assumeTrue(Charset.isSupported("ISO-10646-UCS-2")); final byte[] data = "".getBytes("ISO-10646-UCS-2"); try (BOMInputStream in = new BOMInputStream(createUtf16BeDataStream(data, true), ByteOrderMark.UTF_16BE)) { parseXml(in); } parseXml(createUtf16BeDataStream(data, true)); } @Test public void testReadXmlWithBOMUcs4() throws Exception { // UCS-4 is BE or LE? // Hm: ISO-10646-UCS-4 is not supported on Oracle 1.6.0_31 assumeTrue(Charset.isSupported("ISO-10646-UCS-4")); final byte[] data = "".getBytes("ISO-10646-UCS-4"); // XML parser does not know what to do with UTF-32 try (BOMInputStream in = new BOMInputStream(createUtf32BeDataStream(data, true), ByteOrderMark.UTF_32BE)) { parseXml(in); // XML parser does not know what to do with UTF-32 assumeTrue(jvmAndSaxBothSupportCharset("UTF_32LE"), "JVM and SAX need to support UTF_32LE for this"); } parseXml(createUtf32BeDataStream(data, true)); } @Test public void testReadXmlWithBOMUtf16Be() throws Exception { final byte[] data = "".getBytes(StandardCharsets.UTF_16BE); try (BOMInputStream in = new BOMInputStream(createUtf16BeDataStream(data, true), ByteOrderMark.UTF_16BE)) { parseXml(in); } parseXml(createUtf16BeDataStream(data, true)); } @Test public void testReadXmlWithBOMUtf16Le() throws Exception { final byte[] data = "".getBytes(StandardCharsets.UTF_16LE); try (BOMInputStream in = new BOMInputStream(createUtf16LeDataStream(data, true), ByteOrderMark.UTF_16LE)) { parseXml(in); } parseXml(createUtf16LeDataStream(data, true)); } @Test public void testReadXmlWithBOMUtf32Be() throws Exception { assumeTrue(jvmAndSaxBothSupportCharset("UTF_32BE"), "JVM and SAX need to support UTF_32BE for this"); final byte[] data = "".getBytes("UTF_32BE"); try (BOMInputStream in = new BOMInputStream(createUtf32BeDataStream(data, true), ByteOrderMark.UTF_32BE)) { parseXml(in); } // XML parser does not know what to do with UTF-32, so we warp the input stream with a XmlStreamReader try (XmlStreamReader in = new XmlStreamReader(createUtf32BeDataStream(data, true))) { parseXml(in); } } @Test public void testReadXmlWithBOMUtf32Le() throws Exception { assumeTrue(jvmAndSaxBothSupportCharset("UTF_32LE"), "JVM and SAX need to support UTF_32LE for this"); final byte[] data = "".getBytes("UTF_32LE"); try (BOMInputStream in = new BOMInputStream(createUtf32LeDataStream(data, true), ByteOrderMark.UTF_32LE)) { parseXml(in); } // XML parser does not know what to do with UTF-32, so we warp the input stream with a XmlStreamReader try (XmlStreamReader in = new XmlStreamReader(createUtf32LeDataStream(data, true))) { parseXml(in); } } @Test public void testReadXmlWithBOMUtf8() throws Exception { final byte[] data = "".getBytes(StandardCharsets.UTF_8); try (BOMInputStream in = new BOMInputStream(createUtf8DataStream(data, true))) { parseXml(in); } parseXml(createUtf8DataStream(data, true)); } @Test public void testReadXmlWithoutBOMUtf32Be() throws Exception { assumeTrue(jvmAndSaxBothSupportCharset("UTF_32BE"), "JVM and SAX need to support UTF_32BE for this"); final byte[] data = "".getBytes("UTF_32BE"); try (BOMInputStream in = new BOMInputStream(createUtf32BeDataStream(data, false))) { parseXml(in); } parseXml(createUtf32BeDataStream(data, false)); } @Test public void testReadXmlWithoutBOMUtf32Le() throws Exception { assumeTrue(jvmAndSaxBothSupportCharset("UTF_32LE"), "JVM and SAX need to support UTF_32LE for this"); final byte[] data = "".getBytes("UTF_32LE"); try (BOMInputStream in = new BOMInputStream(createUtf32LeDataStream(data, false))) { parseXml(in); } parseXml(createUtf32BeDataStream(data, false)); } @Test public void testSkipWithBOM() throws Exception { final byte[] data = { 'A', 'B', 'C', 'D' }; try (final InputStream in = new BOMInputStream(createUtf8DataStream(data, true))) { in.skip(2L); assertEquals('C', in.read()); } } @Test public void testSkipWithoutBOM() throws Exception { final byte[] data = { 'A', 'B', 'C', 'D' }; try (final InputStream in = new BOMInputStream(createUtf8DataStream(data, false))) { in.skip(2L); assertEquals('C', in.read()); } } @Test public void skipReturnValueWithBom() throws IOException { final byte[] baseData = { (byte) 0x31, (byte) 0x32, (byte) 0x33 }; try (final BOMInputStream is1 = new BOMInputStream(createUtf8DataStream(baseData, true))) { assertEquals(2, is1.skip(2)); assertEquals((byte) 0x33, is1.read()); } } @Test public void skipReturnValueWithoutBom() throws IOException { final byte[] baseData = { (byte) 0x31, (byte) 0x32, (byte) 0x33 }; try (final BOMInputStream is2 = new BOMInputStream(createUtf8DataStream(baseData, false))) { assertEquals(2, is2.skip(2)); // IO-428 assertEquals((byte) 0x33, is2.read()); } } @Test public void testSmallBufferWithBOM() throws Exception { final byte[] data = { 'A', 'B', 'C' }; try (final InputStream in = new BOMInputStream(createUtf8DataStream(data, true))) { final byte[] buf = new byte[1024]; assertData(new byte[] { 'A', 'B' }, buf, in.read(buf, 0, 2)); assertData(new byte[] { 'C' }, buf, in.read(buf, 0, 2)); } } @Test public void testSmallBufferWithoutBOM() throws Exception { final byte[] data = { 'A', 'B', 'C' }; try (final InputStream in = new BOMInputStream(createUtf8DataStream(data, false))) { final byte[] buf = new byte[1024]; assertData(new byte[] { 'A', 'B' }, buf, in.read(buf, 0, 2)); assertData(new byte[] { 'C' }, buf, in.read(buf, 0, 2)); } } @Test // make sure that our support code works as expected public void testSupportCode() throws Exception { try (final InputStream in = createUtf8DataStream(new byte[] { 'A', 'B' }, true)) { final byte[] buf = new byte[1024]; final int len = in.read(buf); assertEquals(5, len); assertEquals(0xEF, buf[0] & 0xFF); assertEquals(0xBB, buf[1] & 0xFF); assertEquals(0xBF, buf[2] & 0xFF); assertEquals('A', buf[3] & 0xFF); assertEquals('B', buf[4] & 0xFF); assertData(new byte[] { (byte) 0xEF, (byte) 0xBB, (byte) 0xBF, 'A', 'B' }, buf, len); } } private boolean jvmAndSaxBothSupportCharset(final String charSetName) throws ParserConfigurationException, SAXException, IOException { return Charset.isSupported(charSetName) && doesSaxSupportCharacterSet(charSetName); } private boolean doesSaxSupportCharacterSet(final String charSetName) throws ParserConfigurationException, SAXException, IOException { final byte[] data = ("").getBytes(charSetName); final DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); try { final InputSource is = new InputSource(new ByteArrayInputStream(data)); is.setEncoding(charSetName); documentBuilder.parse(is); } catch (final SAXParseException e) { if (e.getMessage().contains(charSetName)) { return false; } } return true; } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/BoundedInputStreamTest.java0100644 0000000 0000000 00000007224 13612062727 032211 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.junit.jupiter.api.Assertions.assertEquals; import java.io.ByteArrayInputStream; import org.apache.commons.io.IOUtils; import org.junit.jupiter.api.Test; /** * Tests for {@link BoundedInputStream}. * */ public class BoundedInputStreamTest { @Test public void testReadSingle() throws Exception { BoundedInputStream bounded; final byte[] helloWorld = "Hello World".getBytes(); final byte[] hello = "Hello".getBytes(); // limit = length bounded = new BoundedInputStream(new ByteArrayInputStream(helloWorld), helloWorld.length); for (int i = 0; i < helloWorld.length; i++) { assertEquals(helloWorld[i], bounded.read(), "limit = length byte[" + i + "]"); } assertEquals(-1, bounded.read(), "limit = length end"); // limit > length bounded = new BoundedInputStream(new ByteArrayInputStream(helloWorld), helloWorld.length + 1); for (int i = 0; i < helloWorld.length; i++) { assertEquals(helloWorld[i], bounded.read(), "limit > length byte[" + i + "]"); } assertEquals(-1, bounded.read(), "limit > length end"); // limit < length bounded = new BoundedInputStream(new ByteArrayInputStream(helloWorld), hello.length); for (int i = 0; i < hello.length; i++) { assertEquals(hello[i], bounded.read(), "limit < length byte[" + i + "]"); } assertEquals(-1, bounded.read(), "limit < length end"); } @Test public void testReadArray() throws Exception { BoundedInputStream bounded; final byte[] helloWorld = "Hello World".getBytes(); final byte[] hello = "Hello".getBytes(); bounded = new BoundedInputStream(new ByteArrayInputStream(helloWorld)); compare("limit = -1", helloWorld, IOUtils.toByteArray(bounded)); bounded = new BoundedInputStream(new ByteArrayInputStream(helloWorld), 0); compare("limit = 0", IOUtils.EMPTY_BYTE_ARRAY, IOUtils.toByteArray(bounded)); bounded = new BoundedInputStream(new ByteArrayInputStream(helloWorld), helloWorld.length); compare("limit = length", helloWorld, IOUtils.toByteArray(bounded)); bounded = new BoundedInputStream(new ByteArrayInputStream(helloWorld), helloWorld.length + 1); compare("limit > length", helloWorld, IOUtils.toByteArray(bounded)); bounded = new BoundedInputStream(new ByteArrayInputStream(helloWorld), helloWorld.length - 6); compare("limit < length", hello, IOUtils.toByteArray(bounded)); } private void compare(final String msg, final byte[] expected, final byte[] actual) { assertEquals(expected.length, actual.length, msg + " length"); for (int i = 0; i < expected.length; i++) { assertEquals(expected[i], actual[i], msg + " byte[" + i + "]"); } } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/BoundedReaderTest.java0100644 0000000 0000000 00000017022 13612062727 031135 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.commons.io.input; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTimeout; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.LineNumberReader; import java.io.Reader; import java.io.StringReader; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.time.Duration; import java.util.Arrays; import java.util.concurrent.atomic.AtomicBoolean; import org.apache.commons.io.FileUtils; import org.junit.jupiter.api.Test; public class BoundedReaderTest { private static final String STRING_END_NO_EOL = "0\n1\n2"; private static final String STRING_END_EOL = "0\n1\n2\n"; private final Reader sr = new BufferedReader(new StringReader("01234567890")); private final Reader shortReader = new BufferedReader(new StringReader("01")); @Test public void readTillEnd() throws IOException { try (final BoundedReader mr = new BoundedReader(sr, 3)) { mr.read(); mr.read(); mr.read(); assertEquals(-1, mr.read()); } } @Test public void shortReader() throws IOException { try (final BoundedReader mr = new BoundedReader(shortReader, 3)) { mr.read(); mr.read(); assertEquals(-1, mr.read()); } } @Test public void readMulti() throws IOException { try (final BoundedReader mr = new BoundedReader(sr, 3)) { final char[] cbuf = new char[4]; Arrays.fill(cbuf, 'X'); final int read = mr.read(cbuf, 0, 4); assertEquals(3, read); assertEquals('0', cbuf[0]); assertEquals('1', cbuf[1]); assertEquals('2', cbuf[2]); assertEquals('X', cbuf[3]); } } @Test public void readMultiWithOffset() throws IOException { try (final BoundedReader mr = new BoundedReader(sr, 3)) { final char[] cbuf = new char[4]; Arrays.fill(cbuf, 'X'); final int read = mr.read(cbuf, 1, 2); assertEquals(2, read); assertEquals('X', cbuf[0]); assertEquals('0', cbuf[1]); assertEquals('1', cbuf[2]); assertEquals('X', cbuf[3]); } } @Test public void markReset() throws IOException { try (final BoundedReader mr = new BoundedReader(sr, 3)) { mr.mark(3); mr.read(); mr.read(); mr.read(); mr.reset(); mr.read(); mr.read(); mr.read(); assertEquals(-1, mr.read()); } } @Test public void markResetWithMarkOutsideBoundedReaderMax() throws IOException { try (final BoundedReader mr = new BoundedReader(sr, 3)) { mr.mark(4); mr.read(); mr.read(); mr.read(); assertEquals(-1, mr.read()); } } @Test public void markResetWithMarkOutsideBoundedReaderMaxAndInitialOffset() throws IOException { try (final BoundedReader mr = new BoundedReader(sr, 3)) { mr.read(); mr.mark(3); mr.read(); mr.read(); assertEquals(-1, mr.read()); } } @Test public void markResetFromOffset1() throws IOException { try (final BoundedReader mr = new BoundedReader(sr, 3)) { mr.mark(3); mr.read(); mr.read(); mr.read(); assertEquals(-1, mr.read()); mr.reset(); mr.mark(1); mr.read(); assertEquals(-1, mr.read()); } } @Test public void markResetMarkMore() throws IOException { try (final BoundedReader mr = new BoundedReader(sr, 3)) { mr.mark(4); mr.read(); mr.read(); mr.read(); mr.reset(); mr.read(); mr.read(); mr.read(); assertEquals(-1, mr.read()); } } @Test public void skipTest() throws IOException { try (final BoundedReader mr = new BoundedReader(sr, 3)) { mr.skip(2); mr.read(); assertEquals(-1, mr.read()); } } @Test public void closeTest() throws IOException { final AtomicBoolean closed = new AtomicBoolean(false); try (final Reader sr = new BufferedReader(new StringReader("01234567890")) { @Override public void close() throws IOException { closed.set(true); super.close(); } }) { try (final BoundedReader mr = new BoundedReader(sr, 3)) { // nothing } } assertTrue(closed.get()); } private void testLineNumberReader(final Reader source) throws IOException { try (LineNumberReader reader = new LineNumberReader(new BoundedReader(source, 10_000_000))) { while (reader.readLine() != null) { // noop } } } @Test public void testLineNumberReaderAndStringReaderLastLineEolNo() { assertTimeout(Duration.ofMillis(5000), () -> testLineNumberReader(new StringReader(STRING_END_NO_EOL))); } @Test public void testLineNumberReaderAndStringReaderLastLineEolYes() { assertTimeout(Duration.ofMillis(5000), () -> testLineNumberReader(new StringReader(STRING_END_EOL))); } @Test public void testLineNumberReaderAndFileReaderLastLineEolNo() { assertTimeout(Duration.ofMillis(5000), () -> testLineNumberReaderAndFileReaderLastLine(STRING_END_NO_EOL)); } @Test public void testLineNumberReaderAndFileReaderLastLineEolYes() { assertTimeout(Duration.ofMillis(5000), () -> testLineNumberReaderAndFileReaderLastLine(STRING_END_EOL)); } public void testLineNumberReaderAndFileReaderLastLine(final String data) throws IOException { final Path path = Files.createTempFile(getClass().getSimpleName(), ".txt"); try { final File file = path.toFile(); FileUtils.write(file, data, StandardCharsets.ISO_8859_1); try (Reader source = Files.newBufferedReader(file.toPath())) { testLineNumberReader(source); } } finally { Files.delete(path); } } @Test public void testReadBytesEOF() { assertTimeout(Duration.ofMillis(5000), () -> { final BoundedReader mr = new BoundedReader(sr, 3); try (BufferedReader br = new BufferedReader(mr)) { br.readLine(); br.readLine(); } }); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/BrokenInputStreamTest.java0100644 0000000 0000000 00000005707 13612062727 032055 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; import java.io.IOException; import java.io.InputStream; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * JUnit Test Case for {@link BrokenInputStream}. */ @SuppressWarnings("ResultOfMethodCallIgnored") public class BrokenInputStreamTest { private IOException exception; private InputStream stream; @BeforeEach public void setUp() { exception = new IOException("test exception"); stream = new BrokenInputStream(exception); } @Test public void testRead() { try { stream.read(); fail("Expected exception not thrown."); } catch (final IOException e) { assertEquals(exception, e); } try { stream.read(new byte[1]); fail("Expected exception not thrown."); } catch (final IOException e) { assertEquals(exception, e); } try { stream.read(new byte[1], 0, 1); fail("Expected exception not thrown."); } catch (final IOException e) { assertEquals(exception, e); } } @Test public void testAvailable() { try { stream.available(); fail("Expected exception not thrown."); } catch (final IOException e) { assertEquals(exception, e); } } @Test public void testSkip() { try { stream.skip(1); fail("Expected exception not thrown."); } catch (final IOException e) { assertEquals(exception, e); } } @Test public void testReset() { try { stream.reset(); fail("Expected exception not thrown."); } catch (final IOException e) { assertEquals(exception, e); } } @Test public void testClose() { try { stream.close(); fail("Expected exception not thrown."); } catch (final IOException e) { assertEquals(exception, e); } } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/BrokenReaderTest.java0100644 0000000 0000000 00000006214 13612062727 030776 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; import java.io.IOException; import java.io.Reader; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * JUnit Test Case for {@link BrokenReader}. */ @SuppressWarnings("ResultOfMethodCallIgnored") public class BrokenReaderTest { private IOException exception; private Reader reader; @BeforeEach public void setUp() { exception = new IOException("test exception"); reader = new BrokenReader(exception); } @Test public void testRead() { try { reader.read(); fail("Expected exception not thrown."); } catch (final IOException e) { assertEquals(exception, e); } try { reader.read(new char[1]); fail("Expected exception not thrown."); } catch (final IOException e) { assertEquals(exception, e); } try { reader.read(new char[1], 0, 1); fail("Expected exception not thrown."); } catch (final IOException e) { assertEquals(exception, e); } } @Test public void testSkip() { try { reader.skip(1); fail("Expected exception not thrown."); } catch (final IOException e) { assertEquals(exception, e); } } @Test public void testReady() { try { reader.ready(); fail("Expected exception not thrown."); } catch (final IOException e) { assertEquals(exception, e); } } @Test public void testMark() { try { reader.mark(1); fail("Expected exception not thrown."); } catch (final IOException e) { assertEquals(exception, e); } } @Test public void testReset() { try { reader.reset(); fail("Expected exception not thrown."); } catch (final IOException e) { assertEquals(exception, e); } } @Test public void testClose() { try { reader.close(); fail("Expected exception not thrown."); } catch (final IOException e) { assertEquals(exception, e); } } } ././@LongLink0100644 0000000 0000000 00000000150 13612062727 011635 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/BufferedFileChannelInputStreamTest.javacommons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/BufferedFileChannelInputStreamTest.j0100644 0000000 0000000 00000003211 13612062727 033744 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import java.io.IOException; import java.io.InputStream; import org.junit.jupiter.api.BeforeEach; /** * Tests functionality of {@link BufferedFileChannelInputStream}. * * This class was ported and adapted from Apache Spark commit 933dc6cb7b3de1d8ccaf73d124d6eb95b947ed19 where it was * called {@code BufferedFileChannelInputStreamSuite}. */ public class BufferedFileChannelInputStreamTest extends AbstractInputStreamTest { @SuppressWarnings("resource") @Override @BeforeEach public void setUp() throws IOException { super.setUp(); // @formatter:off inputStreams = new InputStream[] { new BufferedFileChannelInputStream(inputFile), // default new BufferedFileChannelInputStream(inputFile, 123) // small, unaligned buffer }; //@formatter:on } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/CharSequenceInputStreamTest.java0100644 0000000 0000000 00000037315 13612062727 033203 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import java.io.IOException; import java.io.InputStream; import java.nio.charset.Charset; import java.util.Random; import java.util.Set; import org.apache.commons.io.Charsets; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; public class CharSequenceInputStreamTest { private static final String ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; private static final String LARGE_TEST_STRING; private static final String TEST_STRING = "\u00e0 peine arriv\u00e9s nous entr\u00e2mes dans sa chambre"; static { final StringBuilder buffer = new StringBuilder(); for (int i = 0; i < 100; i++) { buffer.append(TEST_STRING); } LARGE_TEST_STRING = buffer.toString(); } private final Random random = new Random(); private Set getRequiredCharsetNames() { return Charsets.requiredCharsets().keySet(); } private void testBufferedRead(final String testString, final String charsetName) throws IOException { final byte[] expected = testString.getBytes(charsetName); try (InputStream in = new CharSequenceInputStream(testString, charsetName, 512)) { final byte[] buffer = new byte[128]; int offset = 0; while (true) { int bufferOffset = random.nextInt(64); final int bufferLength = random.nextInt(64); int read = in.read(buffer, bufferOffset, bufferLength); if (read == -1) { assertEquals(expected.length, offset, "EOF: offset should equal length for charset " + charsetName); break; } assertTrue(read <= bufferLength, "Read " + read + " <= " + bufferLength); while (read > 0) { assertTrue(offset < expected.length, "offset for " + charsetName + " " + offset + " < " + expected.length); assertEquals(expected[offset], buffer[bufferOffset], "bytes should agree for " + charsetName); offset++; bufferOffset++; read--; } } } } // Unfortunately checking canEncode does not seem to work for all charsets: // testBufferedRead_AvailableCharset(org.apache.commons.io.input.CharSequenceInputStreamTest) Time elapsed: 0.682 sec <<< ERROR! // java.lang.UnsupportedOperationException: null // at java.nio.CharBuffer.array(CharBuffer.java:940) // at sun.nio.cs.ext.COMPOUND_TEXT_Encoder.encodeLoop(COMPOUND_TEXT_Encoder.java:75) // at java.nio.charset.CharsetEncoder.encode(CharsetEncoder.java:544) // at org.apache.commons.io.input.CharSequenceInputStream.fillBuffer(CharSequenceInputStream.java:111) @Test public void testBufferedRead_AvailableCharset() throws IOException { for (final String csName : Charset.availableCharsets().keySet()) { // prevent java.lang.UnsupportedOperationException at sun.nio.cs.ext.ISO2022_CN.newEncoder. if (isAvailabilityTestableForCharset(csName)) { testBufferedRead(TEST_STRING, csName); } } } @Test public void testBufferedRead_RequiredCharset() throws IOException { for (final String csName : getRequiredCharsetNames()) { testBufferedRead(TEST_STRING, csName); } } @Test public void testBufferedRead_UTF8() throws IOException { testBufferedRead(TEST_STRING, "UTF-8"); } private void testCharsetMismatchInfiniteLoop(final String csName) throws IOException { // Input is UTF-8 bytes: 0xE0 0xB2 0xA0 final char[] inputChars = { (char) 0xE0, (char) 0xB2, (char) 0xA0 }; final Charset charset = Charset.forName(csName); // infinite loop for US-ASCII, UTF-8 OK try (InputStream stream = new CharSequenceInputStream(new String(inputChars), charset, 512)) { while (stream.read() != -1) { } } } @Test public void testCharsetMismatchInfiniteLoop_RequiredCharsets() throws IOException { for (final String csName : getRequiredCharsetNames()) { testCharsetMismatchInfiniteLoop(csName); } } // Test is broken if readFirst > 0 // This is because the initial read fills the buffer from the CharSequence // so data1 gets the first buffer full; data2 will get the next buffer full private void testIO_356(final int bufferSize, final int dataSize, final int readFirst, final String csName) throws Exception { final CharSequenceInputStream is = new CharSequenceInputStream(ALPHABET, csName, bufferSize); for (int i = 0; i < readFirst; i++) { final int ch = is.read(); assertNotEquals(-1, ch); } is.mark(dataSize); final byte[] data1 = new byte[dataSize]; final int readCount1 = is.read(data1); assertEquals(dataSize, readCount1); is.reset(); // should allow data to be re-read final byte[] data2 = new byte[dataSize]; final int readCount2 = is.read(data2); assertEquals(dataSize, readCount2); is.close(); // data buffers should be identical assertArrayEquals(data1, data2, "bufferSize=" + bufferSize + " dataSize=" + dataSize); } @Test public void testIO_356_B10_D10_S0_UTF16() throws Exception { testIO_356(10, 10, 0, "UTF-16"); } @Test public void testIO_356_B10_D10_S0_UTF8() throws Exception { testIO_356(10, 10, 0, "UTF-8"); } @Test public void testIO_356_B10_D10_S1_UTF8() throws Exception { testIO_356(10, 10, 1, "UTF-8"); } @Test public void testIO_356_B10_D10_S2_UTF8() throws Exception { testIO_356(10, 10, 2, "UTF-8"); } @Test public void testIO_356_B10_D13_S0_UTF8() throws Exception { testIO_356(10, 13, 0, "UTF-8"); } @Test public void testIO_356_B10_D13_S1_UTF8() throws Exception { testIO_356(10, 13, 1, "UTF-8"); } @Test public void testIO_356_B10_D20_S0_UTF8() throws Exception { testIO_356(10, 20, 0, "UTF-8"); } private void testIO_356_Loop(final String csName, final int maxBytesPerChar) throws Exception { for (int bufferSize = maxBytesPerChar; bufferSize <= 10; bufferSize++) { for (int dataSize = 1; dataSize <= 20; dataSize++) { testIO_356(bufferSize, dataSize, 0, csName); } } } @Test public void testIO_356_Loop_UTF16() throws Exception { testIO_356_Loop("UTF-16", 4); } @Test public void testIO_356_Loop_UTF8() throws Exception { testIO_356_Loop("UTF-8", 4); } @Test public void testLargeBufferedRead_RequiredCharsets() throws IOException { for (final String csName : getRequiredCharsetNames()) { testBufferedRead(LARGE_TEST_STRING, csName); } } @Test public void testLargeBufferedRead_UTF8() throws IOException { testBufferedRead(LARGE_TEST_STRING, "UTF-8"); } @Test public void testLargeSingleByteRead_RequiredCharsets() throws IOException { for (final String csName : getRequiredCharsetNames()) { testSingleByteRead(LARGE_TEST_STRING, csName); } } @Test public void testLargeSingleByteRead_UTF8() throws IOException { testSingleByteRead(LARGE_TEST_STRING, "UTF-8"); } // This test is broken for charsets that don't create a single byte for each char private void testMarkReset(final String csName) throws Exception { try (InputStream r = new CharSequenceInputStream("test", csName)) { assertEquals(2, r.skip(2)); r.mark(0); assertEquals('s', r.read(), csName); assertEquals('t', r.read(), csName); assertEquals(-1, r.read(), csName); r.reset(); assertEquals('s', r.read(), csName); assertEquals('t', r.read(), csName); assertEquals(-1, r.read(), csName); r.reset(); r.reset(); } } @Test @Disabled // Test broken for charsets that create multiple bytes for a single char public void testMarkReset_RequiredCharsets() throws Exception { for (final String csName : getRequiredCharsetNames()) { testMarkReset(csName); } } @Test public void testMarkReset_USASCII() throws Exception { testMarkReset("US-ASCII"); } @Test public void testMarkReset_UTF8() throws Exception { testMarkReset("UTF-8"); } @Test public void testMarkSupported() throws Exception { try (InputStream r = new CharSequenceInputStream("test", "UTF-8")) { assertTrue(r.markSupported()); } } private void testReadZero(final String csName) throws Exception { try (InputStream r = new CharSequenceInputStream("test", csName)) { final byte[] bytes = new byte[30]; assertEquals(0, r.read(bytes, 0, 0)); } } @Test public void testReadZero_EmptyString() throws Exception { try (InputStream r = new CharSequenceInputStream("", "UTF-8")) { final byte[] bytes = new byte[30]; assertEquals(0, r.read(bytes, 0, 0)); } } @Test public void testReadZero_RequiredCharsets() throws Exception { for (final String csName : getRequiredCharsetNames()) { testReadZero(csName); } } private void testSingleByteRead(final String testString, final String charsetName) throws IOException { final byte[] bytes = testString.getBytes(charsetName); try (InputStream in = new CharSequenceInputStream(testString, charsetName, 512)) { for (final byte b : bytes) { final int read = in.read(); assertTrue(read >= 0, "read " + read + " >=0 "); assertTrue(read <= 255, "read " + read + " <= 255"); assertEquals(b, (byte) read, "Should agree with input"); } assertEquals(-1, in.read()); } } @Test public void testSingleByteRead_RequiredCharsets() throws IOException { for (final String csName : getRequiredCharsetNames()) { testSingleByteRead(TEST_STRING, csName); } } @Test public void testSingleByteRead_UTF16() throws IOException { testSingleByteRead(TEST_STRING, "UTF-16"); } @Test public void testSingleByteRead_UTF8() throws IOException { testSingleByteRead(TEST_STRING, "UTF-8"); } // This is broken for charsets that don't map each char to a byte private void testSkip(final String csName) throws Exception { try (InputStream r = new CharSequenceInputStream("test", csName)) { assertEquals(1, r.skip(1)); assertEquals(2, r.skip(2)); assertEquals('t', r.read(), csName); r.skip(100); assertEquals(-1, r.read(), csName); } } @Test @Disabled // test is broken for charsets that generate multiple bytes per char. public void testSkip_RequiredCharsets() throws Exception { for (final String csName : getRequiredCharsetNames()) { testSkip(csName); } } @Test public void testSkip_USASCII() throws Exception { testSkip("US-ASCII"); } @Test public void testSkip_UTF8() throws Exception { testSkip("UTF-8"); } private int checkAvail(final InputStream is, final int min) throws Exception { final int available = is.available(); assertTrue(available >= min, "avail should be >= " + min + ", but was " + available); return available; } private void testAvailableSkip(final String csName) throws Exception { final String input = "test"; try (InputStream r = new CharSequenceInputStream(input, csName)) { int available = checkAvail(r, input.length()); assertEquals(available - 1, r.skip(available - 1)); // skip all but one available = checkAvail(r, 1); assertEquals(1, r.skip(1)); available = checkAvail(r, 0); } } private void testAvailableRead(final String csName) throws Exception { final String input = "test"; try (InputStream r = new CharSequenceInputStream(input, csName)) { int available = checkAvail(r, input.length()); assertEquals(available - 1, r.skip(available - 1)); // skip all but one available = checkAvail(r, 1); final byte[] buff = new byte[available]; assertEquals(available, r.read(buff, 0, available)); } } @Test public void testAvailable() throws Exception { for (final String csName : Charset.availableCharsets().keySet()) { // prevent java.lang.UnsupportedOperationException at sun.nio.cs.ext.ISO2022_CN.newEncoder. // also try and avoid the following Effor on Continuum // java.lang.UnsupportedOperationException: null // at java.nio.CharBuffer.array(CharBuffer.java:940) // at sun.nio.cs.ext.COMPOUND_TEXT_Encoder.encodeLoop(COMPOUND_TEXT_Encoder.java:75) // at java.nio.charset.CharsetEncoder.encode(CharsetEncoder.java:544) // at org.apache.commons.io.input.CharSequenceInputStream.fillBuffer(CharSequenceInputStream.java:120) // at org.apache.commons.io.input.CharSequenceInputStream.read(CharSequenceInputStream.java:151) // at org.apache.commons.io.input.CharSequenceInputStreamTest.testAvailableRead(CharSequenceInputStreamTest.java:412) // at org.apache.commons.io.input.CharSequenceInputStreamTest.testAvailable(CharSequenceInputStreamTest.java:424) try { if (isAvailabilityTestableForCharset(csName)) { testAvailableSkip(csName); testAvailableRead(csName); } } catch (final UnsupportedOperationException e){ fail("Operation not supported for " + csName); } } } private boolean isAvailabilityTestableForCharset(final String csName) { return Charset.forName(csName).canEncode() && !"COMPOUND_TEXT".equalsIgnoreCase(csName) && !"x-COMPOUND_TEXT".equalsIgnoreCase(csName) && !isOddBallLegacyCharsetThatDoesNotSupportFrenchCharacters(csName); } private boolean isOddBallLegacyCharsetThatDoesNotSupportFrenchCharacters(final String csName) { return "x-IBM1388".equalsIgnoreCase(csName) || "ISO-2022-CN".equalsIgnoreCase(csName) || "ISO-2022-JP".equalsIgnoreCase(csName) || "Shift_JIS".equalsIgnoreCase(csName); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/CharSequenceReaderTest.java0100644 0000000 0000000 00000030226 13612062727 032124 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Reader; import java.nio.CharBuffer; import java.util.Arrays; import org.apache.commons.io.TestResources; import org.junit.jupiter.api.Test; /** * Test case for {@link CharSequenceReader}. * */ public class CharSequenceReaderTest { private static final char NONE = (new char[1])[0]; @Test public void testClose() throws IOException { final Reader reader = new CharSequenceReader("FooBar"); checkRead(reader, "Foo"); reader.close(); checkRead(reader, "Foo"); final Reader subReader = new CharSequenceReader("xFooBarx", 1, 7); checkRead(subReader, "Foo"); subReader.close(); checkRead(subReader, "Foo"); } @Test public void testReady() throws IOException { final Reader reader = new CharSequenceReader("FooBar"); assertTrue(reader.ready()); reader.skip(3); assertTrue(reader.ready()); checkRead(reader, "Bar"); assertFalse(reader.ready()); reader.reset(); assertTrue(reader.ready()); reader.skip(2); assertTrue(reader.ready()); reader.skip(10); assertFalse(reader.ready()); reader.close(); assertTrue(reader.ready()); reader.skip(20); assertFalse(reader.ready()); final Reader subReader = new CharSequenceReader("xFooBarx", 1, 7); assertTrue(subReader.ready()); subReader.skip(3); assertTrue(subReader.ready()); checkRead(subReader, "Bar"); assertFalse(subReader.ready()); subReader.reset(); assertTrue(subReader.ready()); subReader.skip(2); assertTrue(subReader.ready()); subReader.skip(10); assertFalse(subReader.ready()); subReader.close(); assertTrue(subReader.ready()); subReader.skip(20); assertFalse(subReader.ready()); } @Test public void testMarkSupported() throws Exception { try (final Reader reader = new CharSequenceReader("FooBar")) { assertTrue(reader.markSupported()); } } @Test public void testMark() throws IOException { try (final Reader reader = new CharSequenceReader("FooBar")) { checkRead(reader, "Foo"); reader.mark(0); checkRead(reader, "Bar"); reader.reset(); checkRead(reader, "Bar"); reader.close(); checkRead(reader, "Foo"); reader.reset(); checkRead(reader, "Foo"); } try (final Reader subReader = new CharSequenceReader("xFooBarx", 1, 7)) { checkRead(subReader, "Foo"); subReader.mark(0); checkRead(subReader, "Bar"); subReader.reset(); checkRead(subReader, "Bar"); subReader.close(); checkRead(subReader, "Foo"); subReader.reset(); checkRead(subReader, "Foo"); } } @Test public void testSkip() throws IOException { final Reader reader = new CharSequenceReader("FooBar"); assertEquals(3, reader.skip(3)); checkRead(reader, "Bar"); assertEquals(0, reader.skip(3)); reader.reset(); assertEquals(2, reader.skip(2)); assertEquals(4, reader.skip(10)); assertEquals(0, reader.skip(1)); reader.close(); assertEquals(6, reader.skip(20)); assertEquals(-1, reader.read()); final Reader subReader = new CharSequenceReader("xFooBarx", 1, 7); assertEquals(3, subReader.skip(3)); checkRead(subReader, "Bar"); assertEquals(0, subReader.skip(3)); subReader.reset(); assertEquals(2, subReader.skip(2)); assertEquals(4, subReader.skip(10)); assertEquals(0, subReader.skip(1)); subReader.close(); assertEquals(6, subReader.skip(20)); assertEquals(-1, subReader.read()); } @Test public void testRead() throws IOException { final String value = "Foo"; testRead(value); testRead(new StringBuilder(value)); testRead(new StringBuffer(value)); testRead(CharBuffer.wrap(value)); } private void testRead(final CharSequence charSequence) throws IOException { try (final Reader reader = new CharSequenceReader(charSequence)) { assertEquals('F', reader.read()); assertEquals('o', reader.read()); assertEquals('o', reader.read()); assertEquals(-1, reader.read()); assertEquals(-1, reader.read()); } try (final Reader reader = new CharSequenceReader(charSequence, 1, 5)) { assertEquals('o', reader.read()); assertEquals('o', reader.read()); assertEquals(-1, reader.read()); assertEquals(-1, reader.read()); } } @Test public void testReadCharArray() throws IOException { final String value = "FooBar"; testReadCharArray(value); testReadCharArray(new StringBuilder(value)); testReadCharArray(new StringBuffer(value)); testReadCharArray(CharBuffer.wrap(value)); } private void testReadCharArray(final CharSequence charSequence) throws IOException { try (final Reader reader = new CharSequenceReader(charSequence)) { char[] chars = new char[2]; assertEquals(2, reader.read(chars)); checkArray(new char[] { 'F', 'o' }, chars); chars = new char[3]; assertEquals(3, reader.read(chars)); checkArray(new char[] { 'o', 'B', 'a' }, chars); chars = new char[3]; assertEquals(1, reader.read(chars)); checkArray(new char[] { 'r', NONE, NONE }, chars); assertEquals(-1, reader.read(chars)); } try (final Reader reader = new CharSequenceReader(charSequence, 1, 5)) { char[] chars = new char[2]; assertEquals(2, reader.read(chars)); checkArray(new char[] { 'o', 'o' }, chars); chars = new char[3]; assertEquals(2, reader.read(chars)); checkArray(new char[] { 'B', 'a', NONE }, chars); chars = new char[3]; assertEquals(-1, reader.read(chars)); checkArray(new char[] { NONE, NONE, NONE }, chars); assertEquals(-1, reader.read(chars)); } } @Test public void testReadCharArrayPortion() throws IOException { final String value = "FooBar"; testReadCharArrayPortion(value); testReadCharArrayPortion(new StringBuilder(value)); testReadCharArrayPortion(new StringBuffer(value)); testReadCharArrayPortion(CharBuffer.wrap(value)); } private void testReadCharArrayPortion(final CharSequence charSequence) throws IOException { final char[] chars = new char[10]; try (final Reader reader = new CharSequenceReader(charSequence)) { assertEquals(3, reader.read(chars, 3, 3)); checkArray(new char[] { NONE, NONE, NONE, 'F', 'o', 'o' }, chars); assertEquals(3, reader.read(chars, 0, 3)); checkArray(new char[] { 'B', 'a', 'r', 'F', 'o', 'o', NONE }, chars); assertEquals(-1, reader.read(chars)); } Arrays.fill(chars, NONE); try (final Reader reader = new CharSequenceReader(charSequence, 1, 5)) { assertEquals(2, reader.read(chars, 3, 2)); checkArray(new char[] { NONE, NONE, NONE, 'o', 'o', NONE }, chars); assertEquals(2, reader.read(chars, 0, 3)); checkArray(new char[] { 'B', 'a', NONE, 'o', 'o', NONE }, chars); assertEquals(-1, reader.read(chars)); } } private void checkRead(final Reader reader, final String expected) throws IOException { for (int i = 0; i < expected.length(); i++) { assertEquals(expected.charAt(i), (char)reader.read(), "Read[" + i + "] of '" + expected + "'"); } } private void checkArray(final char[] expected, final char[] actual) { for (int i = 0; i < expected.length; i++) { assertEquals(expected[i], actual[i], "Compare[" +i + "]"); } } @Test public void testConstructor() { assertThrows(IllegalArgumentException.class, () -> new CharSequenceReader("FooBar", -1, 6), "Expected exception not thrown for negative start."); assertThrows(IllegalArgumentException.class, () -> new CharSequenceReader("FooBar", 1, 0), "Expected exception not thrown for end before start."); } @Test @SuppressWarnings("resource") // don't really need to close CharSequenceReader here public void testToString() { assertEquals("FooBar", new CharSequenceReader("FooBar").toString()); assertEquals("FooBar", new CharSequenceReader("xFooBarx", 1, 7).toString()); } @Test public void testSerialization() throws IOException, ClassNotFoundException { /* * File CharSequenceReader.bin contains a CharSequenceReader that was serialized before * the start and end fields were added. Its CharSequence is "FooBar". * This part of the test will test that adding the fields does not break any existing * serialized CharSequenceReaders. */ try (ObjectInputStream ois = new ObjectInputStream(TestResources.getInputStream("CharSequenceReader.bin"))) { final CharSequenceReader reader = (CharSequenceReader) ois.readObject(); assertEquals('F', reader.read()); assertEquals('o', reader.read()); assertEquals('o', reader.read()); assertEquals('B', reader.read()); assertEquals('a', reader.read()); assertEquals('r', reader.read()); assertEquals(-1, reader.read()); assertEquals(-1, reader.read()); } final ByteArrayOutputStream baos = new ByteArrayOutputStream(); try (ObjectOutputStream oos = new ObjectOutputStream(baos)) { final CharSequenceReader reader = new CharSequenceReader("xFooBarx", 1, 7); oos.writeObject(reader); } try (ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()))) { final CharSequenceReader reader = (CharSequenceReader) ois.readObject(); assertEquals('F', reader.read()); assertEquals('o', reader.read()); assertEquals('o', reader.read()); assertEquals('B', reader.read()); assertEquals('a', reader.read()); assertEquals('r', reader.read()); assertEquals(-1, reader.read()); assertEquals(-1, reader.read()); reader.reset(); assertEquals('F', reader.read()); assertEquals('o', reader.read()); assertEquals('o', reader.read()); assertEquals('B', reader.read()); assertEquals('a', reader.read()); assertEquals('r', reader.read()); assertEquals(-1, reader.read()); assertEquals(-1, reader.read()); } } } ././@LongLink0100644 0000000 0000000 00000000153 13612062727 011640 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/CharacterFilterReaderIntPredicateTest.javacommons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/CharacterFilterReaderIntPredicateTes0100644 0000000 0000000 00000011726 13612062727 034014 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.junit.jupiter.api.Assertions.assertEquals; import java.io.IOException; import java.io.StringReader; import java.util.function.IntPredicate; import org.apache.commons.io.IOUtils; import org.apache.commons.io.output.StringBuilderWriter; import org.apache.commons.lang3.StringUtils; import org.junit.jupiter.api.Test; /** * Tests {@link CharacterFilterReader} with an {@link IntPredicate}. */ public class CharacterFilterReaderIntPredicateTest { @Test public void testInputSize0FilterAll() throws IOException { final StringReader input = new StringReader(StringUtils.EMPTY); try (CharacterFilterReader reader = new CharacterFilterReader(input, ch -> true)) { assertEquals(-1, reader.read()); } } @Test public void testInputSize1FilterAll() throws IOException { try (StringReader input = new StringReader("a"); CharacterFilterReader reader = new CharacterFilterReader(input, ch -> true)) { assertEquals(-1, reader.read()); } } @Test public void testInputSize2FilterAll() throws IOException { final StringReader input = new StringReader("aa"); try (CharacterFilterReader reader = new CharacterFilterReader(input, ch -> true)) { assertEquals(-1, reader.read()); } } @Test public void testInputSize2FilterFirst() throws IOException { final StringReader input = new StringReader("ab"); try (CharacterFilterReader reader = new CharacterFilterReader(input, ch -> ch == 'a')) { assertEquals('b', reader.read()); assertEquals(-1, reader.read()); } } @Test public void testInputSize2FilterLast() throws IOException { final StringReader input = new StringReader("ab"); try (CharacterFilterReader reader = new CharacterFilterReader(input, ch -> ch == 'b')) { assertEquals('a', reader.read()); assertEquals(-1, reader.read()); } } @Test public void testInputSize5FilterWhitespace() throws IOException { final StringReader input = new StringReader(" a b "); try (CharacterFilterReader reader = new CharacterFilterReader(input, Character::isWhitespace)) { assertEquals('a', reader.read()); assertEquals('b', reader.read()); assertEquals(-1, reader.read()); } } @Test public void testReadIntoBuffer() throws IOException { final StringReader input = new StringReader("ababcabcd"); try (CharacterFilterReader reader = new CharacterFilterReader(input, ch -> ch == 'b')) { final char[] buff = new char[9]; final int charCount = reader.read(buff); assertEquals(6, charCount); assertEquals("aacacd", new String(buff, 0, charCount)); } } @Test public void testReadIntoBufferFilterWhitespace() throws IOException { final StringReader input = new StringReader(" a b a b c a b c d "); try (CharacterFilterReader reader = new CharacterFilterReader(input, Character::isWhitespace)) { final char[] buff = new char[19]; final int charCount = reader.read(buff); assertEquals(9, charCount); assertEquals("ababcabcd", new String(buff, 0, charCount)); } } @Test public void testReadUsingReader() throws IOException { final StringReader input = new StringReader("ababcabcd"); try (StringBuilderWriter output = new StringBuilderWriter(); CharacterFilterReader reader = new CharacterFilterReader(input, ch -> ch == 'b')) { IOUtils.copy(reader, output); assertEquals("aacacd", output.toString()); } } @Test public void testReadUsingReaderFilterWhitespace() throws IOException { final StringReader input = new StringReader(" a b a b c a b c d "); try (StringBuilderWriter output = new StringBuilderWriter(); CharacterFilterReader reader = new CharacterFilterReader(input, Character::isWhitespace)) { IOUtils.copy(reader, output); assertEquals("ababcabcd", output.toString()); } } }commons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/CharacterFilterReaderTest.java0100644 0000000 0000000 00000010516 13612062727 032620 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.apache.commons.io.IOUtils.EOF; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTimeoutPreemptively; import java.io.IOException; import java.io.StringReader; import java.time.Duration; import java.util.HashSet; import org.apache.commons.io.IOUtils; import org.apache.commons.io.output.StringBuilderWriter; import org.junit.jupiter.api.Test; public class CharacterFilterReaderTest { private static final String STRING_FIXTURE = "ababcabcd"; @Test public void testInputSize0FilterSize1() throws IOException { final StringReader input = new StringReader(""); final HashSet codePoints = new HashSet<>(); codePoints.add(Integer.valueOf('a')); try (CharacterFilterReader reader = new CharacterFilterReader(input, 'A')) { assertEquals(-1, reader.read()); } } @Test public void testInputSize1FilterSize1() throws IOException { try (StringReader input = new StringReader("a"); CharacterFilterReader reader = new CharacterFilterReader(input, 'a')) { assertEquals(-1, reader.read()); } } @Test public void testInputSize2FilterSize1FilterAll() throws IOException { final StringReader input = new StringReader("aa"); try (CharacterFilterReader reader = new CharacterFilterReader(input, 'a')) { assertEquals(-1, reader.read()); } } @Test public void testInputSize2FilterSize1FilterFirst() throws IOException { final StringReader input = new StringReader("ab"); try (CharacterFilterReader reader = new CharacterFilterReader(input, 'a')) { assertEquals('b', reader.read()); assertEquals(-1, reader.read()); } } @Test public void testInputSize2FilterSize1FilterLast() throws IOException { final StringReader input = new StringReader("ab"); try (CharacterFilterReader reader = new CharacterFilterReader(input, 'b')) { assertEquals('a', reader.read()); assertEquals(-1, reader.read()); } } @Test public void testReadFilteringEOF() { final StringReader input = new StringReader(STRING_FIXTURE); assertTimeoutPreemptively(Duration.ofMillis(500), () -> { try (StringBuilderWriter output = new StringBuilderWriter(); CharacterFilterReader reader = new CharacterFilterReader(input, EOF)) { int c; while ((c = reader.read()) != EOF) { output.write(c); } assertEquals(STRING_FIXTURE, output.toString()); } }); } @Test public void testReadIntoBuffer() throws IOException { final StringReader input = new StringReader(STRING_FIXTURE); try (CharacterFilterReader reader = new CharacterFilterReader(input, 'b')) { final char[] buff = new char[9]; final int charCount = reader.read(buff); assertEquals(6, charCount); assertEquals("aacacd", new String(buff, 0, charCount)); } } @Test public void testReadUsingReader() throws IOException { final StringReader input = new StringReader(STRING_FIXTURE); try (StringBuilderWriter output = new StringBuilderWriter(); CharacterFilterReader reader = new CharacterFilterReader(input, 'b')) { IOUtils.copy(reader, output); assertEquals("aacacd", output.toString()); } } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/CharacterSetFilterReaderTest.java0100644 0000000 0000000 00000014167 13612062727 033302 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.apache.commons.io.IOUtils.EOF; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTimeoutPreemptively; import java.io.IOException; import java.io.StringReader; import java.time.Duration; import java.util.HashSet; import java.util.Set; import org.apache.commons.io.output.StringBuilderWriter; import org.junit.jupiter.api.Test; public class CharacterSetFilterReaderTest { private static final String STRING_FIXTURE = "ab"; @Test public void testInputSize0FilterSize0() throws IOException { final StringReader input = new StringReader(""); try (CharacterSetFilterReader reader = new CharacterSetFilterReader(input, new HashSet(0))) { assertEquals(-1, reader.read()); } } @Test public void testInputSize0FilterSize1() throws IOException { final StringReader input = new StringReader(""); final HashSet codePoints = new HashSet<>(); codePoints.add(Integer.valueOf('a')); try (CharacterSetFilterReader reader = new CharacterSetFilterReader(input, codePoints)) { assertEquals(-1, reader.read()); } } @Test public void testInputSize0NullFilter() throws IOException { final StringReader input = new StringReader(""); try (CharacterSetFilterReader reader = new CharacterSetFilterReader(input, (Set) null)) { assertEquals(-1, reader.read()); } } @Test public void testInputSize1FilterSize1() throws IOException { try (StringReader input = new StringReader("a")) { final HashSet codePoints = new HashSet<>(); codePoints.add(Integer.valueOf('a')); try (final CharacterSetFilterReader reader = new CharacterSetFilterReader(input, codePoints)) { assertEquals(-1, reader.read()); } } } @Test public void testInputSize2FilterSize1FilterAll() throws IOException { final StringReader input = new StringReader("aa"); final HashSet codePoints = new HashSet<>(); codePoints.add(Integer.valueOf('a')); try (CharacterSetFilterReader reader = new CharacterSetFilterReader(input, codePoints)) { assertEquals(-1, reader.read()); } } @Test public void testInputSize2FilterSize1FilterFirst() throws IOException { final StringReader input = new StringReader(STRING_FIXTURE); final HashSet codePoints = new HashSet<>(); codePoints.add(Integer.valueOf('a')); try (CharacterSetFilterReader reader = new CharacterSetFilterReader(input, codePoints)) { assertEquals('b', reader.read()); assertEquals(-1, reader.read()); } } @Test public void testInputSize2FilterSize1FilterLast() throws IOException { final StringReader input = new StringReader(STRING_FIXTURE); final HashSet codePoints = new HashSet<>(); codePoints.add(Integer.valueOf('b')); try (CharacterSetFilterReader reader = new CharacterSetFilterReader(input, codePoints)) { assertEquals('a', reader.read()); assertEquals(-1, reader.read()); } } @Test public void testInputSize2FilterSize2FilterFirst() throws IOException { final StringReader input = new StringReader(STRING_FIXTURE); final HashSet codePoints = new HashSet<>(); codePoints.add(Integer.valueOf('a')); codePoints.add(Integer.valueOf('y')); try (CharacterSetFilterReader reader = new CharacterSetFilterReader(input, codePoints)) { assertEquals('b', reader.read()); assertEquals(-1, reader.read()); } } @Test public void testInputSize2FilterSize2FilterLast() throws IOException { final StringReader input = new StringReader(STRING_FIXTURE); final HashSet codePoints = new HashSet<>(); codePoints.add(Integer.valueOf('x')); codePoints.add(Integer.valueOf('b')); try (CharacterSetFilterReader reader = new CharacterSetFilterReader(input, codePoints)) { assertEquals('a', reader.read()); assertEquals(-1, reader.read()); } } @Test public void testInputSize2FilterSize2FilterNone() throws IOException { final StringReader input = new StringReader(STRING_FIXTURE); final HashSet codePoints = new HashSet<>(); codePoints.add(Integer.valueOf('x')); codePoints.add(Integer.valueOf('y')); try (CharacterSetFilterReader reader = new CharacterSetFilterReader(input, codePoints)) { assertEquals('a', reader.read()); assertEquals('b', reader.read()); } } @Test public void testReadFilteringEOF() { final StringReader input = new StringReader(STRING_FIXTURE); assertTimeoutPreemptively(Duration.ofMillis(500), () -> { try (StringBuilderWriter output = new StringBuilderWriter(); CharacterSetFilterReader reader = new CharacterSetFilterReader(input, EOF)) { int c; while ((c = reader.read()) != EOF) { output.write(c); } assertEquals(STRING_FIXTURE, output.toString()); } }); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/CircularInputStreamTest.java0100644 0000000 0000000 00000007214 13612062727 032374 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import java.io.IOException; import java.io.InputStream; import java.util.Arrays; import org.apache.commons.io.IOUtils; import org.junit.jupiter.api.Test; /** * Tests {@link CircularInputStream}. */ public class CircularInputStreamTest { private void assertStreamOutput(final byte[] toCycle, final byte[] expected) throws IOException { final byte[] actual = new byte[expected.length]; try (InputStream infStream = createInputStream(toCycle, -1)) { final int actualReadBytes = infStream.read(actual); assertArrayEquals(expected, actual); assertEquals(expected.length, actualReadBytes); } } private InputStream createInputStream(final byte[] repeatContent, final long targetByteCount) { return new CircularInputStream(repeatContent, targetByteCount); } @Test public void testContainsEofInputSize0() { assertThrows(IllegalArgumentException.class, () -> createInputStream(new byte[] { -1 }, 0)); } @Test public void testCount0() throws IOException { try (InputStream in = createInputStream(new byte[] { 1, 2 }, 0)) { assertEquals(IOUtils.EOF, in.read()); } } @Test public void testCount0InputSize0() { assertThrows(IllegalArgumentException.class, () -> createInputStream(new byte[] {}, 0)); } @Test public void testCount0InputSize1() throws IOException { try (InputStream in = createInputStream(new byte[] { 1 }, 0)) { assertEquals(IOUtils.EOF, in.read()); } } @Test public void testCount1InputSize1() throws IOException { try (InputStream in = createInputStream(new byte[] { 1 }, 1)) { assertEquals(1, in.read()); assertEquals(IOUtils.EOF, in.read()); } } @Test public void testCycleBytes() throws IOException { final byte[] input = { 1, 2 }; final byte[] expected = { 1, 2, 1, 2, 1 }; assertStreamOutput(input, expected); } @Test public void testNullInputSize0() { assertThrows(NullPointerException.class, () -> createInputStream(null, 0)); } @Test public void testWholeRangeOfBytes() throws IOException { final int size = Byte.MAX_VALUE - Byte.MIN_VALUE + 1; final byte[] contentToCycle = new byte[size]; byte value = Byte.MIN_VALUE; for (int i = 0; i < contentToCycle.length; i++) { contentToCycle[i] = value == IOUtils.EOF ? 0 : value; value++; } final byte[] expectedOutput = Arrays.copyOf(contentToCycle, size); assertStreamOutput(contentToCycle, expectedOutput); } } ././@LongLink0100644 0000000 0000000 00000000146 13612062727 011642 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/ClassLoaderObjectInputStreamTest.javacommons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/ClassLoaderObjectInputStreamTest.jav0100644 0000000 0000000 00000016672 13612062727 034022 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.Flushable; import java.io.InputStream; import java.io.ObjectOutputStream; import java.io.Serializable; /** * Tests the CountingInputStream. * */ public class ClassLoaderObjectInputStreamTest { /* Note: This test case tests the simplest functionality of * ObjectInputStream. IF we really wanted to test ClassLoaderObjectInputStream * we would probably need to create a transient Class Loader. -TO */ @org.junit.jupiter.api.Test public void testExpected() throws Exception { final ByteArrayOutputStream baos = new ByteArrayOutputStream(); final ObjectOutputStream oos = new ObjectOutputStream(baos); final Object input = Boolean.FALSE; oos.writeObject(input); final InputStream bais = new ByteArrayInputStream(baos.toByteArray()); try (final ClassLoaderObjectInputStream clois = new ClassLoaderObjectInputStream(getClass().getClassLoader(), bais)) { final Object result = clois.readObject(); assertEquals(input, result); } } @org.junit.jupiter.api.Test public void testLong() throws Exception { final ByteArrayOutputStream baos = new ByteArrayOutputStream(); final ObjectOutputStream oos = new ObjectOutputStream(baos); final Object input = (long) 123; oos.writeObject(input); final InputStream bais = new ByteArrayInputStream(baos.toByteArray()); try (final ClassLoaderObjectInputStream clois = new ClassLoaderObjectInputStream(getClass().getClassLoader(), bais)) { final Object result = clois.readObject(); assertEquals(input, result); } } @org.junit.jupiter.api.Test public void testPrimitiveLong() throws Exception { final ByteArrayOutputStream baos = new ByteArrayOutputStream(); final ObjectOutputStream oos = new ObjectOutputStream(baos); final long input = 12345L; oos.writeLong(input); oos.close(); final InputStream bais = new ByteArrayInputStream(baos.toByteArray()); try (final ClassLoaderObjectInputStream clois = new ClassLoaderObjectInputStream(getClass().getClassLoader(), bais)) { final long result = clois.readLong(); assertEquals(input, result); } } private enum E {A, B, C} private static class Test implements Serializable { private static final long serialVersionUID = 1L; private final int i; private final Object o; private final E e; Test(final int i, final Object o) { this.i = i; this.e = E.A; this.o = o; } @Override public boolean equals(final Object other) { if (other instanceof Test) { final Test tother = (Test) other; return (this.i == tother.i) & (this.e == tother.e) & equalObject(tother.o); } return false; } private boolean equalObject(final Object other) { if (this.o == null) { return other == null; } return o.equals(other); } @Override public int hashCode() { return super.hashCode(); } } @org.junit.jupiter.api.Test public void testObject1() throws Exception { final ByteArrayOutputStream baos = new ByteArrayOutputStream(); final ObjectOutputStream oos = new ObjectOutputStream(baos); final Object input = new Test(123, null); oos.writeObject(input); oos.close(); final InputStream bais = new ByteArrayInputStream(baos.toByteArray()); try (final ClassLoaderObjectInputStream clois = new ClassLoaderObjectInputStream(getClass().getClassLoader(), bais)) { final Object result = clois.readObject(); assertEquals(input, result); } } @org.junit.jupiter.api.Test public void testObject2() throws Exception { final ByteArrayOutputStream baos = new ByteArrayOutputStream(); final ObjectOutputStream oos = new ObjectOutputStream(baos); final Object input = new Test(123, 0); oos.writeObject(input); oos.close(); final InputStream bais = new ByteArrayInputStream(baos.toByteArray()); try (final ClassLoaderObjectInputStream clois = new ClassLoaderObjectInputStream(getClass().getClassLoader(), bais)) { final Object result = clois.readObject(); assertEquals(input, result); } } @org.junit.jupiter.api.Test public void testResolveProxyClass() throws Exception { final ByteArrayOutputStream baos = new ByteArrayOutputStream(); final ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(Boolean.FALSE); final InputStream bais = new ByteArrayInputStream(baos.toByteArray()); try (final ClassLoaderObjectInputStream clois = new ClassLoaderObjectInputStream(getClass().getClassLoader(), bais)) { final String[] interfaces = { Comparable.class.getName() }; final Class result = clois.resolveProxyClass(interfaces); assertTrue(Comparable.class.isAssignableFrom(result), "Assignable"); } } @org.junit.jupiter.api.Test public void testResolveProxyClassWithMultipleInterfaces() throws Exception { final ByteArrayOutputStream baos = new ByteArrayOutputStream(); final ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(Boolean.FALSE); final InputStream bais = new ByteArrayInputStream(baos.toByteArray()); try (final ClassLoaderObjectInputStream clois = new ClassLoaderObjectInputStream(getClass().getClassLoader(), bais)) { final String[] interfaces = { Comparable.class.getName(), Serializable.class.getName(), Runnable.class.getName() }; final Class result = clois.resolveProxyClass(interfaces); assertTrue(Comparable.class.isAssignableFrom(result), "Assignable"); assertTrue(Runnable.class.isAssignableFrom(result), "Assignable"); assertTrue(Serializable.class.isAssignableFrom(result), "Assignable"); assertFalse(Flushable.class.isAssignableFrom(result), "Not Assignable"); } } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/CloseShieldInputStreamTest.java0100644 0000000 0000000 00000003635 13612062727 033031 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * JUnit Test Case for {@link CloseShieldInputStream}. */ public class CloseShieldInputStreamTest { private byte[] data; private InputStream original; private InputStream shielded; private boolean closed; @BeforeEach public void setUp() { data = new byte[] { 'x', 'y', 'z' }; original = new ByteArrayInputStream(data) { @Override public void close() { closed = true; } }; shielded = CloseShieldInputStream.wrap(original); closed = false; } @Test public void testClose() throws IOException { shielded.close(); assertFalse(closed, "closed"); assertEquals(-1, shielded.read(), "read()"); assertEquals(data[0], original.read(), "read()"); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/CloseShieldReaderTest.java0100644 0000000 0000000 00000003604 13612062727 031754 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import java.io.IOException; import java.io.Reader; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * JUnit Test Case for {@link CloseShieldReader}. */ public class CloseShieldReaderTest { private String data; private Reader original; private Reader shielded; @BeforeEach public void setUp() { data = "xyz"; original = spy(new CharSequenceReader(data)); shielded = CloseShieldReader.wrap(original); } @Test public void testClose() throws IOException { shielded.close(); verify(original, never()).close(); final char[] cbuf = new char[10]; assertEquals(-1, shielded.read(cbuf, 0, 10), "read(cbuf, off, len)"); assertEquals(data.length(), original.read(cbuf, 0, 10), "read(cbuf, off, len)"); assertEquals(data, new String(cbuf, 0, data.length())); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/ClosedInputStreamTest.java0100644 0000000 0000000 00000002320 13612062727 032032 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.Test; /** * JUnit Test Case for {@link ClosedInputStream}. */ public class ClosedInputStreamTest { @Test public void testRead() throws Exception { try (final ClosedInputStream cis = new ClosedInputStream()) { assertEquals(-1, cis.read(), "read()"); } } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/ClosedReaderTest.java0100644 0000000 0000000 00000002333 13612062727 030765 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.Test; /** * JUnit Test Case for {@link ClosedReader}. */ public class ClosedReaderTest { @Test public void testRead() throws Exception { try (final ClosedReader cr = new ClosedReader()) { assertEquals(-1, cr.read(new char[10], 0, 10), "read(cbuf, off, len)"); } } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/CountingInputStreamTest.java0100644 0000000 0000000 00000016227 13612062727 032422 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; import java.io.ByteArrayInputStream; import java.io.IOException; import org.apache.commons.io.IOUtils; import org.junit.jupiter.api.Test; /** * Tests the CountingInputStream. * */ public class CountingInputStreamTest { @Test public void testCounting() throws Exception { final String text = "A piece of text"; final byte[] bytes = text.getBytes(); final ByteArrayInputStream bais = new ByteArrayInputStream(bytes); try (final CountingInputStream cis = new CountingInputStream(bais)) { // have to declare this larger as we're going to read // off the end of the stream and input stream seems // to do bounds checking final byte[] result = new byte[21]; final byte[] ba = new byte[5]; int found = cis.read(ba); System.arraycopy(ba, 0, result, 0, 5); assertEquals(found, cis.getCount()); final int value = cis.read(); found++; result[5] = (byte) value; assertEquals(found, cis.getCount()); found += cis.read(result, 6, 5); assertEquals(found, cis.getCount()); found += cis.read(result, 11, 10); // off the end assertEquals(found, cis.getCount()); // trim to get rid of the 6 empty values final String textResult = new String(result).trim(); assertEquals(textResult, text); } } /* * Test for files > 2GB in size - see issue IO-84 */ @Test public void testLargeFiles_IO84() throws Exception { final long size = (long) Integer.MAX_VALUE + (long) 1; final NullInputStream mock = new NullInputStream(size); final CountingInputStream cis = new CountingInputStream(mock); // Test integer methods IOUtils.consume(cis); try { cis.getCount(); fail("Expected getCount() to throw an ArithmeticException"); } catch (final ArithmeticException ae) { // expected result } try { cis.resetCount(); fail("Expected resetCount() to throw an ArithmeticException"); } catch (final ArithmeticException ae) { // expected result } mock.close(); // Test long methods IOUtils.consume(cis); assertEquals(size, cis.getByteCount(), "getByteCount()"); assertEquals(size, cis.resetByteCount(), "resetByteCount()"); } @Test public void testResetting() throws Exception { final String text = "A piece of text"; final byte[] bytes = text.getBytes(); final ByteArrayInputStream bais = new ByteArrayInputStream(bytes); try (final CountingInputStream cis = new CountingInputStream(bais)) { final byte[] result = new byte[bytes.length]; int found = cis.read(result, 0, 5); assertEquals(found, cis.getCount()); final int count = cis.resetCount(); found = cis.read(result, 6, 5); assertEquals(found, count); } } @Test public void testZeroLength1() throws Exception { final ByteArrayInputStream bais = new ByteArrayInputStream(IOUtils.EMPTY_BYTE_ARRAY); try (final CountingInputStream cis = new CountingInputStream(bais)) { final int found = cis.read(); assertEquals(-1, found); assertEquals(0, cis.getCount()); } } @Test public void testZeroLength2() throws Exception { final ByteArrayInputStream bais = new ByteArrayInputStream(IOUtils.EMPTY_BYTE_ARRAY); try (final CountingInputStream cis = new CountingInputStream(bais)) { final byte[] result = new byte[10]; final int found = cis.read(result); assertEquals(-1, found); assertEquals(0, cis.getCount()); } } @Test public void testZeroLength3() throws Exception { final ByteArrayInputStream bais = new ByteArrayInputStream(IOUtils.EMPTY_BYTE_ARRAY); try (final CountingInputStream cis = new CountingInputStream(bais)) { final byte[] result = new byte[10]; final int found = cis.read(result, 0, 5); assertEquals(-1, found); assertEquals(0, cis.getCount()); } } @Test public void testEOF1() throws Exception { final ByteArrayInputStream bais = new ByteArrayInputStream(new byte[2]); try (final CountingInputStream cis = new CountingInputStream(bais)) { int found = cis.read(); assertEquals(0, found); assertEquals(1, cis.getCount()); found = cis.read(); assertEquals(0, found); assertEquals(2, cis.getCount()); found = cis.read(); assertEquals(-1, found); assertEquals(2, cis.getCount()); } } @Test public void testEOF2() throws Exception { final ByteArrayInputStream bais = new ByteArrayInputStream(new byte[2]); try (final CountingInputStream cis = new CountingInputStream(bais)) { final byte[] result = new byte[10]; final int found = cis.read(result); assertEquals(2, found); assertEquals(2, cis.getCount()); } } @Test public void testEOF3() throws Exception { final ByteArrayInputStream bais = new ByteArrayInputStream(new byte[2]); try (final CountingInputStream cis = new CountingInputStream(bais)) { final byte[] result = new byte[10]; final int found = cis.read(result, 0, 5); assertEquals(2, found); assertEquals(2, cis.getCount()); } } @Test public void testSkipping() throws IOException { final String text = "Hello World!"; final byte[] bytes = text.getBytes(); final ByteArrayInputStream bais = new ByteArrayInputStream(bytes); try (final CountingInputStream cis = new CountingInputStream(bais)) { assertEquals(6, cis.skip(6)); assertEquals(6, cis.getCount()); final byte[] result = new byte[6]; cis.read(result); assertEquals("World!", new String(result)); assertEquals(12, cis.getCount()); } } } ././@LongLink0100644 0000000 0000000 00000000145 13612062727 011641 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/InfiniteCircularInputStreamTest.javacommons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/InfiniteCircularInputStreamTest.java0100644 0000000 0000000 00000006601 13612062727 034061 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import java.io.IOException; import java.io.InputStream; import java.util.Arrays; import org.apache.commons.io.IOUtils; import org.junit.jupiter.api.Test; /** * Tests {@link InfiniteCircularInputStream}. */ public class InfiniteCircularInputStreamTest { private void assertStreamOutput(final byte[] toCycle, final byte[] expected) throws IOException { final byte[] actual = new byte[expected.length]; try (InputStream infStream = new InfiniteCircularInputStream(toCycle)) { final int actualReadBytes = infStream.read(actual); assertArrayEquals(expected, actual); assertEquals(expected.length, actualReadBytes); } } private InputStream createInputStream(final byte[] repeatContent) { return new InfiniteCircularInputStream(repeatContent); } @Test public void testContainsEofInputSize0() { assertThrows(IllegalArgumentException.class, () -> createInputStream(new byte[] { -1 })); } @Test public void testCount0InputSize0() { assertThrows(IllegalArgumentException.class, () -> createInputStream(new byte[] {})); } @Test public void testCount0InputSize1() throws IOException { try (InputStream in = createInputStream(new byte[] { 1 })) { // empty } } @Test public void testCount1InputSize1() throws IOException { try (InputStream in = createInputStream(new byte[] { 1 })) { assertEquals(1, in.read()); assertEquals(1, in.read()); } } @Test public void testCycleBytes() throws IOException { final byte[] input = { 1, 2 }; final byte[] expected = { 1, 2, 1, 2, 1 }; assertStreamOutput(input, expected); } @Test public void testNullInputSize0() { assertThrows(NullPointerException.class, () -> createInputStream(null)); } @Test public void testWholeRangeOfBytes() throws IOException { final int size = Byte.MAX_VALUE - Byte.MIN_VALUE + 1; final byte[] contentToCycle = new byte[size]; byte value = Byte.MIN_VALUE; for (int i = 0; i < contentToCycle.length; i++) { contentToCycle[i] = value == IOUtils.EOF ? 0 : value; value++; } final byte[] expectedOutput = Arrays.copyOf(contentToCycle, size); assertStreamOutput(contentToCycle, expectedOutput); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/MarkShieldInputStreamTest.java0100644 0000000 0000000 00000010270 13612062727 032647 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; import java.io.InputStream; import org.junit.jupiter.api.Test; public class MarkShieldInputStreamTest { @Test public void markIsNoOpWhenUnderlyingDoesNotSupport() throws IOException { try (final MarkTestableInputStream in = new MarkTestableInputStream(new NullInputStream(64, false, false)); final MarkShieldInputStream msis = new MarkShieldInputStream(in)) { msis.mark(1024); assertEquals(0, in.markcount); assertEquals(0, in.readlimit); } } @Test public void markIsNoOpWhenUnderlyingSupports() throws IOException { try (final MarkTestableInputStream in = new MarkTestableInputStream(new NullInputStream(64, true, false)); final MarkShieldInputStream msis = new MarkShieldInputStream(in)) { msis.mark(1024); assertEquals(0, in.markcount); assertEquals(0, in.readlimit); } } @Test public void markSupportedIsFalseWhenUnderlyingFalse() throws IOException { // test wrapping an underlying stream which does NOT support marking try (final InputStream is = new NullInputStream(64, false, false)) { assertFalse(is.markSupported()); try (final MarkShieldInputStream msis = new MarkShieldInputStream(is)) { assertFalse(msis.markSupported()); } } } @Test public void markSupportedIsFalseWhenUnderlyingTrue() throws IOException { // test wrapping an underlying stream which supports marking try (final InputStream is = new NullInputStream(64, true, false)) { assertTrue(is.markSupported()); try (final MarkShieldInputStream msis = new MarkShieldInputStream(is)) { assertFalse(msis.markSupported()); } } } @Test public void resetThrowsExceptionWhenUnderylingDoesNotSupport() throws IOException { // test wrapping an underlying stream which does NOT support marking try (final MarkShieldInputStream msis = new MarkShieldInputStream( new NullInputStream(64, false, false))) { assertThrows(UnsupportedOperationException.class, () -> msis.reset()); } } @Test public void resetThrowsExceptionWhenUnderylingSupports() throws IOException { // test wrapping an underlying stream which supports marking try (final MarkShieldInputStream msis = new MarkShieldInputStream( new NullInputStream(64, true, false))) { assertThrows(UnsupportedOperationException.class, () -> msis.reset()); } } private static class MarkTestableInputStream extends ProxyInputStream { int markcount; int readlimit; public MarkTestableInputStream(final InputStream in) { super(in); } @SuppressWarnings("sync-override") @Override public void mark(final int readlimit) { // record that `mark` was called this.markcount++; this.readlimit = readlimit; // invoke on super super.mark(readlimit); } } } ././@LongLink0100644 0000000 0000000 00000000155 13612062727 011642 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/MessageDigestCalculatingInputStreamTest.javacommons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/MessageDigestCalculatingInputStreamT0100644 0000000 0000000 00000003703 13612062727 034066 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import java.io.ByteArrayInputStream; import java.security.MessageDigest; import java.util.Random; import org.junit.jupiter.api.Test; public class MessageDigestCalculatingInputStreamTest { public static byte[] generateRandomByteStream(final int pSize) { final byte[] buffer = new byte[pSize]; final Random rnd = new Random(); rnd.nextBytes(buffer); return buffer; } @Test public void test() throws Exception { for (int i = 256; i < 8192; i = i*2) { final byte[] buffer = generateRandomByteStream(i); final MessageDigest md5Sum = MessageDigest.getInstance("MD5"); final byte[] expect = md5Sum.digest(buffer); try (final MessageDigestCalculatingInputStream md5InputStream = new MessageDigestCalculatingInputStream(new ByteArrayInputStream(buffer))) { md5InputStream.consume(); final byte[] got = md5InputStream.getMessageDigest().digest(); assertArrayEquals(expect, got); } } } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/NullInputStreamTest.java0100644 0000000 0000000 00000020556 13612062727 031546 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import java.io.EOFException; import java.io.IOException; import java.io.InputStream; import org.junit.jupiter.api.Test; /** * JUnit Test Case for {@link NullInputStream}. * */ public class NullInputStreamTest { // Use the same message as in java.io.InputStream.reset() in OpenJDK 8.0.275-1. private static final String MARK_RESET_NOT_SUPPORTED = "mark/reset not supported"; @Test public void testRead() throws Exception { final int size = 5; final InputStream input = new TestNullInputStream(size); for (int i = 0; i < size; i++) { assertEquals(size - i, input.available(), "Check Size [" + i + "]"); assertEquals(i, input.read(), "Check Value [" + i + "]"); } assertEquals(0, input.available(), "Available after contents all read"); // Check available is zero after End of file assertEquals(-1, input.read(), "End of File"); assertEquals(0, input.available(), "Available after End of File"); // Test reading after the end of file try { final int result = input.read(); fail("Should have thrown an IOException, byte=[" + result + "]"); } catch (final IOException e) { assertEquals("Read after end of file", e.getMessage()); } // Close - should reset input.close(); assertEquals(size, input.available(), "Available after close"); } @Test public void testReadByteArray() throws Exception { final byte[] bytes = new byte[10]; final InputStream input = new TestNullInputStream(15); // Read into array final int count1 = input.read(bytes); assertEquals(bytes.length, count1, "Read 1"); for (int i = 0; i < count1; i++) { assertEquals(i, bytes[i], "Check Bytes 1"); } // Read into array final int count2 = input.read(bytes); assertEquals(5, count2, "Read 2"); for (int i = 0; i < count2; i++) { assertEquals(count1 + i, bytes[i], "Check Bytes 2"); } // End of File final int count3 = input.read(bytes); assertEquals(-1, count3, "Read 3 (EOF)"); // Test reading after the end of file try { final int count4 = input.read(bytes); fail("Should have thrown an IOException, byte=[" + count4 + "]"); } catch (final IOException e) { assertEquals("Read after end of file", e.getMessage()); } // reset by closing input.close(); // Read into array using offset & length final int offset = 2; final int lth = 4; final int count5 = input.read(bytes, offset, lth); assertEquals(lth, count5, "Read 5"); for (int i = offset; i < lth; i++) { assertEquals(i, bytes[i], "Check Bytes 2"); } } @Test public void testEOFException() throws Exception { final InputStream input = new TestNullInputStream(2, false, true); assertEquals(0, input.read(), "Read 1"); assertEquals(1, input.read(), "Read 2"); try { final int result = input.read(); fail("Should have thrown an EOFException, byte=[" + result + "]"); } catch (final EOFException e) { // expected } input.close(); } @Test public void testMarkAndReset() throws Exception { int position = 0; final int readlimit = 10; @SuppressWarnings("resource") // this is actually closed final InputStream input = new TestNullInputStream(100, true, false); assertTrue(input.markSupported(), "Mark Should be Supported"); // No Mark try { input.reset(); fail("Read limit exceeded, expected IOException "); } catch (final IOException e) { assertEquals("No position has been marked", e.getMessage(), "No Mark IOException message"); } for (; position < 3; position++) { assertEquals(position, input.read(), "Read Before Mark [" + position +"]"); } // Mark input.mark(readlimit); // Read further for (int i = 0; i < 3; i++) { assertEquals(position + i, input.read(), "Read After Mark [" + i +"]"); } // Reset input.reset(); // Read From marked position for (int i = 0; i < readlimit + 1; i++) { assertEquals(position + i, input.read(), "Read After Reset [" + i +"]"); } // Reset after read limit passed try { input.reset(); fail("Read limit exceeded, expected IOException "); } catch (final IOException e) { assertEquals("Marked position [" + position + "] is no longer valid - passed the read limit [" + readlimit + "]", e.getMessage(), "Read limit IOException message"); } input.close(); } @Test public void testMarkNotSupported() throws Exception { final InputStream input = new TestNullInputStream(100, false, true); assertFalse(input.markSupported(), "Mark Should NOT be Supported"); try { input.mark(5); fail("mark() should throw UnsupportedOperationException"); } catch (final UnsupportedOperationException e) { assertEquals(MARK_RESET_NOT_SUPPORTED, e.getMessage(), "mark() error message"); } try { input.reset(); fail("reset() should throw UnsupportedOperationException"); } catch (final UnsupportedOperationException e) { assertEquals(MARK_RESET_NOT_SUPPORTED, e.getMessage(), "reset() error message"); } input.close(); } @Test public void testSkip() throws Exception { final InputStream input = new TestNullInputStream(10, true, false); assertEquals(0, input.read(), "Read 1"); assertEquals(1, input.read(), "Read 2"); assertEquals(5, input.skip(5), "Skip 1"); assertEquals(7, input.read(), "Read 3"); assertEquals(2, input.skip(5), "Skip 2"); // only 2 left to skip assertEquals(-1, input.skip(5), "Skip 3 (EOF)"); // End of file try { input.skip(5); // fail("Expected IOException for skipping after end of file"); } catch (final IOException e) { assertEquals("Skip after end of file", e.getMessage(), "Skip after EOF IOException message"); } input.close(); } // ------------- Test NullInputStream implementation ------------- private static final class TestNullInputStream extends NullInputStream { public TestNullInputStream(final int size) { super(size); } public TestNullInputStream(final int size, final boolean markSupported, final boolean throwEofException) { super(size, markSupported, throwEofException); } @Override protected int processByte() { return (int)getPosition() - 1; } @Override protected void processBytes(final byte[] bytes, final int offset, final int length) { final int startPos = (int)getPosition() - length; for (int i = offset; i < length; i++) { bytes[i] = (byte)(startPos + i); } } } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/NullReaderTest.java0100644 0000000 0000000 00000020115 13612062727 030464 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import java.io.EOFException; import java.io.IOException; import java.io.Reader; import org.junit.jupiter.api.Test; /** * JUnit Test Case for {@link NullReader}. * */ public class NullReaderTest { // Use the same message as in java.io.InputStream.reset() in OpenJDK 8.0.275-1. private static final String MARK_RESET_NOT_SUPPORTED = "mark/reset not supported"; @Test public void testRead() throws Exception { final int size = 5; final TestNullReader reader = new TestNullReader(size); for (int i = 0; i < size; i++) { assertEquals(i, reader.read(), "Check Value [" + i + "]"); } // Check End of File assertEquals(-1, reader.read(), "End of File"); // Test reading after the end of file try { final int result = reader.read(); fail("Should have thrown an IOException, value=[" + result + "]"); } catch (final IOException e) { assertEquals("Read after end of file", e.getMessage()); } // Close - should reset reader.close(); assertEquals(0, reader.getPosition(), "Available after close"); } @Test public void testReadCharArray() throws Exception { final char[] chars = new char[10]; final Reader reader = new TestNullReader(15); // Read into array final int count1 = reader.read(chars); assertEquals(chars.length, count1, "Read 1"); for (int i = 0; i < count1; i++) { assertEquals(i, chars[i], "Check Chars 1"); } // Read into array final int count2 = reader.read(chars); assertEquals(5, count2, "Read 2"); for (int i = 0; i < count2; i++) { assertEquals(count1 + i, chars[i], "Check Chars 2"); } // End of File final int count3 = reader.read(chars); assertEquals(-1, count3, "Read 3 (EOF)"); // Test reading after the end of file try { final int count4 = reader.read(chars); fail("Should have thrown an IOException, value=[" + count4 + "]"); } catch (final IOException e) { assertEquals("Read after end of file", e.getMessage()); } // reset by closing reader.close(); // Read into array using offset & length final int offset = 2; final int lth = 4; final int count5 = reader.read(chars, offset, lth); assertEquals(lth, count5, "Read 5"); for (int i = offset; i < lth; i++) { assertEquals(i, chars[i], "Check Chars 3"); } } @Test public void testEOFException() throws Exception { final Reader reader = new TestNullReader(2, false, true); assertEquals(0, reader.read(), "Read 1"); assertEquals(1, reader.read(), "Read 2"); try { final int result = reader.read(); fail("Should have thrown an EOFException, value=[" + result + "]"); } catch (final EOFException e) { // expected } reader.close(); } @Test public void testMarkAndReset() throws Exception { int position = 0; final int readlimit = 10; @SuppressWarnings("resource") // this is actually closed final Reader reader = new TestNullReader(100, true, false); assertTrue(reader.markSupported(), "Mark Should be Supported"); // No Mark try { reader.reset(); fail("Read limit exceeded, expected IOException "); } catch (final IOException e) { assertEquals("No position has been marked", e.getMessage(), "No Mark IOException message"); } for (; position < 3; position++) { assertEquals(position, reader.read(), "Read Before Mark [" + position +"]"); } // Mark reader.mark(readlimit); // Read further for (int i = 0; i < 3; i++) { assertEquals(position + i, reader.read(), "Read After Mark [" + i +"]"); } // Reset reader.reset(); // Read From marked position for (int i = 0; i < readlimit + 1; i++) { assertEquals(position + i, reader.read(), "Read After Reset [" + i +"]"); } // Reset after read limit passed try { reader.reset(); fail("Read limit exceeded, expected IOException "); } catch (final IOException e) { assertEquals("Marked position [" + position + "] is no longer valid - passed the read limit [" + readlimit + "]", e.getMessage(), "Read limit IOException message"); } reader.close(); } @Test public void testMarkNotSupported() throws Exception { final Reader reader = new TestNullReader(100, false, true); assertFalse(reader.markSupported(), "Mark Should NOT be Supported"); try { reader.mark(5); fail("mark() should throw UnsupportedOperationException"); } catch (final UnsupportedOperationException e) { assertEquals(MARK_RESET_NOT_SUPPORTED, e.getMessage(), "mark() error message"); } try { reader.reset(); fail("reset() should throw UnsupportedOperationException"); } catch (final UnsupportedOperationException e) { assertEquals(MARK_RESET_NOT_SUPPORTED, e.getMessage(), "reset() error message"); } reader.close(); } @Test public void testSkip() throws Exception { final Reader reader = new TestNullReader(10, true, false); assertEquals(0, reader.read(), "Read 1"); assertEquals(1, reader.read(), "Read 2"); assertEquals(5, reader.skip(5), "Skip 1"); assertEquals(7, reader.read(), "Read 3"); assertEquals(2, reader.skip(5), "Skip 2"); // only 2 left to skip assertEquals(-1, reader.skip(5), "Skip 3 (EOF)"); // End of file try { reader.skip(5); // fail("Expected IOException for skipping after end of file"); } catch (final IOException e) { assertEquals("Skip after end of file", e.getMessage(), "Skip after EOF IOException message"); } reader.close(); } // ------------- Test NullReader implementation ------------- private static final class TestNullReader extends NullReader { public TestNullReader(final int size) { super(size); } public TestNullReader(final int size, final boolean markSupported, final boolean throwEofException) { super(size, markSupported, throwEofException); } @Override protected int processChar() { return (int)getPosition() - 1; } @Override protected void processChars(final char[] chars, final int offset, final int length) { final int startPos = (int)getPosition() - length; for (int i = offset; i < length; i++) { chars[i] = (char)(startPos + i); } } } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/ObservableInputStreamTest.java0100644 0000000 0000000 00000026360 13612062727 032717 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertThrows; import java.io.ByteArrayInputStream; import java.io.IOException; import org.apache.commons.io.IOUtils; import org.apache.commons.io.input.ObservableInputStream.Observer; import org.apache.commons.io.output.NullOutputStream; import org.junit.jupiter.api.Test; /** * Tests {@link ObservableInputStream}. */ public class ObservableInputStreamTest { private static class DataViewObserver extends MethodCountObserver { private byte[] buffer; private int lastValue = -1; private int length = -1; private int offset = -1; @Override public void data(final byte[] buffer, final int offset, final int length) throws IOException { this.buffer = buffer; this.offset = offset; this.length = length; } @Override public void data(final int value) throws IOException { super.data(value); lastValue = value; } } private static class LengthObserver extends Observer { private long total; @Override public void data(final byte[] buffer, final int offset, final int length) throws IOException { this.total += length; } @Override public void data(final int value) throws IOException { total++; } public long getTotal() { return total; } } private static class MethodCountObserver extends Observer { private long closedCount; private long dataBufferCount; private long dataCount; private long errorCount; private long finishedCount; @Override public void closed() throws IOException { closedCount++; } @Override public void data(final byte[] buffer, final int offset, final int length) throws IOException { dataBufferCount++; } @Override public void data(final int value) throws IOException { dataCount++; } @Override public void error(final IOException exception) throws IOException { errorCount++; } @Override public void finished() throws IOException { finishedCount++; } public long getClosedCount() { return closedCount; } public long getDataBufferCount() { return dataBufferCount; } public long getDataCount() { return dataCount; } public long getErrorCount() { return errorCount; } public long getFinishedCount() { return finishedCount; } } @Test public void testBrokenInputStreamRead() throws IOException { try (final ObservableInputStream ois = new ObservableInputStream(new BrokenInputStream())) { assertThrows(IOException.class, () -> ois.read()); } } @Test public void testBrokenInputStreamReadBuffer() throws IOException { try (final ObservableInputStream ois = new ObservableInputStream(new BrokenInputStream())) { assertThrows(IOException.class, () -> ois.read(new byte[1])); } } @Test public void testBrokenInputStreamReadSubBuffer() throws IOException { try (final ObservableInputStream ois = new ObservableInputStream(new BrokenInputStream())) { assertThrows(IOException.class, () -> ois.read(new byte[2], 0, 1)); } } /** * Tests that {@link Observer#data(int)} is called. */ @Test public void testDataByteCalled_add() throws Exception { final byte[] buffer = MessageDigestCalculatingInputStreamTest .generateRandomByteStream(IOUtils.DEFAULT_BUFFER_SIZE); final DataViewObserver lko = new DataViewObserver(); try (final ObservableInputStream ois = new ObservableInputStream(new ByteArrayInputStream(buffer))) { assertEquals(-1, lko.lastValue); ois.read(); assertEquals(-1, lko.lastValue); assertEquals(0, lko.getFinishedCount()); assertEquals(0, lko.getClosedCount()); ois.add(lko); for (int i = 1; i < buffer.length; i++) { final int result = ois.read(); assertEquals((byte) result, buffer[i]); assertEquals(result, lko.lastValue); assertEquals(0, lko.getFinishedCount()); assertEquals(0, lko.getClosedCount()); } final int result = ois.read(); assertEquals(-1, result); assertEquals(1, lko.getFinishedCount()); assertEquals(0, lko.getClosedCount()); ois.close(); assertEquals(1, lko.getFinishedCount()); assertEquals(1, lko.getClosedCount()); } } /** * Tests that {@link Observer#data(int)} is called. */ @Test public void testDataByteCalled_ctor() throws Exception { final byte[] buffer = MessageDigestCalculatingInputStreamTest .generateRandomByteStream(IOUtils.DEFAULT_BUFFER_SIZE); final DataViewObserver lko = new DataViewObserver(); try (final ObservableInputStream ois = new ObservableInputStream(new ByteArrayInputStream(buffer), lko)) { assertEquals(-1, lko.lastValue); ois.read(); assertNotEquals(-1, lko.lastValue); assertEquals(0, lko.getFinishedCount()); assertEquals(0, lko.getClosedCount()); for (int i = 1; i < buffer.length; i++) { final int result = ois.read(); assertEquals((byte) result, buffer[i]); assertEquals(result, lko.lastValue); assertEquals(0, lko.getFinishedCount()); assertEquals(0, lko.getClosedCount()); } final int result = ois.read(); assertEquals(-1, result); assertEquals(1, lko.getFinishedCount()); assertEquals(0, lko.getClosedCount()); ois.close(); assertEquals(1, lko.getFinishedCount()); assertEquals(1, lko.getClosedCount()); } } /** * Tests that {@link Observer#data(byte[],int,int)} is called. */ @Test public void testDataBytesCalled() throws Exception { final byte[] buffer = MessageDigestCalculatingInputStreamTest .generateRandomByteStream(IOUtils.DEFAULT_BUFFER_SIZE); try (final ByteArrayInputStream bais = new ByteArrayInputStream(buffer); final ObservableInputStream ois = new ObservableInputStream(bais)) { final DataViewObserver observer = new DataViewObserver(); final byte[] readBuffer = new byte[23]; assertNull(observer.buffer); ois.read(readBuffer); assertNull(observer.buffer); ois.add(observer); for (;;) { if (bais.available() >= 2048) { final int result = ois.read(readBuffer); if (result == -1) { ois.close(); break; } assertEquals(readBuffer, observer.buffer); assertEquals(0, observer.offset); assertEquals(readBuffer.length, observer.length); } else { final int res = Math.min(11, bais.available()); final int result = ois.read(readBuffer, 1, 11); if (result == -1) { ois.close(); break; } assertEquals(readBuffer, observer.buffer); assertEquals(1, observer.offset); assertEquals(res, observer.length); } } } } @Test public void testGetObservers0() throws IOException { try (final ObservableInputStream ois = new ObservableInputStream(new NullInputStream())) { assertTrue(ois.getObservers().isEmpty()); } } @Test public void testGetObservers1() throws IOException { final DataViewObserver observer0 = new DataViewObserver(); try (final ObservableInputStream ois = new ObservableInputStream(new NullInputStream(), observer0)) { assertEquals(observer0, ois.getObservers().get(0)); } } @Test public void testGetObserversOrder() throws IOException { final DataViewObserver observer0 = new DataViewObserver(); final DataViewObserver observer1 = new DataViewObserver(); try (final ObservableInputStream ois = new ObservableInputStream(new NullInputStream(), observer0, observer1)) { assertEquals(observer0, ois.getObservers().get(0)); assertEquals(observer1, ois.getObservers().get(1)); } } private void testNotificationCallbacks(final int bufferSize) throws IOException { final byte[] buffer = IOUtils.byteArray(); final LengthObserver lengthObserver = new LengthObserver(); final MethodCountObserver methodCountObserver = new MethodCountObserver(); try (final ObservableInputStream ois = new ObservableInputStream(new ByteArrayInputStream(buffer), lengthObserver, methodCountObserver)) { assertEquals(IOUtils.DEFAULT_BUFFER_SIZE, IOUtils.copy(ois, NullOutputStream.NULL_OUTPUT_STREAM, bufferSize)); } assertEquals(IOUtils.DEFAULT_BUFFER_SIZE, lengthObserver.getTotal()); assertEquals(1, methodCountObserver.getClosedCount()); assertEquals(1, methodCountObserver.getFinishedCount()); assertEquals(0, methodCountObserver.getErrorCount()); assertEquals(0, methodCountObserver.getDataCount()); assertEquals(buffer.length / bufferSize, methodCountObserver.getDataBufferCount()); } @Test public void testNotificationCallbacksBufferSize1() throws Exception { testNotificationCallbacks(1); } @Test public void testNotificationCallbacksBufferSize2() throws Exception { testNotificationCallbacks(2); } @Test public void testNotificationCallbacksBufferSizeDefault() throws Exception { testNotificationCallbacks(IOUtils.DEFAULT_BUFFER_SIZE); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/ProxyReaderTest.java0100644 0000000 0000000 00000004200 13612062727 030670 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import java.io.IOException; import java.io.Reader; import java.nio.CharBuffer; import org.junit.jupiter.api.Test; /** * Test {@link ProxyReader}. * */ public class ProxyReaderTest { @Test public void testNullCharArray() throws Exception { final ProxyReader proxy = new ProxyReaderImpl(new CustomNullReader(0)); proxy.read((char[])null); proxy.read(null, 0, 0); proxy.close(); } @Test public void testNullCharBuffer() throws Exception { final ProxyReader proxy = new ProxyReaderImpl(new CustomNullReader(0)); proxy.read((CharBuffer)null); proxy.close(); } /** ProxyReader implementation */ private static class ProxyReaderImpl extends ProxyReader { ProxyReaderImpl(final Reader proxy) { super(proxy); } } /** Custom NullReader implementation */ private static class CustomNullReader extends NullReader { CustomNullReader(final int len) { super(len); } @Override public int read(final char[] chars) throws IOException { return chars == null ? 0 : super.read(chars); } @Override public int read(final CharBuffer target) throws IOException { return target == null ? 0 : super.read(target); } } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/QueueInputStreamTest.java0100644 0000000 0000000 00000013446 13612062727 031720 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static java.nio.charset.StandardCharsets.UTF_8; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InterruptedIOException; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.stream.Stream; import org.apache.commons.io.IOUtils; import org.apache.commons.io.output.QueueOutputStream; import org.apache.commons.io.output.QueueOutputStreamTest; import org.apache.commons.lang3.StringUtils; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; /** * Test {@link QueueInputStream}. * * @see {@link QueueOutputStreamTest} */ public class QueueInputStreamTest { public static Stream inputData() { return Stream.of(Arguments.of(""), Arguments.of("1"), Arguments.of("12"), Arguments.of("1234"), Arguments.of("12345678"), Arguments.of(StringUtils.repeat("A", 4095)), Arguments.of(StringUtils.repeat("A", 4096)), Arguments.of(StringUtils.repeat("A", 4097)), Arguments.of(StringUtils.repeat("A", 8191)), Arguments.of(StringUtils.repeat("A", 8192)), Arguments.of(StringUtils.repeat("A", 8193)), Arguments.of(StringUtils.repeat("A", 8192 * 4))); } @ParameterizedTest(name = "inputData={0}") @MethodSource("inputData") public void unbufferedReadWrite(final String inputData) throws IOException { try (final QueueInputStream inputStream = new QueueInputStream(); final QueueOutputStream outputStream = inputStream.newQueueOutputStream()) { writeUnbuffered(outputStream, inputData); final String actualData = readUnbuffered(inputStream); assertEquals(inputData, actualData); } } @ParameterizedTest(name = "inputData={0}") @MethodSource("inputData") public void bufferedReads(final String inputData) throws IOException { final BlockingQueue queue = new LinkedBlockingQueue<>(); try (final BufferedInputStream inputStream = new BufferedInputStream(new QueueInputStream(queue)); final QueueOutputStream outputStream = new QueueOutputStream(queue)) { outputStream.write(inputData.getBytes(UTF_8)); final String actualData = IOUtils.toString(inputStream, UTF_8); assertEquals(inputData, actualData); } } @ParameterizedTest(name = "inputData={0}") @MethodSource("inputData") public void bufferedWrites(final String inputData) throws IOException { final BlockingQueue queue = new LinkedBlockingQueue<>(); try (final QueueInputStream inputStream = new QueueInputStream(queue); final BufferedOutputStream outputStream = new BufferedOutputStream(new QueueOutputStream(queue), defaultBufferSize())) { outputStream.write(inputData.getBytes(UTF_8)); outputStream.flush(); final String actualData = readUnbuffered(inputStream); assertEquals(inputData, actualData); } } @ParameterizedTest(name = "inputData={0}") @MethodSource("inputData") public void bufferedReadWrite(final String inputData) throws IOException { final BlockingQueue queue = new LinkedBlockingQueue<>(); try (final BufferedInputStream inputStream = new BufferedInputStream(new QueueInputStream(queue)); final BufferedOutputStream outputStream = new BufferedOutputStream(new QueueOutputStream(queue), defaultBufferSize())) { outputStream.write(inputData.getBytes(UTF_8)); outputStream.flush(); final String dataCopy = IOUtils.toString(inputStream, UTF_8); assertEquals(inputData, dataCopy); } } @Test public void testNullArgument() { assertThrows(NullPointerException.class, () -> new QueueInputStream(null), "queue is required"); } private int defaultBufferSize() { return 8192; } private void writeUnbuffered(final QueueOutputStream outputStream, final String inputData) throws InterruptedIOException { final byte[] bytes = inputData.getBytes(UTF_8); for (final byte oneByte : bytes) { outputStream.write(oneByte); } } private String readUnbuffered(final InputStream inputStream) throws IOException { final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); int n = -1; while ((n = inputStream.read()) != -1) { byteArrayOutputStream.write(n); } return byteArrayOutputStream.toString("UTF-8"); } } ././@LongLink0100644 0000000 0000000 00000000145 13612062727 011641 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/RandomAccessFileInputStreamTest.javacommons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/RandomAccessFileInputStreamTest.java0100644 0000000 0000000 00000017027 13612062727 033775 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.FileNotFoundException; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.charset.StandardCharsets; import org.junit.jupiter.api.Test; public class RandomAccessFileInputStreamTest { private static final String DATA_FILE = "src/test/resources/org/apache/commons/io/test-file-iso8859-1.bin"; private static final int DATA_FILE_LEN = 1430; private RandomAccessFile createRandomAccessFile() throws FileNotFoundException { return new RandomAccessFile(DATA_FILE, "r"); } @Test public void testAvailable() throws IOException { try (final RandomAccessFileInputStream inputStream = new RandomAccessFileInputStream(createRandomAccessFile(), true)) { assertEquals(DATA_FILE_LEN, inputStream.available()); } } @Test public void testAvailableLong() throws IOException { try (final RandomAccessFileInputStream inputStream = new RandomAccessFileInputStream(createRandomAccessFile(), true)) { assertEquals(DATA_FILE_LEN, inputStream.availableLong()); } } @Test public void testCtorCloseOnCloseFalse() throws IOException { try (RandomAccessFile file = createRandomAccessFile()) { try (final RandomAccessFileInputStream inputStream = new RandomAccessFileInputStream(file, false)) { assertFalse(inputStream.isCloseOnClose()); } file.read(); } } @Test public void testCtorCloseOnCloseTrue() throws IOException { try (RandomAccessFile file = createRandomAccessFile()) { try (final RandomAccessFileInputStream inputStream = new RandomAccessFileInputStream(file, true)) { assertTrue(inputStream.isCloseOnClose()); } assertThrows(IOException.class, () -> file.read()); } } @Test public void testCtorNullFile() { assertThrows(NullPointerException.class, () -> new RandomAccessFileInputStream(null)); } @Test public void testGetters() throws IOException { try (RandomAccessFile file = createRandomAccessFile()) { try (final RandomAccessFileInputStream inputStream = new RandomAccessFileInputStream(file, true)) { assertEquals(file, inputStream.getRandomAccessFile()); assertTrue(inputStream.isCloseOnClose()); } } } @Test public void testRead() throws IOException { try (final RandomAccessFileInputStream inputStream = new RandomAccessFileInputStream(createRandomAccessFile(), true)) { // A Test Line. assertEquals('A', inputStream.read()); assertEquals(' ', inputStream.read()); assertEquals('T', inputStream.read()); assertEquals('e', inputStream.read()); assertEquals('s', inputStream.read()); assertEquals('t', inputStream.read()); assertEquals(' ', inputStream.read()); assertEquals('L', inputStream.read()); assertEquals('i', inputStream.read()); assertEquals('n', inputStream.read()); assertEquals('e', inputStream.read()); assertEquals('.', inputStream.read()); assertEquals(DATA_FILE_LEN - 12, inputStream.available()); assertEquals(DATA_FILE_LEN - 12, inputStream.availableLong()); } } @Test public void testSkip() throws IOException { try (final RandomAccessFile file = createRandomAccessFile(); final RandomAccessFileInputStream inputStream = new RandomAccessFileInputStream(file, false)) { assertEquals(0, inputStream.skip(-1)); assertEquals(0, inputStream.skip(Integer.MIN_VALUE)); assertEquals(0, inputStream.skip(0)); // A Test Line. assertEquals('A', inputStream.read()); assertEquals(1, inputStream.skip(1)); assertEquals('T', inputStream.read()); assertEquals(1, inputStream.skip(1)); assertEquals('s', inputStream.read()); assertEquals(1, inputStream.skip(1)); assertEquals(' ', inputStream.read()); assertEquals(1, inputStream.skip(1)); assertEquals('i', inputStream.read()); assertEquals(1, inputStream.skip(1)); assertEquals('e', inputStream.read()); assertEquals(1, inputStream.skip(1)); // assertEquals(DATA_FILE_LEN - 12, inputStream.available()); assertEquals(DATA_FILE_LEN - 12, inputStream.availableLong()); assertEquals(10, inputStream.skip(10)); assertEquals(DATA_FILE_LEN - 22, inputStream.availableLong()); // final long avail = inputStream.availableLong(); assertEquals(avail, inputStream.skip(inputStream.availableLong())); // At EOF assertEquals(DATA_FILE_LEN, file.length()); assertEquals(DATA_FILE_LEN, file.getFilePointer()); // assertEquals(0, inputStream.skip(1)); assertEquals(0, inputStream.skip(1000000000000L)); } } @Test public void testReadByteArray() throws IOException { try (final RandomAccessFileInputStream inputStream = new RandomAccessFileInputStream(createRandomAccessFile(), true)) { // A Test Line. final int dataLen = 12; final byte[] buffer = new byte[dataLen]; assertEquals(dataLen, inputStream.read(buffer)); assertArrayEquals("A Test Line.".getBytes(StandardCharsets.ISO_8859_1), buffer); // assertEquals(DATA_FILE_LEN - dataLen, inputStream.available()); assertEquals(DATA_FILE_LEN - dataLen, inputStream.availableLong()); } } @Test public void testReadByteArrayBounds() throws IOException { try (final RandomAccessFileInputStream inputStream = new RandomAccessFileInputStream(createRandomAccessFile(), true)) { // A Test Line. final int dataLen = 12; final byte[] buffer = new byte[dataLen]; assertEquals(dataLen, inputStream.read(buffer, 0, dataLen)); assertArrayEquals("A Test Line.".getBytes(StandardCharsets.ISO_8859_1), buffer); // assertEquals(DATA_FILE_LEN - dataLen, inputStream.available()); assertEquals(DATA_FILE_LEN - dataLen, inputStream.availableLong()); } } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/ReadAheadInputStreamTest.java0100644 0000000 0000000 00000004314 13612062727 032424 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import java.io.IOException; import java.io.InputStream; import org.junit.jupiter.api.BeforeEach; /** * Tests {@link ReadAheadInputStream}. * * This class was ported and adapted from Apache Spark commit 933dc6cb7b3de1d8ccaf73d124d6eb95b947ed19 where it was * called {@code ReadAheadInputStreamSuite}. */ public class ReadAheadInputStreamTest extends AbstractInputStreamTest { @SuppressWarnings("resource") @Override @BeforeEach public void setUp() throws IOException { super.setUp(); inputStreams = new InputStream[] { // Tests equal and aligned buffers of wrapped an outer stream. new ReadAheadInputStream(new BufferedFileChannelInputStream(inputFile, 8 * 1024), 8 * 1024), // Tests aligned buffers, wrapped bigger than outer. new ReadAheadInputStream(new BufferedFileChannelInputStream(inputFile, 3 * 1024), 2 * 1024), // Tests aligned buffers, wrapped smaller than outer. new ReadAheadInputStream(new BufferedFileChannelInputStream(inputFile, 2 * 1024), 3 * 1024), // Tests unaligned buffers, wrapped bigger than outer. new ReadAheadInputStream(new BufferedFileChannelInputStream(inputFile, 321), 123), // Tests unaligned buffers, wrapped smaller than outer. new ReadAheadInputStream(new BufferedFileChannelInputStream(inputFile, 123), 321)}; } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/ReaderInputStreamTest.java0100644 0000000 0000000 00000013131 13612062727 032025 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.CharArrayReader; import java.io.IOException; import java.io.StringReader; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.Random; import org.junit.jupiter.api.Test; public class ReaderInputStreamTest { private static final String TEST_STRING = "\u00e0 peine arriv\u00e9s nous entr\u00e2mes dans sa chambre"; private static final String LARGE_TEST_STRING; static { final StringBuilder buffer = new StringBuilder(); for (int i=0; i<100; i++) { buffer.append(TEST_STRING); } LARGE_TEST_STRING = buffer.toString(); } private final Random random = new Random(); private void testWithSingleByteRead(final String testString, final String charsetName) throws IOException { final byte[] bytes = testString.getBytes(charsetName); try (final ReaderInputStream in = new ReaderInputStream(new StringReader(testString), charsetName)) { for (final byte b : bytes) { final int read = in.read(); assertTrue(read >= 0); assertTrue(read <= 255); assertEquals(b, (byte) read); } assertEquals(-1, in.read()); } } private void testWithBufferedRead(final String testString, final String charsetName) throws IOException { final byte[] expected = testString.getBytes(charsetName); try (final ReaderInputStream in = new ReaderInputStream(new StringReader(testString), charsetName)) { final byte[] buffer = new byte[128]; int offset = 0; while (true) { int bufferOffset = random.nextInt(64); final int bufferLength = random.nextInt(64); int read = in.read(buffer, bufferOffset, bufferLength); if (read == -1) { assertEquals(offset, expected.length); break; } assertTrue(read <= bufferLength); while (read > 0) { assertTrue(offset < expected.length); assertEquals(expected[offset], buffer[bufferOffset]); offset++; bufferOffset++; read--; } } } } @Test public void testUTF8WithSingleByteRead() throws IOException { testWithSingleByteRead(TEST_STRING, "UTF-8"); } @Test public void testLargeUTF8WithSingleByteRead() throws IOException { testWithSingleByteRead(LARGE_TEST_STRING, "UTF-8"); } @Test public void testUTF8WithBufferedRead() throws IOException { testWithBufferedRead(TEST_STRING, "UTF-8"); } @Test public void testLargeUTF8WithBufferedRead() throws IOException { testWithBufferedRead(LARGE_TEST_STRING, "UTF-8"); } @Test public void testUTF16WithSingleByteRead() throws IOException { testWithSingleByteRead(TEST_STRING, "UTF-16"); } @SuppressWarnings("deprecation") @Test public void testReadZero() throws Exception { final String inStr = "test"; try (final ReaderInputStream inputStream = new ReaderInputStream(new StringReader(inStr))) { final byte[] bytes = new byte[30]; assertEquals(0, inputStream.read(bytes, 0, 0)); assertEquals(inStr.length(), inputStream.read(bytes, 0, inStr.length() + 1)); // Should always return 0 for length == 0 assertEquals(0, inputStream.read(bytes, 0, 0)); } } @SuppressWarnings("deprecation") @Test public void testReadZeroEmptyString() throws Exception { try (final ReaderInputStream inputStream = new ReaderInputStream(new StringReader(""))) { final byte[] bytes = new byte[30]; // Should always return 0 for length == 0 assertEquals(0, inputStream.read(bytes, 0, 0)); assertEquals(-1, inputStream.read(bytes, 0, 1)); assertEquals(0, inputStream.read(bytes, 0, 0)); assertEquals(-1, inputStream.read(bytes, 0, 1)); } } /* * Tests https://issues.apache.org/jira/browse/IO-277 */ @Test public void testCharsetMismatchInfiniteLoop() throws IOException { // Input is UTF-8 bytes: 0xE0 0xB2 0xA0 final char[] inputChars = { (char) 0xE0, (char) 0xB2, (char) 0xA0 }; // Charset charset = Charset.forName("UTF-8"); // works final Charset charset = StandardCharsets.US_ASCII; // infinite loop try (ReaderInputStream stream = new ReaderInputStream(new CharArrayReader(inputChars), charset)) { while (stream.read() != -1) { } } } } ././@LongLink0100644 0000000 0000000 00000000157 13612062727 011644 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/ReversedLinesFileReaderTestParamBlockSize.javacommons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/ReversedLinesFileReaderTestParamBloc0100644 0000000 0000000 00000032411 13612062727 033767 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.apache.commons.io.StandardLineSeparator.CR; import static org.apache.commons.io.StandardLineSeparator.LF; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import java.io.File; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URISyntaxException; import java.util.stream.IntStream; import org.apache.commons.io.TestResources; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; public class ReversedLinesFileReaderTestParamBlockSize { private static final String UTF_8 = "UTF-8"; private static final String ISO_8859_1 = "ISO-8859-1"; // small and uneven block sizes are not used in reality but are good to show that the algorithm is solid public static IntStream blockSizes() { return IntStream.of(1, 3, 8, 256, 4096); } private ReversedLinesFileReader reversedLinesFileReader; // Strings are escaped in constants to avoid java source encoding issues (source file enc is UTF-8): // "A Test Line. Special chars: ÄäÜüÖöß Ãáéíïçñ ©µ¥£±²®" private static final String TEST_LINE = "A Test Line. Special chars: \u00C4\u00E4\u00DC\u00FC\u00D6\u00F6\u00DF \u00C3\u00E1\u00E9\u00ED\u00EF\u00E7\u00F1\u00C2 \u00A9\u00B5\u00A5\u00A3\u00B1\u00B2\u00AE"; // Hiragana letters: ����� private static final String TEST_LINE_SHIFT_JIS1 = "Hiragana letters: \u3041\u3042\u3043\u3044\u3045"; // Kanji letters: 明輸�京 private static final String TEST_LINE_SHIFT_JIS2 = "Kanji letters: \u660E\u8F38\u5B50\u4EAC"; // windows-31j characters private static final String TEST_LINE_WINDOWS_31J_1 = "\u3041\u3042\u3043\u3044\u3045"; private static final String TEST_LINE_WINDOWS_31J_2 = "\u660E\u8F38\u5B50\u4EAC"; // gbk characters (Simplified Chinese) private static final String TEST_LINE_GBK_1 = "\u660E\u8F38\u5B50\u4EAC"; private static final String TEST_LINE_GBK_2 = "\u7B80\u4F53\u4E2D\u6587"; // x-windows-949 characters (Korean) private static final String TEST_LINE_X_WINDOWS_949_1 = "\uD55C\uAD6D\uC5B4"; private static final String TEST_LINE_X_WINDOWS_949_2 = "\uB300\uD55C\uBBFC\uAD6D"; // x-windows-950 characters (Traditional Chinese) private static final String TEST_LINE_X_WINDOWS_950_1 = "\u660E\u8F38\u5B50\u4EAC"; private static final String TEST_LINE_X_WINDOWS_950_2 = "\u7E41\u9AD4\u4E2D\u6587"; @AfterEach public void closeReader() { try { if (reversedLinesFileReader != null) { reversedLinesFileReader.close(); } } catch (final Exception e) { // ignore } } @ParameterizedTest(name = "BlockSize={0}") @MethodSource("blockSizes") public void testIsoFileDefaults(final int testParamBlockSize) throws URISyntaxException, IOException { final File testFileIso = TestResources.getFile("/test-file-iso8859-1.bin"); reversedLinesFileReader = new ReversedLinesFileReader(testFileIso, testParamBlockSize, ISO_8859_1); assertFileWithShrinkingTestLines(reversedLinesFileReader); } @ParameterizedTest(name = "BlockSize={0}") @MethodSource("blockSizes") public void testUTF8FileWindowsBreaks(final int testParamBlockSize) throws URISyntaxException, IOException { final File testFileIso = TestResources.getFile("/test-file-utf8-win-linebr.bin"); reversedLinesFileReader = new ReversedLinesFileReader(testFileIso, testParamBlockSize, UTF_8); assertFileWithShrinkingTestLines(reversedLinesFileReader); } @ParameterizedTest(name = "BlockSize={0}") @MethodSource("blockSizes") public void testUTF8FileCRBreaks(final int testParamBlockSize) throws URISyntaxException, IOException { final File testFileIso = TestResources.getFile("/test-file-utf8-cr-only.bin"); reversedLinesFileReader = new ReversedLinesFileReader(testFileIso, testParamBlockSize, UTF_8); assertFileWithShrinkingTestLines(reversedLinesFileReader); } @ParameterizedTest(name = "BlockSize={0}") @MethodSource("blockSizes") public void testUTF8File(final int testParamBlockSize) throws URISyntaxException, IOException { final File testFileIso = TestResources.getFile("/test-file-utf8.bin"); reversedLinesFileReader = new ReversedLinesFileReader(testFileIso, testParamBlockSize, UTF_8); assertFileWithShrinkingTestLines(reversedLinesFileReader); } @ParameterizedTest(name = "BlockSize={0}") @MethodSource("blockSizes") public void testEmptyFile(final int testParamBlockSize) throws URISyntaxException, IOException { final File testFileEmpty = TestResources.getFile("/test-file-empty.bin"); reversedLinesFileReader = new ReversedLinesFileReader(testFileEmpty, testParamBlockSize, UTF_8); assertNull(reversedLinesFileReader.readLine()); } @ParameterizedTest(name = "BlockSize={0}") @MethodSource("blockSizes") public void testUTF16BEFile(final int testParamBlockSize) throws URISyntaxException, IOException { final File testFileUTF16BE = TestResources.getFile("/test-file-utf16be.bin"); reversedLinesFileReader = new ReversedLinesFileReader(testFileUTF16BE, testParamBlockSize, "UTF-16BE"); assertFileWithShrinkingTestLines(reversedLinesFileReader); } @ParameterizedTest(name = "BlockSize={0}") @MethodSource("blockSizes") public void testUTF16LEFile(final int testParamBlockSize) throws URISyntaxException, IOException { final File testFileUTF16LE = TestResources.getFile("/test-file-utf16le.bin"); reversedLinesFileReader = new ReversedLinesFileReader(testFileUTF16LE, testParamBlockSize, "UTF-16LE"); assertFileWithShrinkingTestLines(reversedLinesFileReader); } @ParameterizedTest(name = "BlockSize={0}") @MethodSource("blockSizes") public void testShiftJISFile(final int testParamBlockSize) throws URISyntaxException, IOException { final File testFileShiftJIS = TestResources.getFile("/test-file-shiftjis.bin"); reversedLinesFileReader = new ReversedLinesFileReader(testFileShiftJIS, testParamBlockSize, "Shift_JIS"); assertEqualsAndNoLineBreaks(TEST_LINE_SHIFT_JIS2, reversedLinesFileReader.readLine()); assertEqualsAndNoLineBreaks(TEST_LINE_SHIFT_JIS1, reversedLinesFileReader.readLine()); } @ParameterizedTest(name = "BlockSize={0}") @MethodSource("blockSizes") public void testWindows31jFile(final int testParamBlockSize) throws URISyntaxException, IOException { final File testFileWindows31J = TestResources.getFile("/test-file-windows-31j.bin"); reversedLinesFileReader = new ReversedLinesFileReader(testFileWindows31J, testParamBlockSize, "windows-31j"); assertEqualsAndNoLineBreaks(TEST_LINE_WINDOWS_31J_2, reversedLinesFileReader.readLine()); assertEqualsAndNoLineBreaks(TEST_LINE_WINDOWS_31J_1, reversedLinesFileReader.readLine()); } @ParameterizedTest(name = "BlockSize={0}") @MethodSource("blockSizes") public void testGBK(final int testParamBlockSize) throws URISyntaxException, IOException { final File testFileGBK = TestResources.getFile("/test-file-gbk.bin"); reversedLinesFileReader = new ReversedLinesFileReader(testFileGBK, testParamBlockSize, "GBK"); assertEqualsAndNoLineBreaks(TEST_LINE_GBK_2, reversedLinesFileReader.readLine()); assertEqualsAndNoLineBreaks(TEST_LINE_GBK_1, reversedLinesFileReader.readLine()); } @ParameterizedTest(name = "BlockSize={0}") @MethodSource("blockSizes") public void testxWindows949File(final int testParamBlockSize) throws URISyntaxException, IOException { final File testFilexWindows949 = TestResources.getFile("/test-file-x-windows-949.bin"); reversedLinesFileReader = new ReversedLinesFileReader(testFilexWindows949, testParamBlockSize, "x-windows-949"); assertEqualsAndNoLineBreaks(TEST_LINE_X_WINDOWS_949_2, reversedLinesFileReader.readLine()); assertEqualsAndNoLineBreaks(TEST_LINE_X_WINDOWS_949_1, reversedLinesFileReader.readLine()); } @ParameterizedTest(name = "BlockSize={0}") @MethodSource("blockSizes") public void testxWindows950File(final int testParamBlockSize) throws URISyntaxException, IOException { final File testFilexWindows950 = TestResources.getFile("/test-file-x-windows-950.bin"); reversedLinesFileReader = new ReversedLinesFileReader(testFilexWindows950, testParamBlockSize, "x-windows-950"); assertEqualsAndNoLineBreaks(TEST_LINE_X_WINDOWS_950_2, reversedLinesFileReader.readLine()); assertEqualsAndNoLineBreaks(TEST_LINE_X_WINDOWS_950_1, reversedLinesFileReader.readLine()); } @Test public void testFileSizeIsExactMultipleOfBlockSize() throws URISyntaxException, IOException { final int blockSize = 10; final File testFile20Bytes = TestResources.getFile("/test-file-20byteslength.bin"); reversedLinesFileReader = new ReversedLinesFileReader(testFile20Bytes, blockSize, ISO_8859_1); assertEqualsAndNoLineBreaks("987654321", reversedLinesFileReader.readLine()); assertEqualsAndNoLineBreaks("123456789", reversedLinesFileReader.readLine()); } @ParameterizedTest(name = "BlockSize={0}") @MethodSource("blockSizes") public void testUTF8FileWindowsBreaksSmallBlockSize2VerifyBlockSpanningNewLines(final int testParamBlockSize) throws URISyntaxException, IOException { final File testFileUtf8 = TestResources.getFile("/test-file-utf8-win-linebr.bin"); reversedLinesFileReader = new ReversedLinesFileReader(testFileUtf8, testParamBlockSize, UTF_8); assertFileWithShrinkingTestLines(reversedLinesFileReader); } @ParameterizedTest(name = "BlockSize={0}") @MethodSource("blockSizes") public void testIsoFileManyWindowsBreaksSmallBlockSize2VerifyBlockSpanningNewLines(final int testParamBlockSize) throws URISyntaxException, IOException { final File testFileIso = TestResources.getFile("/test-file-iso8859-1-shortlines-win-linebr.bin"); reversedLinesFileReader = new ReversedLinesFileReader(testFileIso, testParamBlockSize, ISO_8859_1); for (int i = 3; i > 0; i--) { for (int j = 1; j <= 3; j++) { assertEqualsAndNoLineBreaks("", reversedLinesFileReader.readLine()); } assertEqualsAndNoLineBreaks("" + i, reversedLinesFileReader.readLine()); } } @ParameterizedTest(name = "BlockSize={0}") @MethodSource("blockSizes") public void testUnsupportedEncodingUTF16(final int testParamBlockSize) throws URISyntaxException { final File testFileEmpty = TestResources.getFile("/test-file-empty.bin"); assertThrows(UnsupportedEncodingException.class, () -> new ReversedLinesFileReader(testFileEmpty, testParamBlockSize, "UTF-16").close()); } @ParameterizedTest(name = "BlockSize={0}") @MethodSource("blockSizes") public void testUnsupportedEncodingBig5(final int testParamBlockSize) throws URISyntaxException { final File testFileEncodingBig5 = TestResources.getFile("/test-file-empty.bin"); assertThrows(UnsupportedEncodingException.class, () -> new ReversedLinesFileReader(testFileEncodingBig5, testParamBlockSize, "Big5").close()); } private void assertFileWithShrinkingTestLines(final ReversedLinesFileReader reversedLinesFileReader) throws IOException { String line = null; int lineCount = 0; while ((line = reversedLinesFileReader.readLine()) != null) { lineCount++; assertEqualsAndNoLineBreaks("Line " + lineCount + " is not matching", TEST_LINE.substring(0, lineCount), line); } } static void assertEqualsAndNoLineBreaks(final String msg, final String expected, final String actual) { if (actual != null) { assertFalse(actual.contains(LF.getString()), "Line contains \\n: line=" + actual); assertFalse(actual.contains(CR.getString()), "Line contains \\r: line=" + actual); } assertEquals(expected, actual, msg); } static void assertEqualsAndNoLineBreaks(final String expected, final String actual) { assertEqualsAndNoLineBreaks(null, expected, actual); } } ././@LongLink0100644 0000000 0000000 00000000152 13612062727 011637 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/ReversedLinesFileReaderTestParamFile.javacommons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/ReversedLinesFileReaderTestParamFile0100644 0000000 0000000 00000013707 13612062727 033776 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.junit.jupiter.api.Assertions.assertEquals; import java.io.BufferedReader; import java.io.IOException; import java.io.Reader; import java.io.Writer; import java.net.URISyntaxException; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.nio.file.FileSystem; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Stack; import java.util.stream.Stream; import org.apache.commons.io.Charsets; import org.apache.commons.io.IOUtils; import org.apache.commons.io.TestResources; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import com.google.common.jimfs.Configuration; import com.google.common.jimfs.Jimfs; /** * Test checks symmetric behavior with BufferedReader. */ public class ReversedLinesFileReaderTestParamFile { public static Stream testDataIntegrityWithBufferedReader() throws IOException, URISyntaxException { // Make a file using the default encoding. final Path sourcePath = TestResources.getPath("test-file-utf8-win-linebr.bin"); final Path targetPath = Files.createTempFile("ReversedLinesFileReaderTestParamFile", ".bin"); try (Reader input = Files.newBufferedReader(sourcePath, StandardCharsets.UTF_8); Writer output = Files.newBufferedWriter(targetPath, Charset.defaultCharset())) { IOUtils.copyLarge(input, output); } // All tests return Stream.of(Arguments.of(targetPath.toAbsolutePath().toString(), null, null, false, false), Arguments.of("test-file-20byteslength.bin", "ISO_8859_1", null, false, true), Arguments.of("test-file-iso8859-1-shortlines-win-linebr.bin", "ISO_8859_1", null, false, true), Arguments.of("test-file-iso8859-1.bin", "ISO_8859_1", null, false, true), Arguments.of("test-file-shiftjis.bin", "Shift_JIS", null, false, true), Arguments.of("test-file-utf16be.bin", "UTF-16BE", null, false, true), Arguments.of("test-file-utf16le.bin", "UTF-16LE", null, false, true), Arguments.of("test-file-utf8-cr-only.bin", "UTF-8", null, false, true), Arguments.of("test-file-utf8-win-linebr.bin", "UTF-8", null, false, true, Arguments.of("test-file-utf8-win-linebr.bin", "UTF-8", 1, false, true), Arguments.of("test-file-utf8-win-linebr.bin", "UTF-8", 2, false, true), Arguments.of("test-file-utf8-win-linebr.bin", "UTF-8", 3, false, true), Arguments.of("test-file-utf8-win-linebr.bin", "UTF-8", 4, false, true), Arguments.of("test-file-utf8.bin", "UTF-8", null, false, true), Arguments.of("test-file-utf8.bin", "UTF-8", null, true, true), Arguments.of("test-file-windows-31j.bin", "windows-31j", null, false, true), Arguments.of("test-file-gbk.bin", "gbk", null, false, true), Arguments.of("test-file-x-windows-949.bin", "x-windows-949", null, false, true), Arguments.of("test-file-x-windows-950.bin", "x-windows-950", null, false, true))); } @ParameterizedTest(name = "{0}, encoding={1}, blockSize={2}, useNonDefaultFileSystem={3}, isResource={4}") @MethodSource public void testDataIntegrityWithBufferedReader(final String fileName, final String charsetName, final Integer blockSize, final boolean useNonDefaultFileSystem, final boolean isResource) throws IOException, URISyntaxException { Path filePath = isResource ? TestResources.getPath(fileName) : Paths.get(fileName); FileSystem fileSystem = null; if (useNonDefaultFileSystem) { fileSystem = Jimfs.newFileSystem(Configuration.unix()); filePath = Files.copy(filePath, fileSystem.getPath("/" + fileName)); } // We want to test null Charset in the ReversedLinesFileReader ctor. final Charset charset = charsetName != null ? Charset.forName(charsetName) : null; try (ReversedLinesFileReader reversedLinesFileReader = blockSize == null ? new ReversedLinesFileReader(filePath, charset) : new ReversedLinesFileReader(filePath, blockSize, charset)) { final Stack lineStack = new Stack<>(); String line; try (BufferedReader bufferedReader = Files.newBufferedReader(filePath, Charsets.toCharset(charset))) { // read all lines in normal order while ((line = bufferedReader.readLine()) != null) { lineStack.push(line); } } // read in reverse order and compare with lines from stack while ((line = reversedLinesFileReader.readLine()) != null) { final String lineFromBufferedReader = lineStack.pop(); assertEquals(lineFromBufferedReader, line); } assertEquals(0, lineStack.size(), "Stack should be empty"); if (fileSystem != null) { fileSystem.close(); } } } } ././@LongLink0100644 0000000 0000000 00000000147 13612062727 011643 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/ReversedLinesFileReaderTestSimple.javacommons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/ReversedLinesFileReaderTestSimple.ja0100644 0000000 0000000 00000010643 13612062727 033754 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.apache.commons.io.input.ReversedLinesFileReaderTestParamBlockSize.assertEqualsAndNoLineBreaks; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.File; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URISyntaxException; import java.util.List; import org.apache.commons.io.IOUtils; import org.apache.commons.io.TestResources; import org.junit.jupiter.api.Test; public class ReversedLinesFileReaderTestSimple { @Test public void testFileSizeIsExactMultipleOfBlockSize() throws URISyntaxException, IOException { final int blockSize = 10; final File testFile20Bytes = TestResources.getFile("/test-file-20byteslength.bin"); try (ReversedLinesFileReader reversedLinesFileReader = new ReversedLinesFileReader(testFile20Bytes, blockSize, "ISO-8859-1")) { assertEqualsAndNoLineBreaks("987654321", reversedLinesFileReader.readLine()); assertEqualsAndNoLineBreaks("123456789", reversedLinesFileReader.readLine()); } } @Test public void testLineCount() throws URISyntaxException, IOException { final int blockSize = 10; final File testFile20Bytes = TestResources.getFile("/test-file-20byteslength.bin"); try (ReversedLinesFileReader reversedLinesFileReader = new ReversedLinesFileReader(testFile20Bytes, blockSize, "ISO-8859-1")) { assertThrows(IllegalArgumentException.class, () -> reversedLinesFileReader.readLines(-1)); assertTrue(reversedLinesFileReader.readLines(0).isEmpty()); final List lines = reversedLinesFileReader.readLines(2); assertEqualsAndNoLineBreaks("987654321", lines.get(0)); assertEqualsAndNoLineBreaks("123456789", lines.get(1)); assertTrue(reversedLinesFileReader.readLines(0).isEmpty()); assertTrue(reversedLinesFileReader.readLines(10000).isEmpty()); } } @Test public void testToString() throws URISyntaxException, IOException { final int blockSize = 10; final File testFile20Bytes = TestResources.getFile("/test-file-20byteslength.bin"); try (ReversedLinesFileReader reversedLinesFileReader = new ReversedLinesFileReader(testFile20Bytes, blockSize, "ISO-8859-1")) { assertThrows(IllegalArgumentException.class, () -> reversedLinesFileReader.toString(-1)); assertTrue(reversedLinesFileReader.readLines(0).isEmpty()); final String lines = reversedLinesFileReader.toString(2); assertEquals("123456789" + System.lineSeparator() + "987654321" + System.lineSeparator(), lines); assertTrue(reversedLinesFileReader.toString(0).isEmpty()); assertTrue(reversedLinesFileReader.toString(10000).isEmpty()); } } @Test public void testUnsupportedEncodingUTF16() throws URISyntaxException { final File testFileEmpty = TestResources.getFile("/test-file-empty.bin"); assertThrows(UnsupportedEncodingException.class, () -> new ReversedLinesFileReader(testFileEmpty, IOUtils.DEFAULT_BUFFER_SIZE, "UTF-16").close()); } @Test public void testUnsupportedEncodingBig5() throws URISyntaxException { final File testFileEncodingBig5 = TestResources.getFile("/test-file-empty.bin"); assertThrows(UnsupportedEncodingException.class, () -> new ReversedLinesFileReader(testFileEncodingBig5, IOUtils.DEFAULT_BUFFER_SIZE, "Big5").close()); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/SequenceReaderTest.java0100644 0000000 0000000 00000015717 13612062727 031336 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.apache.commons.lang3.StringUtils; import org.junit.jupiter.api.Test; /** * Test case for {@link SequenceReader}. */ public class SequenceReaderTest { private static final char NUL = 0; private void checkArray(final char[] expected, final char[] actual) { for (int i = 0; i < expected.length; i++) { assertEquals(expected[i], actual[i], "Compare[" + i + "]"); } } private void checkRead(final Reader reader, final String expected) throws IOException { for (int i = 0; i < expected.length(); i++) { assertEquals(expected.charAt(i), (char) reader.read(), "Read[" + i + "] of '" + expected + "'"); } } private void checkReadEof(final Reader reader) throws IOException { for (int i = 0; i < 10; i++) { assertEquals(-1, reader.read()); } } @Test public void testClose() throws IOException { try (final Reader reader = new SequenceReader(new CharSequenceReader("FooBar"))) { checkRead(reader, "Foo"); reader.close(); checkReadEof(reader); } } @Test public void testReadClosedReader() throws IOException { @SuppressWarnings("resource") final Reader reader = new SequenceReader(new CharSequenceReader("FooBar")); reader.close(); checkReadEof(reader); } @Test public void testMarkSupported() throws Exception { try (final Reader reader = new SequenceReader()) { assertFalse(reader.markSupported()); } } @Test public void testRead() throws IOException { try (final Reader reader = new SequenceReader(new StringReader("Foo"), new StringReader("Bar"))) { assertEquals('F', reader.read()); assertEquals('o', reader.read()); assertEquals('o', reader.read()); assertEquals('B', reader.read()); assertEquals('a', reader.read()); assertEquals('r', reader.read()); checkReadEof(reader); } } @Test public void testReadCharArray() throws IOException { try (final Reader reader = new SequenceReader(new StringReader("Foo"), new StringReader("Bar"))) { char[] chars = new char[2]; assertEquals(2, reader.read(chars)); checkArray(new char[] { 'F', 'o' }, chars); chars = new char[3]; assertEquals(3, reader.read(chars)); checkArray(new char[] { 'o', 'B', 'a' }, chars); chars = new char[3]; assertEquals(1, reader.read(chars)); checkArray(new char[] { 'r', NUL, NUL }, chars); assertEquals(-1, reader.read(chars)); } } @Test public void testReadCharArrayPortion() throws IOException { final char[] chars = new char[10]; try (final Reader reader = new SequenceReader(new StringReader("Foo"), new StringReader("Bar"))) { assertEquals(3, reader.read(chars, 3, 3)); checkArray(new char[] { NUL, NUL, NUL, 'F', 'o', 'o' }, chars); assertEquals(3, reader.read(chars, 0, 3)); checkArray(new char[] { 'B', 'a', 'r', 'F', 'o', 'o', NUL }, chars); assertEquals(-1, reader.read(chars)); assertThrows(IndexOutOfBoundsException.class, () -> reader.read(chars, 10, 10)); assertThrows(NullPointerException.class, () -> reader.read(null, 0, 10)); } } @Test public void testReadCollection() throws IOException { final Collection readers = new ArrayList<>(); readers.add(new StringReader("F")); readers.add(new StringReader("B")); try (final Reader reader = new SequenceReader(readers)) { assertEquals('F', reader.read()); assertEquals('B', reader.read()); checkReadEof(reader); } } @Test public void testReadIterable() throws IOException { final Collection readers = new ArrayList<>(); readers.add(new StringReader("F")); readers.add(new StringReader("B")); final Iterable iterable = readers; try (final Reader reader = new SequenceReader(iterable)) { assertEquals('F', reader.read()); assertEquals('B', reader.read()); checkReadEof(reader); } } @Test public void testReadLength0Readers() throws IOException { try (final Reader reader = new SequenceReader(new StringReader(StringUtils.EMPTY), new StringReader(StringUtils.EMPTY), new StringReader(StringUtils.EMPTY))) { checkReadEof(reader); } } @Test public void testReadLength1Readers() throws IOException { try (final Reader reader = new SequenceReader( // @formatter:off new StringReader("0"), new StringReader("1"), new StringReader("2"), new StringReader("3"))) { // @formatter:on assertEquals('0', reader.read()); assertEquals('1', reader.read()); assertEquals('2', reader.read()); assertEquals('3', reader.read()); } } @Test public void testReadList() throws IOException { final List readers = new ArrayList<>(); readers.add(new StringReader("F")); readers.add(new StringReader("B")); try (final Reader reader = new SequenceReader(readers)) { assertEquals('F', reader.read()); assertEquals('B', reader.read()); checkReadEof(reader); } } @Test public void testSkip() throws IOException { try (final Reader reader = new SequenceReader(new StringReader("Foo"), new StringReader("Bar"))) { assertEquals(3, reader.skip(3)); checkRead(reader, "Bar"); assertEquals(0, reader.skip(3)); } } }commons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/SwappedDataInputStreamTest.java0100644 0000000 0000000 00000010521 13612062727 033020 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.ByteArrayInputStream; import java.io.IOException; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Test for the SwappedDataInputStream. This also * effectively tests the underlying EndianUtils Stream methods. * */ public class SwappedDataInputStreamTest { private SwappedDataInputStream sdis; private byte[] bytes; @BeforeEach public void setUp() { bytes = new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; final ByteArrayInputStream bais = new ByteArrayInputStream( bytes ); this.sdis = new SwappedDataInputStream( bais ); } @AfterEach public void tearDown() { this.sdis = null; } @Test public void testReadBoolean() throws IOException { bytes = new byte[] {0x00, 0x01, 0x02,}; try ( final ByteArrayInputStream bais = new ByteArrayInputStream(bytes); final SwappedDataInputStream sdis = new SwappedDataInputStream(bais) ) { assertFalse(sdis.readBoolean()); assertTrue(sdis.readBoolean()); assertTrue(sdis.readBoolean()); } } @Test public void testReadByte() throws IOException { assertEquals( 0x01, this.sdis.readByte() ); } @Test public void testReadChar() throws IOException { assertEquals( (char) 0x0201, this.sdis.readChar() ); } @Test public void testReadDouble() throws IOException { assertEquals( Double.longBitsToDouble(0x0807060504030201L), this.sdis.readDouble(), 0 ); } @Test public void testReadFloat() throws IOException { assertEquals( Float.intBitsToFloat(0x04030201), this.sdis.readFloat(), 0 ); } @Test public void testReadFully() throws IOException { final byte[] bytesIn = new byte[8]; this.sdis.readFully(bytesIn); for( int i=0; i<8; i++) { assertEquals( bytes[i], bytesIn[i] ); } } @Test public void testReadInt() throws IOException { assertEquals( 0x04030201, this.sdis.readInt() ); } @Test public void testReadLine() { assertThrows(UnsupportedOperationException.class, () -> this.sdis.readLine(), "readLine should be unsupported. "); } @Test public void testReadLong() throws IOException { assertEquals( 0x0807060504030201L, this.sdis.readLong() ); } @Test public void testReadShort() throws IOException { assertEquals( (short) 0x0201, this.sdis.readShort() ); } @Test public void testReadUnsignedByte() throws IOException { assertEquals( 0x01, this.sdis.readUnsignedByte() ); } @Test public void testReadUnsignedShort() throws IOException { assertEquals( (short) 0x0201, this.sdis.readUnsignedShort() ); } @Test public void testReadUTF() { assertThrows(UnsupportedOperationException.class, () -> this.sdis.readUTF(), "readUTF should be unsupported. "); } @Test public void testSkipBytes() throws IOException { this.sdis.skipBytes(4); assertEquals( 0x08070605, this.sdis.readInt() ); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/TaggedInputStreamTest.java0100644 0000000 0000000 00000010621 13612062727 032017 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.util.UUID; import org.apache.commons.io.TaggedIOException; import org.junit.jupiter.api.Test; /** * JUnit Test Case for {@link TaggedInputStream}. */ public class TaggedInputStreamTest { @Test public void testEmptyStream() throws IOException { final InputStream stream = new TaggedInputStream(ClosedInputStream.CLOSED_INPUT_STREAM); assertEquals(0, stream.available()); assertEquals(-1, stream.read()); assertEquals(-1, stream.read(new byte[1])); assertEquals(-1, stream.read(new byte[1], 0, 1)); stream.close(); } @Test public void testNormalStream() throws IOException { final InputStream stream = new TaggedInputStream( new ByteArrayInputStream(new byte[] { 'a', 'b', 'c' })); assertEquals(3, stream.available()); assertEquals('a', stream.read()); final byte[] buffer = new byte[1]; assertEquals(1, stream.read(buffer)); assertEquals('b', buffer[0]); assertEquals(1, stream.read(buffer, 0, 1)); assertEquals('c', buffer[0]); assertEquals(-1, stream.read()); stream.close(); } @Test public void testBrokenStream() { final IOException exception = new IOException("test exception"); final TaggedInputStream stream = new TaggedInputStream(new BrokenInputStream(exception)); // Test the available() method try { stream.available(); fail("Expected exception not thrown."); } catch (final IOException e) { assertTrue(stream.isCauseOf(e)); try { stream.throwIfCauseOf(e); fail("Expected exception not thrown."); } catch (final IOException e2) { assertEquals(exception, e2); } } // Test the read() method try { stream.read(); fail("Expected exception not thrown."); } catch (final IOException e) { assertTrue(stream.isCauseOf(e)); try { stream.throwIfCauseOf(e); fail("Expected exception not thrown."); } catch (final IOException e2) { assertEquals(exception, e2); } } // Test the close() method try { stream.close(); fail("Expected exception not thrown."); } catch (final IOException e) { assertTrue(stream.isCauseOf(e)); try { stream.throwIfCauseOf(e); fail("Expected exception not thrown."); } catch (final IOException e2) { assertEquals(exception, e2); } } } @Test public void testOtherException() throws Exception { final IOException exception = new IOException("test exception"); final TaggedInputStream stream = new TaggedInputStream(ClosedInputStream.CLOSED_INPUT_STREAM); assertFalse(stream.isCauseOf(exception)); assertFalse(stream.isCauseOf( new TaggedIOException(exception, UUID.randomUUID()))); stream.throwIfCauseOf(exception); stream.throwIfCauseOf( new TaggedIOException(exception, UUID.randomUUID())); stream.close(); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/TaggedReaderTest.java0100644 0000000 0000000 00000010346 13612062727 030752 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import java.util.UUID; import org.apache.commons.io.TaggedIOException; import org.junit.jupiter.api.Test; /** * JUnit Test Case for {@link TaggedReader}. */ public class TaggedReaderTest { @Test public void testEmptyReader() throws IOException { try (final Reader reader = new TaggedReader(ClosedReader.CLOSED_READER)) { assertFalse(reader.ready()); assertEquals(-1, reader.read()); assertEquals(-1, reader.read(new char[1])); assertEquals(-1, reader.read(new char[1], 0, 1)); } } @Test public void testNormalReader() throws IOException { try (final Reader reader = new TaggedReader(new StringReader("abc"))) { assertTrue(reader.ready()); assertEquals('a', reader.read()); final char[] buffer = new char[1]; assertEquals(1, reader.read(buffer)); assertEquals('b', buffer[0]); assertEquals(1, reader.read(buffer, 0, 1)); assertEquals('c', buffer[0]); assertEquals(-1, reader.read()); } } @Test public void testBrokenReader() { final IOException exception = new IOException("test exception"); final TaggedReader reader = new TaggedReader(new BrokenReader(exception)); // Test the ready() method try { reader.ready(); fail("Expected exception not thrown."); } catch (final IOException e) { assertTrue(reader.isCauseOf(e)); try { reader.throwIfCauseOf(e); fail("Expected exception not thrown."); } catch (final IOException e2) { assertEquals(exception, e2); } } // Test the read() method try { reader.read(); fail("Expected exception not thrown."); } catch (final IOException e) { assertTrue(reader.isCauseOf(e)); try { reader.throwIfCauseOf(e); fail("Expected exception not thrown."); } catch (final IOException e2) { assertEquals(exception, e2); } } // Test the close() method try { reader.close(); fail("Expected exception not thrown."); } catch (final IOException e) { assertTrue(reader.isCauseOf(e)); try { reader.throwIfCauseOf(e); fail("Expected exception not thrown."); } catch (final IOException e2) { assertEquals(exception, e2); } } } @Test public void testOtherException() throws Exception { final IOException exception = new IOException("test exception"); try (final TaggedReader reader = new TaggedReader(ClosedReader.CLOSED_READER)) { assertFalse(reader.isCauseOf(exception)); assertFalse(reader.isCauseOf(new TaggedIOException(exception, UUID.randomUUID()))); reader.throwIfCauseOf(exception); reader.throwIfCauseOf(new TaggedIOException(exception, UUID.randomUUID())); } } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/TailerTest.java0100644 0000000 0000000 00000045233 13612062727 027657 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.RandomAccessFile; import java.io.Writer; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.StandardOpenOption; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.concurrent.Executor; import java.util.concurrent.ScheduledThreadPoolExecutor; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.io.TestResources; import org.apache.commons.io.test.TestUtils; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; /** * Tests for {@link Tailer}. * */ public class TailerTest { @TempDir public static File temporaryFolder; private Tailer tailer; @AfterEach public void tearDown() { if (tailer != null) { tailer.stop(); } } @Test @SuppressWarnings("squid:S2699") // Suppress "Add at least one assertion to this test case" public void testLongFile() throws Exception { final long delay = 50; final File file = new File(temporaryFolder, "testLongFile.txt"); createFile(file, 0); try (final Writer writer = Files.newBufferedWriter(file.toPath(), StandardOpenOption.APPEND)) { for (int i = 0; i < 100000; i++) { writer.write("LineLineLineLineLineLineLineLineLineLine\n"); } writer.write("SBTOURIST\n"); } final TestTailerListener listener = new TestTailerListener(); tailer = new Tailer(file, listener, delay, false); // final long start = System.currentTimeMillis(); final Thread thread = new Thread(tailer); thread.start(); List lines = listener.getLines(); while (lines.isEmpty() || !lines.get(lines.size() - 1).equals("SBTOURIST")) { lines = listener.getLines(); } // System.out.println("Elapsed: " + (System.currentTimeMillis() - start)); listener.clear(); } @Test @SuppressWarnings("squid:S2699") // Suppress "Add at least one assertion to this test case" public void testBufferBreak() throws Exception { final long delay = 50; final File file = new File(temporaryFolder, "testBufferBreak.txt"); createFile(file, 0); writeString(file, "SBTOURIST\n"); final TestTailerListener listener = new TestTailerListener(); tailer = new Tailer(file, listener, delay, false, 1); final Thread thread = new Thread(tailer); thread.start(); List lines = listener.getLines(); while (lines.isEmpty() || !lines.get(lines.size() - 1).equals("SBTOURIST")) { lines = listener.getLines(); } listener.clear(); } @Test public void testMultiByteBreak() throws Exception { // System.out.println("testMultiByteBreak() Default charset: " + Charset.defaultCharset().displayName()); final long delay = 50; final File origin = TestResources.getFile("test-file-utf8.bin"); final File file = new File(temporaryFolder, "testMultiByteBreak.txt"); createFile(file, 0); final TestTailerListener listener = new TestTailerListener(); final String osname = System.getProperty("os.name"); final boolean isWindows = osname.startsWith("Windows"); // Need to use UTF-8 to read & write the file otherwise it can be corrupted (depending on the default charset) final Charset charsetUTF8 = StandardCharsets.UTF_8; tailer = new Tailer(file, charsetUTF8, listener, delay, false, isWindows, IOUtils.DEFAULT_BUFFER_SIZE); final Thread thread = new Thread(tailer); thread.start(); try (Writer out = new OutputStreamWriter(Files.newOutputStream(file.toPath()), charsetUTF8); BufferedReader reader = new BufferedReader(new InputStreamReader(Files.newInputStream(origin.toPath()), charsetUTF8))) { final List lines = new ArrayList<>(); String line; while((line = reader.readLine()) != null){ out.write(line); out.write("\n"); lines.add(line); } out.close(); // ensure data is written final long testDelayMillis = delay * 10; TestUtils.sleep(testDelayMillis); final List tailerlines = listener.getLines(); assertEquals(lines.size(), tailerlines.size(), "line count"); for(int i = 0,len = lines.size();i lines = listener.getLines(); assertEquals(0, lines.size(), "1 line count"); writeString(file, " one\n"); TestUtils.sleep(delay * 2); lines = listener.getLines(); assertEquals(1, lines.size(), "1 line count"); assertEquals("Line one", lines.get(0), "1 line 1"); listener.clear(); } @Test public void testTailer() throws Exception { // Create & start the Tailer final long delayMillis = 50; final File file = new File(temporaryFolder, "tailer1-test.txt"); createFile(file, 0); final TestTailerListener listener = new TestTailerListener(); final String osname = System.getProperty("os.name"); final boolean isWindows = osname.startsWith("Windows"); tailer = new Tailer(file, listener, delayMillis, false, isWindows); final Thread thread = new Thread(tailer); thread.start(); // Write some lines to the file write(file, "Line one", "Line two"); final long testDelayMillis = delayMillis * 10; TestUtils.sleep(testDelayMillis); List lines = listener.getLines(); assertEquals(2, lines.size(), "1 line count"); assertEquals("Line one", lines.get(0), "1 line 1"); assertEquals("Line two", lines.get(1), "1 line 2"); listener.clear(); // Write another line to the file write(file, "Line three"); TestUtils.sleep(testDelayMillis); lines = listener.getLines(); assertEquals(1, lines.size(), "2 line count"); assertEquals("Line three", lines.get(0), "2 line 3"); listener.clear(); // Check file does actually have all the lines lines = FileUtils.readLines(file, "UTF-8"); assertEquals(3, lines.size(), "3 line count"); assertEquals("Line one", lines.get(0), "3 line 1"); assertEquals("Line two", lines.get(1), "3 line 2"); assertEquals("Line three", lines.get(2), "3 line 3"); // Delete & re-create file.delete(); assertFalse(file.exists(), "File should not exist"); createFile(file, 0); assertTrue(file.exists(), "File should now exist"); TestUtils.sleep(testDelayMillis); // Write another line write(file, "Line four"); TestUtils.sleep(testDelayMillis); lines = listener.getLines(); assertEquals(1, lines.size(), "4 line count"); assertEquals("Line four", lines.get(0), "4 line 3"); listener.clear(); // Stop thread.interrupt(); TestUtils.sleep(testDelayMillis * 4); write(file, "Line five"); assertEquals(0, listener.getLines().size(), "4 line count"); assertNotNull(listener.exception, "Missing InterruptedException"); assertTrue(listener.exception instanceof InterruptedException, "Unexpected Exception: " + listener.exception); assertEquals(1 , listener.initialized, "Expected init to be called"); // assertEquals(0 , listener.notFound, "fileNotFound should not be called"); // there is a window when it might be called assertEquals(1 , listener.rotated, "fileRotated should be be called"); } @Test public void testTailerEndOfFileReached() throws Exception { // Create & start the Tailer final long delayMillis = 50; final long testDelayMillis = delayMillis * 10; final File file = new File(temporaryFolder, "tailer-eof-test.txt"); createFile(file, 0); final TestTailerListener listener = new TestTailerListener(); final String osname = System.getProperty("os.name"); final boolean isWindows = osname.startsWith("Windows"); tailer = new Tailer(file, listener, delayMillis, false, isWindows); final Thread thread = new Thread(tailer); thread.start(); // write a few lines write(file, "line1", "line2", "line3"); TestUtils.sleep(testDelayMillis); // write a few lines write(file, "line4", "line5", "line6"); TestUtils.sleep(testDelayMillis); // write a few lines write(file, "line7", "line8", "line9"); TestUtils.sleep(testDelayMillis); // May be > 3 times due to underlying OS behavior wrt streams assertTrue(listener.reachedEndOfFile >= 3, "end of file reached at least 3 times"); } protected void createFile(final File file, final long size) throws IOException { if (!file.getParentFile().exists()) { throw new IOException("Cannot create file " + file + " as the parent directory does not exist"); } try (final BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(file.toPath()))) { TestUtils.generateTestData(output, size); } // try to make sure file is found // (to stop continuum occasionally failing) RandomAccessFile reader = null; try { while (reader == null) { try { reader = new RandomAccessFile(file.getPath(), "r"); } catch (final FileNotFoundException ignore) { } try { TestUtils.sleep(200L); } catch (final InterruptedException ignore) { // ignore } } } finally { try { IOUtils.close(reader); } catch (final IOException ignored) { // ignored } } } /** Append some lines to a file */ private void write(final File file, final String... lines) throws Exception { try (Writer writer = Files.newBufferedWriter(file.toPath(), StandardOpenOption.APPEND)) { for (final String line : lines) { writer.write(line + "\n"); } } } /** Append a string to a file */ private void writeString(final File file, final String ... strings) throws Exception { try (Writer writer = Files.newBufferedWriter(file.toPath(), StandardOpenOption.APPEND)) { for (final String string : strings) { writer.write(string); } } } @Test public void testStopWithNoFile() throws Exception { final File file = new File(temporaryFolder,"nosuchfile"); assertFalse(file.exists(), "nosuchfile should not exist"); final TestTailerListener listener = new TestTailerListener(); final int delay = 100; final int idle = 50; // allow time for thread to work tailer = Tailer.create(file, listener, delay, false); TestUtils.sleep(idle); tailer.stop(); TestUtils.sleep(delay+idle); assertNull(listener.exception, "Should not generate Exception"); assertEquals(1 , listener.initialized, "Expected init to be called"); assertTrue(listener.notFound > 0, "fileNotFound should be called"); assertEquals(0 , listener.rotated, "fileRotated should be not be called"); assertEquals(0, listener.reachedEndOfFile, "end of file never reached"); } /* * Tests [IO-357][Tailer] InterruptedException while the thead is sleeping is silently ignored. */ @Test public void testInterrupt() throws Exception { final File file = new File(temporaryFolder, "nosuchfile"); assertFalse(file.exists(), "nosuchfile should not exist"); final TestTailerListener listener = new TestTailerListener(); // Use a long delay to try to make sure the test thread calls interrupt() while the tailer thread is sleeping. final int delay = 1000; final int idle = 50; // allow time for thread to work tailer = new Tailer(file, listener, delay, false, IOUtils.DEFAULT_BUFFER_SIZE); final Thread thread = new Thread(tailer); thread.setDaemon(true); thread.start(); TestUtils.sleep(idle); thread.interrupt(); TestUtils.sleep(delay + idle); assertNotNull(listener.exception, "Missing InterruptedException"); assertTrue(listener.exception instanceof InterruptedException, "Unexpected Exception: " + listener.exception); assertEquals(1, listener.initialized, "Expected init to be called"); assertTrue(listener.notFound > 0, "fileNotFound should be called"); assertEquals(0, listener.rotated, "fileRotated should be not be called"); assertEquals(0, listener.reachedEndOfFile, "end of file never reached"); } @Test public void testStopWithNoFileUsingExecutor() throws Exception { final File file = new File(temporaryFolder,"nosuchfile"); assertFalse(file.exists(), "nosuchfile should not exist"); final TestTailerListener listener = new TestTailerListener(); final int delay = 100; final int idle = 50; // allow time for thread to work tailer = new Tailer(file, listener, delay, false); final Executor exec = new ScheduledThreadPoolExecutor(1); exec.execute(tailer); TestUtils.sleep(idle); tailer.stop(); TestUtils.sleep(delay+idle); assertNull(listener.exception, "Should not generate Exception"); assertEquals(1 , listener.initialized, "Expected init to be called"); assertTrue(listener.notFound > 0, "fileNotFound should be called"); assertEquals(0 , listener.rotated, "fileRotated should be not be called"); assertEquals(0, listener.reachedEndOfFile, "end of file never reached"); } @Test public void testIO335() throws Exception { // test CR behavior // Create & start the Tailer final long delayMillis = 50; final File file = new File(temporaryFolder, "tailer-testio334.txt"); createFile(file, 0); final TestTailerListener listener = new TestTailerListener(); tailer = new Tailer(file, listener, delayMillis, false); final Thread thread = new Thread(tailer); thread.start(); // Write some lines to the file writeString(file, "CRLF\r\n", "LF\n", "CR\r", "CRCR\r\r", "trail"); final long testDelayMillis = delayMillis * 10; TestUtils.sleep(testDelayMillis); final List lines = listener.getLines(); assertEquals(4, lines.size(), "line count"); assertEquals("CRLF", lines.get(0), "line 1"); assertEquals("LF", lines.get(1), "line 2"); assertEquals("CR", lines.get(2), "line 3"); assertEquals("CRCR\r", lines.get(3), "line 4"); } /** * Test {@link TailerListener} implementation. */ private static class TestTailerListener extends TailerListenerAdapter { // Must be synchronized because it is written by one thread and read by another private final List lines = Collections.synchronizedList(new ArrayList()); volatile Exception exception; volatile int notFound; volatile int rotated; volatile int initialized; volatile int reachedEndOfFile; @Override public void handle(final String line) { lines.add(line); } public List getLines() { return lines; } public void clear() { lines.clear(); } @Override public void handle(final Exception e) { exception = e; } @Override public void init(final Tailer tailer) { initialized++; // not atomic, but OK because only updated here. } @Override public void fileNotFound() { notFound++; // not atomic, but OK because only updated here. } @Override public void fileRotated() { rotated++; // not atomic, but OK because only updated here. } @Override public void endOfFileReached() { reachedEndOfFile++; // not atomic, but OK because only updated here. } } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/TeeInputStreamTest.java0100644 0000000 0000000 00000013303 13612062727 031341 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.apache.commons.io.test.ThrowOnCloseInputStream; import org.apache.commons.io.test.ThrowOnCloseOutputStream; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * JUnit Test Case for {@link TeeInputStream}. */ public class TeeInputStreamTest { private final String ASCII = "US-ASCII"; private InputStream tee; private ByteArrayOutputStream output; @BeforeEach public void setUp() throws Exception { final InputStream input = new ByteArrayInputStream("abc".getBytes(ASCII)); output = new ByteArrayOutputStream(); tee = new TeeInputStream(input, output); } @Test public void testReadNothing() throws Exception { assertEquals("", new String(output.toString(ASCII))); } @Test public void testReadOneByte() throws Exception { assertEquals('a', tee.read()); assertEquals("a", new String(output.toString(ASCII))); } @Test public void testReadEverything() throws Exception { assertEquals('a', tee.read()); assertEquals('b', tee.read()); assertEquals('c', tee.read()); assertEquals(-1, tee.read()); assertEquals("abc", new String(output.toString(ASCII))); } @Test public void testReadToArray() throws Exception { final byte[] buffer = new byte[8]; assertEquals(3, tee.read(buffer)); assertEquals('a', buffer[0]); assertEquals('b', buffer[1]); assertEquals('c', buffer[2]); assertEquals(-1, tee.read(buffer)); assertEquals("abc", new String(output.toString(ASCII))); } @Test public void testReadToArrayWithOffset() throws Exception { final byte[] buffer = new byte[8]; assertEquals(3, tee.read(buffer, 4, 4)); assertEquals('a', buffer[4]); assertEquals('b', buffer[5]); assertEquals('c', buffer[6]); assertEquals(-1, tee.read(buffer, 4, 4)); assertEquals("abc", new String(output.toString(ASCII))); } @Test public void testSkip() throws Exception { assertEquals('a', tee.read()); assertEquals(1, tee.skip(1)); assertEquals('c', tee.read()); assertEquals(-1, tee.read()); assertEquals("ac", new String(output.toString(ASCII))); } @Test public void testMarkReset() throws Exception { assertEquals('a', tee.read()); tee.mark(1); assertEquals('b', tee.read()); tee.reset(); assertEquals('b', tee.read()); assertEquals('c', tee.read()); assertEquals(-1, tee.read()); assertEquals("abbc", new String(output.toString(ASCII))); } /** * Tests that the main {@code InputStream} is closed when closing the branch {@code OutputStream} throws an * exception on {@link TeeInputStream#close()}, if specified to do so. */ @Test public void testCloseBranchIOException() throws Exception { final ByteArrayInputStream goodIs = mock(ByteArrayInputStream.class); final OutputStream badOs = new ThrowOnCloseOutputStream(); final TeeInputStream nonClosingTis = new TeeInputStream(goodIs, badOs, false); nonClosingTis.close(); verify(goodIs).close(); final TeeInputStream closingTis = new TeeInputStream(goodIs, badOs, true); try { closingTis.close(); fail("Expected " + IOException.class.getName()); } catch (final IOException e) { verify(goodIs, times(2)).close(); } } /** * Tests that the branch {@code OutputStream} is closed when closing the main {@code InputStream} throws an * exception on {@link TeeInputStream#close()}, if specified to do so. */ @Test public void testCloseMainIOException() throws IOException { final InputStream badIs = new ThrowOnCloseInputStream(); final ByteArrayOutputStream goodOs = mock(ByteArrayOutputStream.class); final TeeInputStream nonClosingTis = new TeeInputStream(badIs, goodOs, false); try { nonClosingTis.close(); fail("Expected " + IOException.class.getName()); } catch (final IOException e) { verify(goodOs, never()).close(); } final TeeInputStream closingTis = new TeeInputStream(badIs, goodOs, true); try { closingTis.close(); fail("Expected " + IOException.class.getName()); } catch (final IOException e) { verify(goodOs).close(); } } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/TeeReaderTest.java0100644 0000000 0000000 00000013637 13612062727 030302 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import java.io.StringWriter; import java.io.Writer; import java.nio.CharBuffer; import org.apache.commons.io.output.StringBuilderWriter; import org.apache.commons.io.test.ThrowOnCloseReader; import org.apache.commons.io.test.ThrowOnCloseWriter; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * JUnit Test Case for {@link TeeReader}. */ public class TeeReaderTest { private StringBuilderWriter output; private Reader tee; @BeforeEach public void setUp() { final Reader input = new CharSequenceReader("abc"); output = new StringBuilderWriter(); tee = new TeeReader(input, output); } /** * Tests that the main {@code Reader} is closed when closing the branch {@code Writer} throws an * exception on {@link TeeReader#close()}, if specified to do so. */ @Test public void testCloseBranchIOException() throws Exception { final StringReader goodR = mock(StringReader.class); final Writer badW = new ThrowOnCloseWriter(); final TeeReader nonClosingTr = new TeeReader(goodR, badW, false); nonClosingTr.close(); verify(goodR).close(); final TeeReader closingTr = new TeeReader(goodR, badW, true); try { closingTr.close(); fail("Expected " + IOException.class.getName()); } catch (final IOException e) { verify(goodR, times(2)).close(); } } /** * Tests that the branch {@code Writer} is closed when closing the main {@code Reader} throws an * exception on {@link TeeReader#close()}, if specified to do so. */ @Test public void testCloseMainIOException() throws IOException { final Reader badR = new ThrowOnCloseReader(); final StringWriter goodW = mock(StringWriter.class); final TeeReader nonClosingTr = new TeeReader(badR, goodW, false); try { nonClosingTr.close(); fail("Expected " + IOException.class.getName()); } catch (final IOException e) { verify(goodW, never()).close(); } final TeeReader closingTr = new TeeReader(badR, goodW, true); try { closingTr.close(); fail("Expected " + IOException.class.getName()); } catch (final IOException e) { //Assert.assertTrue(goodW.closed); verify(goodW).close(); } } @Test public void testMarkReset() throws Exception { assertEquals('a', tee.read()); tee.mark(1); assertEquals('b', tee.read()); tee.reset(); assertEquals('b', tee.read()); assertEquals('c', tee.read()); assertEquals(-1, tee.read()); assertEquals("abbc", output.toString()); } @Test public void testReadEverything() throws Exception { assertEquals('a', tee.read()); assertEquals('b', tee.read()); assertEquals('c', tee.read()); assertEquals(-1, tee.read()); assertEquals("abc", output.toString()); } @Test public void testReadNothing() { assertEquals("", output.toString()); } @Test public void testReadOneChar() throws Exception { assertEquals('a', tee.read()); assertEquals("a", output.toString()); } @Test public void testReadToArray() throws Exception { final char[] buffer = new char[8]; assertEquals(3, tee.read(buffer)); assertEquals('a', buffer[0]); assertEquals('b', buffer[1]); assertEquals('c', buffer[2]); assertEquals(-1, tee.read(buffer)); assertEquals("abc", output.toString()); } @Test public void testReadToArrayWithOffset() throws Exception { final char[] buffer = new char[8]; assertEquals(3, tee.read(buffer, 4, 4)); assertEquals('a', buffer[4]); assertEquals('b', buffer[5]); assertEquals('c', buffer[6]); assertEquals(-1, tee.read(buffer, 4, 4)); assertEquals("abc", output.toString()); } @Test public void testReadToCharBuffer() throws Exception { final CharBuffer buffer = CharBuffer.allocate(8); buffer.position(1); assertEquals(3, tee.read(buffer)); assertEquals(4, buffer.position()); buffer.flip(); buffer.position(1); assertEquals('a', buffer.charAt(0)); assertEquals('b', buffer.charAt(1)); assertEquals('c', buffer.charAt(2)); assertEquals(-1, tee.read(buffer)); assertEquals("abc", output.toString()); } @Test public void testSkip() throws Exception { assertEquals('a', tee.read()); assertEquals(1, tee.skip(1)); assertEquals('c', tee.read()); assertEquals(-1, tee.read()); assertEquals("ac", output.toString()); } }commons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/TimestampedObserverTest.java0100644 0000000 0000000 00000006426 13612062727 032424 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.ByteArrayInputStream; import java.io.IOException; import java.time.Instant; import org.apache.commons.io.IOUtils; import org.junit.jupiter.api.Test; /** * Tests {@link TimestampedObserver}. */ public class TimestampedObserverTest { @Test public void test() throws IOException, InterruptedException { final Instant before = Instant.now(); Thread.sleep(20); // Some OS' clock granularity may be high. final TimestampedObserver timestampedObserver = new TimestampedObserver(); // toString() should not blow up before close(). assertNotNull(timestampedObserver.toString()); assertTrue(timestampedObserver.getOpenInstant().isAfter(before)); assertTrue(timestampedObserver.getOpenToNowDuration().toNanos() > 0); assertNull(timestampedObserver.getCloseInstant()); final byte[] buffer = MessageDigestCalculatingInputStreamTest .generateRandomByteStream(IOUtils.DEFAULT_BUFFER_SIZE); try (final ObservableInputStream ois = new ObservableInputStream(new ByteArrayInputStream(buffer), timestampedObserver)) { assertTrue(timestampedObserver.getOpenInstant().isAfter(before)); assertTrue(timestampedObserver.getOpenToNowDuration().toNanos() > 0); } assertTrue(timestampedObserver.getOpenInstant().isAfter(before)); assertTrue(timestampedObserver.getOpenToNowDuration().toNanos() > 0); assertTrue(timestampedObserver.getCloseInstant().isAfter(timestampedObserver.getOpenInstant())); assertTrue(timestampedObserver.getOpenToCloseDuration().toNanos() > 0); assertNotNull(timestampedObserver.toString()); } @Test public void testExample() throws IOException { final TimestampedObserver timestampedObserver = new TimestampedObserver(); final byte[] buffer = MessageDigestCalculatingInputStreamTest .generateRandomByteStream(IOUtils.DEFAULT_BUFFER_SIZE); try (final ObservableInputStream ois = new ObservableInputStream(new ByteArrayInputStream(buffer), timestampedObserver)) { // } // System.out.printf("IO duration: %s%n", timestampedObserver); // System.out.printf("IO duration: %s%n", timestampedObserver.getOpenToCloseDuration()); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/UnixLineEndingInputStreamTest.java0100644 0000000 0000000 00000005334 13612062727 033511 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.junit.jupiter.api.Assertions.assertEquals; import java.io.ByteArrayInputStream; import java.io.IOException; import java.nio.charset.StandardCharsets; import org.junit.jupiter.api.Test; public class UnixLineEndingInputStreamTest { @Test public void simpleString() throws Exception { assertEquals( "abc\n", roundtrip( "abc" ) ); } @Test public void inTheMiddleOfTheLine() throws Exception { assertEquals( "a\nbc\n", roundtrip( "a\r\nbc" ) ); } @Test public void multipleBlankLines() throws Exception { assertEquals( "a\n\nbc\n", roundtrip( "a\r\n\r\nbc" ) ); } @Test public void twoLinesAtEnd() throws Exception { assertEquals( "a\n\n", roundtrip( "a\r\n\r\n" ) ); } @Test public void crOnlyEnsureAtEof() throws Exception { assertEquals( "a\nb\n", roundtrip( "a\rb" ) ); } @Test public void crOnlyNotAtEof() throws Exception { assertEquals( "a\nb", roundtrip( "a\rb", false ) ); } @Test public void crAtEnd() throws Exception { assertEquals( "a\n", roundtrip( "a\r" ) ); } @Test public void retainLineFeed() throws Exception { assertEquals( "a\n\n", roundtrip( "a\r\n\r\n", false ) ); assertEquals( "a", roundtrip( "a", false ) ); } private String roundtrip( final String msg ) throws IOException { return roundtrip( msg, true ); } private String roundtrip( final String msg, final boolean ensure ) throws IOException { final ByteArrayInputStream baos = new ByteArrayInputStream( msg.getBytes(StandardCharsets.UTF_8) ); final UnixLineEndingInputStream lf = new UnixLineEndingInputStream( baos, ensure ); final byte[] buf = new byte[100]; final int read = lf.read( buf ); lf.close(); return new String( buf, 0, read, StandardCharsets.UTF_8); } }././@LongLink0100644 0000000 0000000 00000000154 13612062727 011641 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/UnsynchronizedByteArrayInputStreamTest.javacommons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/UnsynchronizedByteArrayInputStreamTe0100644 0000000 0000000 00000034440 13612062727 034207 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.apache.commons.io.input.UnsynchronizedByteArrayInputStream.END_OF_STREAM; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; import org.apache.commons.io.IOUtils; import org.junit.jupiter.api.Test; /** * Basic unit tests for the alternative ByteArrayInputStream implementation. */ public class UnsynchronizedByteArrayInputStreamTest { @Test public void testConstructor1() throws IOException { final byte[] empty = IOUtils.EMPTY_BYTE_ARRAY; final byte[] one = new byte[1]; final byte[] some = new byte[25]; UnsynchronizedByteArrayInputStream is = new UnsynchronizedByteArrayInputStream(empty); assertEquals(empty.length, is.available()); is.close(); is = new UnsynchronizedByteArrayInputStream(one); assertEquals(one.length, is.available()); is.close(); is = new UnsynchronizedByteArrayInputStream(some); assertEquals(some.length, is.available()); is.close(); } @Test @SuppressWarnings("resource") // not necessary to close these resources public void testConstructor2() { final byte[] empty = IOUtils.EMPTY_BYTE_ARRAY; final byte[] one = new byte[1]; final byte[] some = new byte[25]; UnsynchronizedByteArrayInputStream is = new UnsynchronizedByteArrayInputStream(empty, 0); assertEquals(empty.length, is.available()); is = new UnsynchronizedByteArrayInputStream(empty, 1); assertEquals(0, is.available()); is = new UnsynchronizedByteArrayInputStream(one, 0); assertEquals(one.length, is.available()); is = new UnsynchronizedByteArrayInputStream(one, 1); assertEquals(0, is.available()); is = new UnsynchronizedByteArrayInputStream(one, 2); assertEquals(0, is.available()); is = new UnsynchronizedByteArrayInputStream(some, 0); assertEquals(some.length, is.available()); is = new UnsynchronizedByteArrayInputStream(some, 1); assertEquals(some.length - 1, is.available()); is = new UnsynchronizedByteArrayInputStream(some, 10); assertEquals(some.length - 10, is.available()); is = new UnsynchronizedByteArrayInputStream(some, some.length); assertEquals(0, is.available()); } @Test @SuppressWarnings("resource") // not necessary to close these resources public void testConstructor3() { final byte[] empty = IOUtils.EMPTY_BYTE_ARRAY; final byte[] one = new byte[1]; final byte[] some = new byte[25]; UnsynchronizedByteArrayInputStream is = new UnsynchronizedByteArrayInputStream(empty, 0); assertEquals(empty.length, is.available()); is = new UnsynchronizedByteArrayInputStream(empty, 1); assertEquals(0, is.available()); is = new UnsynchronizedByteArrayInputStream(empty, 0,1); assertEquals(0, is.available()); is = new UnsynchronizedByteArrayInputStream(empty, 1,1); assertEquals(0, is.available()); is = new UnsynchronizedByteArrayInputStream(one, 0); assertEquals(one.length, is.available()); is = new UnsynchronizedByteArrayInputStream(one, 1); assertEquals(one.length - 1, is.available()); is = new UnsynchronizedByteArrayInputStream(one, 2); assertEquals(0, is.available()); is = new UnsynchronizedByteArrayInputStream(one, 0, 1); assertEquals(1, is.available()); is = new UnsynchronizedByteArrayInputStream(one, 1, 1); assertEquals(0, is.available()); is = new UnsynchronizedByteArrayInputStream(one, 0, 2); assertEquals(1, is.available()); is = new UnsynchronizedByteArrayInputStream(one, 2, 1); assertEquals(0, is.available()); is = new UnsynchronizedByteArrayInputStream(one, 2, 2); assertEquals(0, is.available()); is = new UnsynchronizedByteArrayInputStream(some, 0); assertEquals(some.length, is.available()); is = new UnsynchronizedByteArrayInputStream(some, 1); assertEquals(some.length - 1, is.available()); is = new UnsynchronizedByteArrayInputStream(some, 10); assertEquals(some.length - 10, is.available()); is = new UnsynchronizedByteArrayInputStream(some, some.length); assertEquals(0, is.available()); is = new UnsynchronizedByteArrayInputStream(some, some.length, some.length); assertEquals(0, is.available()); is = new UnsynchronizedByteArrayInputStream(some, some.length - 1, some.length); assertEquals(1, is.available()); is = new UnsynchronizedByteArrayInputStream(some, 0, 7); assertEquals(7, is.available()); is = new UnsynchronizedByteArrayInputStream(some, 7, 7); assertEquals(7, is.available()); is = new UnsynchronizedByteArrayInputStream(some, 0, some.length * 2); assertEquals(some.length, is.available()); is = new UnsynchronizedByteArrayInputStream(some, some.length - 1, 7); assertEquals(1, is.available()); } @Test public void testInvalidConstructor2OffsetUnder() { assertThrows(IllegalArgumentException.class, () -> { new UnsynchronizedByteArrayInputStream(IOUtils.EMPTY_BYTE_ARRAY, -1); }); } @Test public void testInvalidConstructor3LengthUnder() { assertThrows(IllegalArgumentException.class, () -> { new UnsynchronizedByteArrayInputStream(IOUtils.EMPTY_BYTE_ARRAY, 0, -1); }); } @Test public void testInvalidConstructor3OffsetUnder() { assertThrows(IllegalArgumentException.class, () -> { new UnsynchronizedByteArrayInputStream(IOUtils.EMPTY_BYTE_ARRAY, -1, 1); }); } @Test @SuppressWarnings("resource") // not necessary to close these resources public void testInvalidReadArrayExplicitLenUnder() { final byte[] buf = IOUtils.EMPTY_BYTE_ARRAY; final UnsynchronizedByteArrayInputStream is = new UnsynchronizedByteArrayInputStream(new byte[] {(byte)0xa, (byte)0xb, (byte)0xc}); assertThrows(IndexOutOfBoundsException.class, () -> { is.read(buf, 0, -1); }); } @Test public void testInvalidReadArrayExplicitOffsetUnder() { final byte[] buf = IOUtils.EMPTY_BYTE_ARRAY; @SuppressWarnings("resource") // not necessary to close these resources final UnsynchronizedByteArrayInputStream is = new UnsynchronizedByteArrayInputStream(new byte[] {(byte)0xa, (byte)0xb, (byte)0xc}); assertThrows(IndexOutOfBoundsException.class, () -> { is.read(buf, -1, 1); }); } @Test public void testInvalidReadArrayExplicitRangeOver() { final byte[] buf = IOUtils.EMPTY_BYTE_ARRAY; @SuppressWarnings("resource") // not necessary to close these resources final UnsynchronizedByteArrayInputStream is = new UnsynchronizedByteArrayInputStream(new byte[] {(byte)0xa, (byte)0xb, (byte)0xc}); assertThrows(IndexOutOfBoundsException.class, () -> { is.read(buf, 0, 1); }); } @Test public void testInvalidReadArrayNull() { final byte[] buf = null; @SuppressWarnings("resource") // not necessary to close these resources final UnsynchronizedByteArrayInputStream is = new UnsynchronizedByteArrayInputStream(new byte[] {(byte)0xa, (byte)0xb, (byte)0xc}); assertThrows(NullPointerException.class, () -> { is.read(buf); }); } @Test public void testInvalidSkipNUnder() { @SuppressWarnings("resource") // not necessary to close these resources final UnsynchronizedByteArrayInputStream is = new UnsynchronizedByteArrayInputStream(new byte[] {(byte)0xa, (byte)0xb, (byte)0xc}); assertThrows(IllegalArgumentException.class, () -> { is.skip(-1); }); } @Test public void testMarkReset() { @SuppressWarnings("resource") // not necessary to close these resources final UnsynchronizedByteArrayInputStream is = new UnsynchronizedByteArrayInputStream(new byte[] {(byte)0xa, (byte)0xb, (byte)0xc}); assertTrue(is.markSupported()); assertEquals(0xa, is.read()); assertTrue(is.markSupported()); is.mark(10); assertEquals(0xb, is.read()); assertEquals(0xc, is.read()); is.reset(); assertEquals(0xb, is.read()); assertEquals(0xc, is.read()); assertEquals(END_OF_STREAM, is.read()); is.reset(); assertEquals(0xb, is.read()); assertEquals(0xc, is.read()); assertEquals(END_OF_STREAM, is.read()); } @Test public void testReadArray() { byte[] buf = new byte[10]; @SuppressWarnings("resource") // not necessary to close these resources UnsynchronizedByteArrayInputStream is = new UnsynchronizedByteArrayInputStream(IOUtils.EMPTY_BYTE_ARRAY); int read = is.read(buf); assertEquals(END_OF_STREAM, read); assertArrayEquals(new byte[10], buf); buf = IOUtils.EMPTY_BYTE_ARRAY; is = new UnsynchronizedByteArrayInputStream(new byte[]{(byte) 0xa, (byte) 0xb, (byte) 0xc}); read = is.read(buf); assertEquals(0, read); buf = new byte[10]; is = new UnsynchronizedByteArrayInputStream(new byte[]{(byte) 0xa, (byte) 0xb, (byte) 0xc}); read = is.read(buf); assertEquals(3, read); assertEquals(0xa, buf[0]); assertEquals(0xb, buf[1]); assertEquals(0xc, buf[2]); assertEquals(0, buf[3]); buf = new byte[2]; is = new UnsynchronizedByteArrayInputStream(new byte[]{(byte) 0xa, (byte) 0xb, (byte) 0xc}); read = is.read(buf); assertEquals(2, read); assertEquals(0xa, buf[0]); assertEquals(0xb, buf[1]); read = is.read(buf); assertEquals(1, read); assertEquals(0xc, buf[0]); } @Test public void testReadArrayExplicit() { byte[] buf = new byte[10]; @SuppressWarnings("resource") // not necessary to close these resources UnsynchronizedByteArrayInputStream is = new UnsynchronizedByteArrayInputStream(IOUtils.EMPTY_BYTE_ARRAY); int read = is.read(buf, 0, 10); assertEquals(END_OF_STREAM, read); assertArrayEquals(new byte[10], buf); buf = new byte[10]; is = new UnsynchronizedByteArrayInputStream(IOUtils.EMPTY_BYTE_ARRAY); read = is.read(buf, 4, 2); assertEquals(END_OF_STREAM, read); assertArrayEquals(new byte[10], buf); buf = new byte[10]; is = new UnsynchronizedByteArrayInputStream(IOUtils.EMPTY_BYTE_ARRAY); read = is.read(buf, 4, 6); assertEquals(END_OF_STREAM, read); assertArrayEquals(new byte[10], buf); buf = IOUtils.EMPTY_BYTE_ARRAY; is = new UnsynchronizedByteArrayInputStream(new byte[]{(byte) 0xa, (byte) 0xb, (byte) 0xc}); read = is.read(buf, 0,0); assertEquals(0, read); buf = new byte[10]; is = new UnsynchronizedByteArrayInputStream(new byte[]{(byte) 0xa, (byte) 0xb, (byte) 0xc}); read = is.read(buf, 0, 2); assertEquals(2, read); assertEquals(0xa, buf[0]); assertEquals(0xb, buf[1]); assertEquals(0, buf[2]); read = is.read(buf, 0, 10); assertEquals(1, read); assertEquals(0xc, buf[0]); } @Test public void testReadSingle() { @SuppressWarnings("resource") // not necessary to close these resources UnsynchronizedByteArrayInputStream is = new UnsynchronizedByteArrayInputStream(IOUtils.EMPTY_BYTE_ARRAY); assertEquals(END_OF_STREAM, is.read()); is = new UnsynchronizedByteArrayInputStream(new byte[] {(byte)0xa, (byte)0xb, (byte)0xc}); assertEquals(0xa, is.read()); assertEquals(0xb, is.read()); assertEquals(0xc, is.read()); assertEquals(END_OF_STREAM, is.read()); } @Test public void testSkip() { @SuppressWarnings("resource") // not necessary to close these resources UnsynchronizedByteArrayInputStream is = new UnsynchronizedByteArrayInputStream(new byte[] {(byte)0xa, (byte)0xb, (byte)0xc}); assertEquals(3, is.available()); is.skip(1); assertEquals(2, is.available()); assertEquals(0xb, is.read()); is.skip(1); assertEquals(0, is.available()); assertEquals(END_OF_STREAM, is.read()); is = new UnsynchronizedByteArrayInputStream(new byte[] {(byte)0xa, (byte)0xb, (byte)0xc}); assertEquals(3, is.available()); is.skip(0); assertEquals(3, is.available()); assertEquals(0xa, is.read()); is = new UnsynchronizedByteArrayInputStream(new byte[] {(byte)0xa, (byte)0xb, (byte)0xc}); assertEquals(3, is.available()); is.skip(2); assertEquals(1, is.available()); assertEquals(0xc, is.read()); assertEquals(END_OF_STREAM, is.read()); is = new UnsynchronizedByteArrayInputStream(new byte[] {(byte)0xa, (byte)0xb, (byte)0xc}); assertEquals(3, is.available()); is.skip(3); assertEquals(0, is.available()); assertEquals(END_OF_STREAM, is.read()); is = new UnsynchronizedByteArrayInputStream(new byte[] {(byte)0xa, (byte)0xb, (byte)0xc}); assertEquals(3, is.available()); is.skip(999); assertEquals(0, is.available()); assertEquals(END_OF_STREAM, is.read()); } } ././@LongLink0100644 0000000 0000000 00000000146 13612062727 011642 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/WindowsLineEndingInputStreamTest.javacommons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/WindowsLineEndingInputStreamTest.jav0100644 0000000 0000000 00000005235 13612062727 034057 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.junit.jupiter.api.Assertions.assertEquals; import java.io.ByteArrayInputStream; import java.io.IOException; import java.nio.charset.StandardCharsets; import org.junit.jupiter.api.Test; public class WindowsLineEndingInputStreamTest { @Test public void simpleString() throws Exception { assertEquals( "abc\r\n", roundtrip( "abc" ) ); } @Test public void inTheMiddleOfTheLine() throws Exception { assertEquals( "a\r\nbc\r\n", roundtrip( "a\r\nbc" ) ); } @Test public void multipleBlankLines() throws Exception { assertEquals( "a\r\n\r\nbc\r\n", roundtrip( "a\r\n\r\nbc" ) ); } @Test public void twoLinesAtEnd() throws Exception { assertEquals( "a\r\n\r\n", roundtrip( "a\r\n\r\n" ) ); } @Test public void linuxLinefeeds() throws Exception { final String roundtrip = roundtrip( "ab\nc", false ); assertEquals( "ab\r\nc", roundtrip ); } @Test public void malformed() throws Exception { assertEquals( "a\rbc", roundtrip( "a\rbc", false ) ); } @Test public void retainLineFeed() throws Exception { assertEquals( "a\r\n\r\n", roundtrip( "a\r\n\r\n", false ) ); assertEquals( "a", roundtrip( "a", false ) ); } private String roundtrip( final String msg ) throws IOException { return roundtrip( msg, true ); } private String roundtrip( final String msg, final boolean ensure ) throws IOException { final ByteArrayInputStream baos = new ByteArrayInputStream( msg.getBytes(StandardCharsets.UTF_8) ); final WindowsLineEndingInputStream lf = new WindowsLineEndingInputStream( baos, ensure ); final byte[] buf = new byte[100]; final int read = lf.read( buf ); lf.close(); return new String( buf, 0, read, StandardCharsets.UTF_8); } }commons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/XmlStreamReaderTest.java0100644 0000000 0000000 00000057466 13612062727 031511 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStreamWriter; import java.io.Writer; import java.net.URL; import java.net.URLConnection; import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.text.MessageFormat; import java.util.HashMap; import java.util.Map; import org.apache.commons.io.IOUtils; import org.junit.jupiter.api.Test; import org.junitpioneer.jupiter.DefaultLocale; public class XmlStreamReaderTest { private static final String XML5 = "xml-prolog-encoding-spaced-single-quotes"; private static final String XML4 = "xml-prolog-encoding-single-quotes"; private static final String XML3 = "xml-prolog-encoding-double-quotes"; private static final String XML2 = "xml-prolog"; private static final String XML1 = "xml"; protected void testRawNoBomValid(final String encoding) throws Exception { InputStream is = getXmlInputStream("no-bom", XML1, encoding, encoding); XmlStreamReader xmlReader = new XmlStreamReader(is, false); assertEquals(xmlReader.getEncoding(), "UTF-8"); xmlReader.close(); is = getXmlInputStream("no-bom", XML2, encoding, encoding); xmlReader = new XmlStreamReader(is); assertEquals(xmlReader.getEncoding(), "UTF-8"); xmlReader.close(); is = getXmlInputStream("no-bom", XML3, encoding, encoding); xmlReader = new XmlStreamReader(is); assertEquals(xmlReader.getEncoding(), encoding); xmlReader.close(); is = getXmlInputStream("no-bom", XML4, encoding, encoding); xmlReader = new XmlStreamReader(is); assertEquals(xmlReader.getEncoding(), encoding); xmlReader.close(); is = getXmlInputStream("no-bom", XML5, encoding, encoding); xmlReader = new XmlStreamReader(is); assertEquals(xmlReader.getEncoding(), encoding); xmlReader.close(); } protected void testRawNoBomInvalid(final String encoding) throws Exception { final InputStream is = getXmlInputStream("no-bom", XML3, encoding, encoding); try { new XmlStreamReader(is, false).close(); fail("It should have failed"); } catch (final IOException ex) { assertTrue(ex.getMessage().contains("Invalid encoding,")); } } @Test protected void testNullFileInput() { assertThrows(NullPointerException.class, () -> new XmlStreamReader((File) null)); } @Test protected void testNullPathInput() { assertThrows(NullPointerException.class, () -> new XmlStreamReader((Path) null)); } @Test protected void testNullInputStreamInput() { assertThrows(NullPointerException.class, () -> new XmlStreamReader((InputStream) null)); } @Test protected void testNullURLInput() { assertThrows(NullPointerException.class, () -> new XmlStreamReader((URL) null)); } @Test protected void testNullURLConnectionInput() { assertThrows(NullPointerException.class, () -> new XmlStreamReader((URLConnection) null, "US-ASCII")); } @Test public void testRawNoBomUsAscii() throws Exception { testRawNoBomValid("US-ASCII"); } @Test public void testRawNoBomUtf8() throws Exception { testRawNoBomValid("UTF-8"); } @Test public void testRawNoBomUtf16BE() throws Exception { testRawNoBomValid("UTF-16BE"); } @Test public void testRawNoBomUtf16LE() throws Exception { testRawNoBomValid("UTF-16LE"); } @Test public void testRawNoBomUtf32BE() throws Exception { testRawNoBomValid("UTF-32BE"); } @Test public void testRawNoBomUtf32LE() throws Exception { testRawNoBomValid("UTF-32LE"); } @Test public void testRawNoBomIso8859_1() throws Exception { testRawNoBomValid("ISO-8859-1"); } @Test public void testRawNoBomCp1047() throws Exception { testRawNoBomValid("CP1047"); } protected void testRawBomValid(final String encoding) throws Exception { final InputStream is = getXmlInputStream(encoding + "-bom", XML3, encoding, encoding); final XmlStreamReader xmlReader = new XmlStreamReader(is, false); if (!encoding.equals("UTF-16") && !encoding.equals("UTF-32")) { assertEquals(xmlReader.getEncoding(), encoding); } else { assertEquals(xmlReader.getEncoding().substring(0, encoding.length()), encoding); } xmlReader.close(); } protected void testRawBomInvalid(final String bomEnc, final String streamEnc, final String prologEnc) throws Exception { final InputStream is = getXmlInputStream(bomEnc, XML3, streamEnc, prologEnc); XmlStreamReader xmlReader = null; try { xmlReader = new XmlStreamReader(is, false); final String foundEnc = xmlReader.getEncoding(); fail("Expected IOException for BOM " + bomEnc + ", streamEnc " + streamEnc + " and prologEnc " + prologEnc + ": found " + foundEnc); } catch (final IOException ex) { assertTrue(ex.getMessage().contains("Invalid encoding,")); } if (xmlReader != null) { xmlReader.close(); } } @Test public void testRawBomUtf8() throws Exception { testRawBomValid("UTF-8"); testRawBomInvalid("UTF-8-bom", "US-ASCII", "US-ASCII"); testRawBomInvalid("UTF-8-bom", "ISO-8859-1", "ISO-8859-1"); testRawBomInvalid("UTF-8-bom", "UTF-8", "UTF-16"); testRawBomInvalid("UTF-8-bom", "UTF-8", "UTF-16BE"); testRawBomInvalid("UTF-8-bom", "UTF-8", "UTF-16LE"); testRawBomInvalid("UTF-16BE-bom", "UTF-16BE", "UTF-16LE"); testRawBomInvalid("UTF-16LE-bom", "UTF-16LE", "UTF-16BE"); testRawBomInvalid("UTF-16LE-bom", "UTF-16LE", "UTF-8"); testRawBomInvalid("UTF-32BE-bom", "UTF-32BE", "UTF-32LE"); testRawBomInvalid("UTF-32LE-bom", "UTF-32LE", "UTF-32BE"); testRawBomInvalid("UTF-32LE-bom", "UTF-32LE", "UTF-8"); } @Test public void testRawBomUtf16() throws Exception { testRawBomValid("UTF-16BE"); testRawBomValid("UTF-16LE"); testRawBomValid("UTF-16"); testRawBomInvalid("UTF-16BE-bom", "UTF-16BE", "UTF-16LE"); testRawBomInvalid("UTF-16LE-bom", "UTF-16LE", "UTF-16BE"); testRawBomInvalid("UTF-16LE-bom", "UTF-16LE", "UTF-8"); } @Test public void testRawBomUtf32() throws Exception { testRawBomValid("UTF-32BE"); testRawBomValid("UTF-32LE"); testRawBomValid("UTF-32"); testRawBomInvalid("UTF-32BE-bom", "UTF-32BE", "UTF-32LE"); testRawBomInvalid("UTF-32LE-bom", "UTF-32LE", "UTF-32BE"); testRawBomInvalid("UTF-32LE-bom", "UTF-32LE", "UTF-8"); } @Test public void testHttp() throws Exception { // niallp 2010-10-06 - remove following 2 tests - I reinstated // checks for non-UTF-16 encodings (18 tests) and these failed // _testHttpValid("application/xml", "no-bom", "US-ASCII", null); // _testHttpValid("application/xml", "UTF-8-bom", "US-ASCII", null); testHttpValid("application/xml", "UTF-8-bom", "UTF-8", null); testHttpValid("application/xml", "UTF-8-bom", "UTF-8", "UTF-8"); testHttpValid("application/xml;charset=UTF-8", "UTF-8-bom", "UTF-8", null); testHttpValid("application/xml;charset=\"UTF-8\"", "UTF-8-bom", "UTF-8", null); testHttpValid("application/xml;charset='UTF-8'", "UTF-8-bom", "UTF-8", null); testHttpValid("application/xml;charset=UTF-8", "UTF-8-bom", "UTF-8", "UTF-8"); testHttpValid("application/xml;charset=UTF-16", "UTF-16BE-bom", "UTF-16BE", null); testHttpValid("application/xml;charset=UTF-16", "UTF-16BE-bom", "UTF-16BE", "UTF-16"); testHttpValid("application/xml;charset=UTF-16", "UTF-16BE-bom", "UTF-16BE", "UTF-16BE"); testHttpInvalid("application/xml;charset=UTF-16BE", "UTF-16BE-bom", "UTF-16BE", null); testHttpInvalid("application/xml;charset=UTF-16BE", "UTF-16BE-bom", "UTF-16BE", "UTF-16"); testHttpInvalid("application/xml;charset=UTF-16BE", "UTF-16BE-bom", "UTF-16BE", "UTF-16BE"); testHttpInvalid("application/xml;charset=UTF-32BE", "UTF-32BE-bom", "UTF-32BE", null); testHttpInvalid("application/xml;charset=UTF-32BE", "UTF-32BE-bom", "UTF-32BE", "UTF-32"); testHttpInvalid("application/xml;charset=UTF-32BE", "UTF-32BE-bom", "UTF-32BE", "UTF-32BE"); testHttpInvalid("application/xml", "UTF-8-bom", "US-ASCII", "US-ASCII"); testHttpInvalid("application/xml;charset=UTF-16", "UTF-16LE", "UTF-8", "UTF-8"); testHttpInvalid("application/xml;charset=UTF-16", "no-bom", "UTF-16BE", "UTF-16BE"); testHttpInvalid("application/xml;charset=UTF-32", "UTF-32LE", "UTF-8", "UTF-8"); testHttpInvalid("application/xml;charset=UTF-32", "no-bom", "UTF-32BE", "UTF-32BE"); testHttpValid("text/xml", "no-bom", "US-ASCII", null); testHttpValid("text/xml;charset=UTF-8", "UTF-8-bom", "UTF-8", "UTF-8"); testHttpValid("text/xml;charset=UTF-8", "UTF-8-bom", "UTF-8", null); testHttpValid("text/xml;charset=UTF-16", "UTF-16BE-bom", "UTF-16BE", null); testHttpValid("text/xml;charset=UTF-16", "UTF-16BE-bom", "UTF-16BE", "UTF-16"); testHttpValid("text/xml;charset=UTF-16", "UTF-16BE-bom", "UTF-16BE", "UTF-16BE"); testHttpValid("text/xml;charset=UTF-32", "UTF-32BE-bom", "UTF-32BE", null); testHttpValid("text/xml;charset=UTF-32", "UTF-32BE-bom", "UTF-32BE", "UTF-32"); testHttpValid("text/xml;charset=UTF-32", "UTF-32BE-bom", "UTF-32BE", "UTF-32BE"); testHttpValid("text/xml", "UTF-8-bom", "US-ASCII", null); testAlternateDefaultEncoding("application/xml", "UTF-8-bom", "UTF-8", null, null); testAlternateDefaultEncoding("application/xml", "no-bom", "US-ASCII", null, "US-ASCII"); testAlternateDefaultEncoding("application/xml", "UTF-8-bom", "UTF-8", null, "UTF-8"); testAlternateDefaultEncoding("text/xml", "no-bom", "US-ASCII", null, null); testAlternateDefaultEncoding("text/xml", "no-bom", "US-ASCII", null, "US-ASCII"); testAlternateDefaultEncoding("text/xml", "no-bom", "US-ASCII", null, "UTF-8"); testHttpInvalid("text/xml;charset=UTF-16BE", "UTF-16BE-bom", "UTF-16BE", null); testHttpInvalid("text/xml;charset=UTF-16BE", "UTF-16BE-bom", "UTF-16BE", "UTF-16"); testHttpInvalid("text/xml;charset=UTF-16BE", "UTF-16BE-bom", "UTF-16BE", "UTF-16BE"); testHttpInvalid("text/xml;charset=UTF-16", "no-bom", "UTF-16BE", "UTF-16BE"); testHttpInvalid("text/xml;charset=UTF-16", "no-bom", "UTF-16BE", null); testHttpInvalid("text/xml;charset=UTF-32BE", "UTF-32BE-bom", "UTF-32BE", null); testHttpInvalid("text/xml;charset=UTF-32BE", "UTF-32BE-bom", "UTF-32BE", "UTF-32"); testHttpInvalid("text/xml;charset=UTF-32BE", "UTF-32BE-bom", "UTF-32BE", "UTF-32BE"); testHttpInvalid("text/xml;charset=UTF-32", "no-bom", "UTF-32BE", "UTF-32BE"); testHttpInvalid("text/xml;charset=UTF-32", "no-bom", "UTF-32BE", null); testHttpLenient("text/xml", "no-bom", "US-ASCII", null, "US-ASCII"); testHttpLenient("text/xml;charset=UTF-8", "UTF-8-bom", "UTF-8", "UTF-8", "UTF-8"); testHttpLenient("text/xml;charset=UTF-8", "UTF-8-bom", "UTF-8", null, "UTF-8"); testHttpLenient("text/xml;charset=UTF-16", "UTF-16BE-bom", "UTF-16BE", null, "UTF-16BE"); testHttpLenient("text/xml;charset=UTF-16", "UTF-16BE-bom", "UTF-16BE", "UTF-16", "UTF-16"); testHttpLenient("text/xml;charset=UTF-16", "UTF-16BE-bom", "UTF-16BE", "UTF-16BE", "UTF-16BE"); testHttpLenient("text/xml;charset=UTF-32", "UTF-32BE-bom", "UTF-32BE", null, "UTF-32BE"); testHttpLenient("text/xml;charset=UTF-32", "UTF-32BE-bom", "UTF-32BE", "UTF-32", "UTF-32"); testHttpLenient("text/xml;charset=UTF-32", "UTF-32BE-bom", "UTF-32BE", "UTF-32BE", "UTF-32BE"); testHttpLenient("text/xml", "UTF-8-bom", "US-ASCII", null, "US-ASCII"); testHttpLenient("text/xml;charset=UTF-16BE", "UTF-16BE-bom", "UTF-16BE", null, "UTF-16BE"); testHttpLenient("text/xml;charset=UTF-16BE", "UTF-16BE-bom", "UTF-16BE", "UTF-16", "UTF-16"); testHttpLenient("text/xml;charset=UTF-16BE", "UTF-16BE-bom", "UTF-16BE", "UTF-16BE", "UTF-16BE"); testHttpLenient("text/xml;charset=UTF-16", "no-bom", "UTF-16BE", "UTF-16BE", "UTF-16BE"); testHttpLenient("text/xml;charset=UTF-16", "no-bom", "UTF-16BE", null, "UTF-16"); testHttpLenient("text/xml;charset=UTF-32BE", "UTF-32BE-bom", "UTF-32BE", null, "UTF-32BE"); testHttpLenient("text/xml;charset=UTF-32BE", "UTF-32BE-bom", "UTF-32BE", "UTF-32", "UTF-32"); testHttpLenient("text/xml;charset=UTF-32BE", "UTF-32BE-bom", "UTF-32BE", "UTF-32BE", "UTF-32BE"); testHttpLenient("text/xml;charset=UTF-32", "no-bom", "UTF-32BE", "UTF-32BE", "UTF-32BE"); testHttpLenient("text/xml;charset=UTF-32", "no-bom", "UTF-32BE", null, "UTF-32"); testHttpLenient("text/html", "no-bom", "US-ASCII", "US-ASCII", "US-ASCII"); testHttpLenient("text/html", "no-bom", "US-ASCII", null, "US-ASCII"); testHttpLenient("text/html;charset=UTF-8", "no-bom", "US-ASCII", "UTF-8", "UTF-8"); testHttpLenient("text/html;charset=UTF-16BE", "no-bom", "US-ASCII", "UTF-8", "UTF-8"); testHttpLenient("text/html;charset=UTF-32BE", "no-bom", "US-ASCII", "UTF-8", "UTF-8"); } // Turkish language has specific rules to convert dotted and dottless i character. @Test @DefaultLocale(language = "tr") public void testLowerCaseEncodingWithTurkishLocale_IO_557() throws Exception { final String[] encodings = { "iso8859-1", "us-ascii", "utf-8" }; for (final String encoding : encodings) { final String xml = getXML("no-bom", XML3, encoding, encoding); try (final ByteArrayInputStream is = new ByteArrayInputStream(xml.getBytes(encoding)); final XmlStreamReader xmlReader = new XmlStreamReader(is)) { assertTrue(encoding.equalsIgnoreCase(xmlReader.getEncoding()), "Check encoding : " + encoding); assertEquals(xml, IOUtils.toString(xmlReader), "Check content"); } } } @Test public void testRawContent() throws Exception { final String encoding = "UTF-8"; final String xml = getXML("no-bom", XML3, encoding, encoding); final ByteArrayInputStream is = new ByteArrayInputStream(xml.getBytes(encoding)); final XmlStreamReader xmlReader = new XmlStreamReader(is); assertEquals(xmlReader.getEncoding(), encoding, "Check encoding"); assertEquals(xml, IOUtils.toString(xmlReader), "Check content"); } @Test public void testHttpContent() throws Exception { final String encoding = "UTF-8"; final String xml = getXML("no-bom", XML3, encoding, encoding); final ByteArrayInputStream is = new ByteArrayInputStream(xml.getBytes(encoding)); final XmlStreamReader xmlReader = new XmlStreamReader(is, encoding); assertEquals(xmlReader.getEncoding(), encoding, "Check encoding"); assertEquals(xml, IOUtils.toString(xmlReader), "Check content"); } public void testAlternateDefaultEncoding(final String cT, final String bomEnc, final String streamEnc, final String prologEnc, final String alternateEnc) throws Exception { final InputStream is = getXmlInputStream(bomEnc, prologEnc == null ? XML1 : XML3, streamEnc, prologEnc); final XmlStreamReader xmlReader = new XmlStreamReader(is, cT, false, alternateEnc); if (!streamEnc.equals("UTF-16")) { // we can not assert things here because UTF-8, US-ASCII and // ISO-8859-1 look alike for the chars used for detection // (niallp 2010-10-06 - I re-instated the check below - the tests(6) passed) final String enc = alternateEnc != null ? alternateEnc : streamEnc; assertEquals(xmlReader.getEncoding(), enc); } else { //String enc = (alternateEnc != null) ? alternateEnc : streamEnc; assertEquals(xmlReader.getEncoding().substring(0, streamEnc.length()), streamEnc); } xmlReader.close(); } public void testHttpValid(final String cT, final String bomEnc, final String streamEnc, final String prologEnc) throws Exception { final InputStream is = getXmlInputStream(bomEnc, prologEnc == null ? XML1 : XML3, streamEnc, prologEnc); final XmlStreamReader xmlReader = new XmlStreamReader(is, cT, false); if (!streamEnc.equals("UTF-16")) { // we can not assert things here because UTF-8, US-ASCII and // ISO-8859-1 look alike for the chars used for detection // (niallp 2010-10-06 - I re-instated the check below and removed the 2 tests that failed) assertEquals(xmlReader.getEncoding(), streamEnc); } else { assertEquals(xmlReader.getEncoding().substring(0, streamEnc.length()), streamEnc); } xmlReader.close(); } protected void testHttpInvalid(final String cT, final String bomEnc, final String streamEnc, final String prologEnc) throws Exception { final InputStream is = getXmlInputStream(bomEnc, prologEnc == null ? XML2 : XML3, streamEnc, prologEnc); try { (new XmlStreamReader(is, cT, false)).close(); fail("It should have failed for HTTP Content-type " + cT + ", BOM " + bomEnc + ", streamEnc " + streamEnc + " and prologEnc " + prologEnc); } catch (final IOException ex) { assertTrue(ex.getMessage().contains("Invalid encoding,")); } } protected void testHttpLenient(final String cT, final String bomEnc, final String streamEnc, final String prologEnc, final String shouldbe) throws Exception { final InputStream is = getXmlInputStream(bomEnc, prologEnc == null ? XML2 : XML3, streamEnc, prologEnc); final XmlStreamReader xmlReader = new XmlStreamReader(is, cT, true); assertEquals(xmlReader.getEncoding(), shouldbe); xmlReader.close(); } private static final String ENCODING_ATTRIBUTE_XML = " \n" + "\n" + "\n" + " \n" + " BOMs = new HashMap<>(); static { BOMs.put("no-bom", NO_BOM_BYTES); BOMs.put("UTF-16BE-bom", UTF_16BE_BOM_BYTES); BOMs.put("UTF-16LE-bom", UTF_16LE_BOM_BYTES); BOMs.put("UTF-32BE-bom", UTF_32BE_BOM_BYTES); BOMs.put("UTF-32LE-bom", UTF_32LE_BOM_BYTES); BOMs.put("UTF-16-bom", NO_BOM_BYTES); // it's added by the writer BOMs.put("UTF-8-bom", UTF_8_BOM_BYTES); } private static final MessageFormat XML = new MessageFormat( "{2}"); private static final MessageFormat XML_WITH_PROLOG = new MessageFormat( "\n{2}"); private static final MessageFormat XML_WITH_PROLOG_AND_ENCODING_DOUBLE_QUOTES = new MessageFormat( "\n{2}"); private static final MessageFormat XML_WITH_PROLOG_AND_ENCODING_SINGLE_QUOTES = new MessageFormat( "\n{2}"); private static final MessageFormat XML_WITH_PROLOG_AND_ENCODING_SPACED_SINGLE_QUOTES = new MessageFormat( "\n{2}"); private static final MessageFormat INFO = new MessageFormat( "\nBOM : {0}\nDoc : {1}\nStream Enc : {2}\nProlog Enc : {3}\n"); private static final Map XMLs = new HashMap<>(); static { XMLs.put(XML1, XML); XMLs.put(XML2, XML_WITH_PROLOG); XMLs.put(XML3, XML_WITH_PROLOG_AND_ENCODING_DOUBLE_QUOTES); XMLs.put(XML4, XML_WITH_PROLOG_AND_ENCODING_SINGLE_QUOTES); XMLs.put(XML5, XML_WITH_PROLOG_AND_ENCODING_SPACED_SINGLE_QUOTES); } /** * @param bomType no-bom, UTF-16BE-bom, UTF-16LE-bom, UTF-8-bom * @param xmlType xml, xml-prolog, xml-prolog-charset * @param streamEnc encoding of the stream * @param prologEnc encoding of the prolog * @return XML stream * @throws IOException If an I/O error occurs */ protected InputStream getXmlInputStream(final String bomType, final String xmlType, final String streamEnc, final String prologEnc) throws IOException { final ByteArrayOutputStream baos = new ByteArrayOutputStream(1024); int[] bom = BOMs.get(bomType); if (bom == null) { bom = new int[0]; } for (final int element : bom) { baos.write(element); } try (final Writer writer = new OutputStreamWriter(baos, streamEnc)) { final String xmlDoc = getXML(bomType, xmlType, streamEnc, prologEnc); writer.write(xmlDoc); // PADDING TO TEST THINGS WORK BEYOND PUSHBACK_SIZE writer.write("\n"); for (int i = 0; i < 10000; i++) { writer.write("\n"); } writer.write("\n"); } return new ByteArrayInputStream(baos.toByteArray()); } /** * Create the XML. */ private String getXML(final String bomType, final String xmlType, final String streamEnc, final String prologEnc) { final MessageFormat xml = XMLs.get(xmlType); final String info = INFO.format(new Object[]{bomType, xmlType, prologEnc}); return xml.format(new Object[]{streamEnc, prologEnc, info}); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/XmlStreamReaderUtilitiesTest.java0100644 0000000 0000000 00000046465 13612062727 033402 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import java.io.ByteArrayInputStream; import java.io.IOException; import org.junit.jupiter.api.Test; /** * Test the Encoding Utilities part of {@link XmlStreamReader}. */ public class XmlStreamReaderUtilitiesTest { private static final String RAWMGS1 = "encoding mismatch"; private static final String RAWMGS2 = "unknown BOM"; private static final String HTTPMGS1 = "BOM must be NULL"; private static final String HTTPMGS2 = "encoding mismatch"; private static final String HTTPMGS3 = "Invalid MIME"; private static final String APPXML = "application/xml"; private static final String APPXML_UTF8 = "application/xml;charset=UTF-8"; private static final String APPXML_UTF16 = "application/xml;charset=UTF-16"; private static final String APPXML_UTF32 = "application/xml;charset=UTF-32"; private static final String APPXML_UTF16BE = "application/xml;charset=UTF-16BE"; private static final String APPXML_UTF16LE = "application/xml;charset=UTF-16LE"; private static final String APPXML_UTF32BE = "application/xml;charset=UTF-32BE"; private static final String APPXML_UTF32LE = "application/xml;charset=UTF-32LE"; private static final String TXTXML = "text/xml"; @Test public void testContentTypeEncoding() { checkContentTypeEncoding(null, null); checkContentTypeEncoding(null, ""); checkContentTypeEncoding(null, "application/xml"); checkContentTypeEncoding(null, "application/xml;"); checkContentTypeEncoding(null, "multipart/mixed;boundary=frontier"); checkContentTypeEncoding(null, "multipart/mixed;boundary='frontier'"); checkContentTypeEncoding(null, "multipart/mixed;boundary=\"frontier\""); checkContentTypeEncoding("UTF-16", "application/xml;charset=utf-16"); checkContentTypeEncoding("UTF-16", "application/xml;charset=UTF-16"); checkContentTypeEncoding("UTF-16", "application/xml;charset='UTF-16'"); checkContentTypeEncoding("UTF-16", "application/xml;charset=\"UTF-16\""); checkContentTypeEncoding("UTF-32", "application/xml;charset=utf-32"); checkContentTypeEncoding("UTF-32", "application/xml;charset=UTF-32"); checkContentTypeEncoding("UTF-32", "application/xml;charset='UTF-32'"); checkContentTypeEncoding("UTF-32", "application/xml;charset=\"UTF-32\""); } private void checkContentTypeEncoding(final String expected, final String httpContentType) { assertEquals(expected, XmlStreamReader.getContentTypeEncoding(httpContentType), "ContentTypeEncoding=[" + httpContentType + "]"); } @Test public void testContentTypeMime() { checkContentTypeMime(null, null); checkContentTypeMime("", ""); checkContentTypeMime("application/xml", "application/xml"); checkContentTypeMime("application/xml", "application/xml;"); checkContentTypeMime("application/xml", "application/xml;charset=utf-16"); checkContentTypeMime("application/xml", "application/xml;charset=utf-32"); } private void checkContentTypeMime(final String expected, final String httpContentType) { assertEquals(expected, XmlStreamReader.getContentTypeMime(httpContentType), "ContentTypeMime=[" + httpContentType + "]"); } @Test public void testAppXml() { checkAppXml(false, null); checkAppXml(false, ""); checkAppXml(true, "application/xml"); checkAppXml(true, "application/xml-dtd"); checkAppXml(true, "application/xml-external-parsed-entity"); checkAppXml(true, "application/soap+xml"); checkAppXml(true, "application/atom+xml"); checkAppXml(false, "application/atomxml"); checkAppXml(false, "text/xml"); checkAppXml(false, "text/atom+xml"); checkAppXml(true, "application/xml-dtd"); checkAppXml(true, "application/xml-external-parsed-entity"); } @SuppressWarnings("boxing") private void checkAppXml(final boolean expected, final String mime) { assertEquals(expected, XmlStreamReader.isAppXml(mime), "Mime=[" + mime + "]"); } @Test public void testTextXml() { checkTextXml(false, null); checkTextXml(false, ""); checkTextXml(true, "text/xml"); checkTextXml(true, "text/xml-external-parsed-entity"); checkTextXml(true, "text/soap+xml"); checkTextXml(true, "text/atom+xml"); checkTextXml(false, "text/atomxml"); checkTextXml(false, "application/xml"); checkTextXml(false, "application/atom+xml"); } @SuppressWarnings("boxing") private void checkTextXml(final boolean expected, final String mime) { assertEquals(expected, XmlStreamReader.isTextXml(mime), "Mime=[" + mime + "]"); } @Test public void testCalculateRawEncodingNoBOM() throws IOException { // No BOM Expected BOM Guess XML Default checkRawError(RAWMGS2, "UTF-32", null, null, null); // checkRawEncoding("UTF-8", null, null, null, null); checkRawEncoding("UTF-8", null, "UTF-16BE", null, null); /* why default & not Guess? */ checkRawEncoding("UTF-8", null, null, "UTF-16BE", null); /* why default & not XMLEnc? */ checkRawEncoding("UTF-8", null, "UTF-8", "UTF-8", "UTF-16BE"); // checkRawEncoding("UTF-16BE", null, "UTF-16BE", "UTF-16BE", null); checkRawEncoding("UTF-16BE", null, null, null, "UTF-16BE"); checkRawEncoding("UTF-16BE", null, "UTF-8", null, "UTF-16BE"); /* why default & not Guess? */ checkRawEncoding("UTF-16BE", null, null, "UTF-8", "UTF-16BE"); /* why default & not Guess? */ checkRawEncoding("UTF-16BE", null, "UTF-16BE", "UTF-16", null); checkRawEncoding("UTF-16LE", null, "UTF-16LE", "UTF-16", null); } @Test public void testCalculateRawEncodingStandard() throws IOException { // Standard BOM Checks BOM Other Default testCalculateRawEncodingStandard("UTF-8", "UTF-16BE", "UTF-16LE"); testCalculateRawEncodingStandard("UTF-16BE", "UTF-8", "UTF-16LE"); testCalculateRawEncodingStandard("UTF-16LE", "UTF-8", "UTF-16BE"); } @Test public void testCalculateRawEncodingStandardUtf32() throws IOException { // Standard BOM Checks BOM Other Default testCalculateRawEncodingStandard("UTF-8", "UTF-32BE", "UTF-32LE"); testCalculateRawEncodingStandard("UTF-32BE", "UTF-8", "UTF-32LE"); testCalculateRawEncodingStandard("UTF-32LE", "UTF-8", "UTF-32BE"); } private void testCalculateRawEncodingStandard(final String bomEnc, final String otherEnc, final String defaultEnc) throws IOException { // Expected BOM Guess XMLEnc Default checkRawEncoding(bomEnc, bomEnc, null, null, defaultEnc); checkRawEncoding(bomEnc, bomEnc, bomEnc, null, defaultEnc); checkRawError(RAWMGS1, bomEnc, otherEnc, null, defaultEnc); checkRawEncoding(bomEnc, bomEnc, null, bomEnc, defaultEnc); checkRawError(RAWMGS1, bomEnc, null, otherEnc, defaultEnc); checkRawEncoding(bomEnc, bomEnc, bomEnc, bomEnc, defaultEnc); checkRawError(RAWMGS1, bomEnc, bomEnc, otherEnc, defaultEnc); checkRawError(RAWMGS1, bomEnc, otherEnc, bomEnc, defaultEnc); } @Test public void testCalculateRawEncodingAdditionalUTF16() throws IOException { // BOM Guess XML Default checkRawError(RAWMGS1, "UTF-16BE", "UTF-16", null, null); checkRawEncoding("UTF-16BE", "UTF-16BE", null, "UTF-16", null); checkRawEncoding("UTF-16BE", "UTF-16BE", "UTF-16BE", "UTF-16", null); checkRawError(RAWMGS1, "UTF-16BE", null, "UTF-16LE", null); checkRawError(RAWMGS1, "UTF-16BE", "UTF-16BE", "UTF-16LE", null); checkRawError(RAWMGS1, "UTF-16LE", "UTF-16", null, null); checkRawEncoding("UTF-16LE", "UTF-16LE", null, "UTF-16", null); checkRawEncoding("UTF-16LE", "UTF-16LE", "UTF-16LE", "UTF-16", null); checkRawError(RAWMGS1, "UTF-16LE", null, "UTF-16BE", null); checkRawError(RAWMGS1, "UTF-16LE", "UTF-16LE", "UTF-16BE", null); } @Test public void testCalculateRawEncodingAdditionalUTF32() throws IOException { // BOM Guess XML Default checkRawError(RAWMGS1, "UTF-32BE", "UTF-32", null, null); checkRawEncoding("UTF-32BE", "UTF-32BE", null, "UTF-32", null); checkRawEncoding("UTF-32BE", "UTF-32BE", "UTF-32BE", "UTF-32", null); checkRawError(RAWMGS1, "UTF-32BE", null, "UTF-32LE", null); checkRawError(RAWMGS1, "UTF-32BE", "UTF-32BE", "UTF-32LE", null); checkRawError(RAWMGS1, "UTF-32LE", "UTF-32", null, null); checkRawEncoding("UTF-32LE", "UTF-32LE", null, "UTF-32", null); checkRawEncoding("UTF-32LE", "UTF-32LE", "UTF-32LE", "UTF-32", null); checkRawError(RAWMGS1, "UTF-32LE", null, "UTF-32BE", null); checkRawError(RAWMGS1, "UTF-32LE", "UTF-32LE", "UTF-32BE", null); } private void checkRawEncoding(final String expected, final String bomEnc, final String xmlGuessEnc, final String xmlEnc, final String defaultEncoding) throws IOException { final StringBuilder builder = new StringBuilder(); builder.append("RawEncoding: ").append(bomEnc).append("], "); builder.append("bomEnc=[").append(bomEnc).append("], "); builder.append("xmlGuessEnc=[").append(xmlGuessEnc).append("], "); builder.append("xmlEnc=[").append(xmlEnc).append("], "); builder.append("defaultEncoding=[").append(defaultEncoding).append("],"); final String encoding = calculateRawEncoding(bomEnc,xmlGuessEnc,xmlEnc, defaultEncoding); assertEquals(expected, encoding, builder.toString()); } protected String calculateRawEncoding(final String bomEnc, final String xmlGuessEnc, final String xmlEnc, final String defaultEncoding) throws IOException { final MockXmlStreamReader mock = new MockXmlStreamReader(defaultEncoding); final String enc = mock.calculateRawEncoding(bomEnc, xmlGuessEnc, xmlEnc); mock.close(); return enc; } private void checkRawError(final String msgSuffix, final String bomEnc, final String xmlGuessEnc, final String xmlEnc, final String defaultEncoding) { try { checkRawEncoding("XmlStreamReaderException", bomEnc, xmlGuessEnc, xmlEnc, defaultEncoding); fail("Expected XmlStreamReaderException"); } catch (final XmlStreamReaderException e) { assertTrue(e.getMessage().startsWith("Invalid encoding"), "Msg Start: " + e.getMessage()); assertTrue(e.getMessage().endsWith(msgSuffix), "Msg End: " + e.getMessage()); assertEquals(bomEnc, e.getBomEncoding(), "bomEnc"); assertEquals(xmlGuessEnc, e.getXmlGuessEncoding(), "xmlGuessEnc"); assertEquals(xmlEnc, e.getXmlEncoding(), "xmlEnc"); assertNull(e.getContentTypeEncoding(), "ContentTypeEncoding"); assertNull(e.getContentTypeMime(), "ContentTypeMime"); } catch (final Exception e) { fail("Expected XmlStreamReaderException, but threw " + e); } } @Test public void testCalculateHttpEncoding() throws IOException { // No BOM Expected Lenient cType BOM Guess XML Default checkHttpError(HTTPMGS3, true, null, null, null, null, null); checkHttpError(HTTPMGS3, false, null, null, null, "UTF-8", null); checkHttpEncoding("UTF-8", true, null, null, null, "UTF-8", null); checkHttpEncoding("UTF-16LE", true, null, null, null, "UTF-16LE", null); checkHttpError(HTTPMGS3, false, "text/css", null, null, null, null); checkHttpEncoding("US-ASCII", false, TXTXML, null, null, null, null); checkHttpEncoding("UTF-16BE", false, TXTXML, null, null, null, "UTF-16BE"); checkHttpEncoding("UTF-8", false, APPXML, null, null, null, null); checkHttpEncoding("UTF-16BE", false, APPXML, null, null, null, "UTF-16BE"); checkHttpEncoding("UTF-8", false, APPXML, "UTF-8", null, null, "UTF-16BE"); checkHttpEncoding("UTF-16LE", false, APPXML_UTF16LE, null, null, null, null); checkHttpEncoding("UTF-16BE", false, APPXML_UTF16BE, null, null, null, null); checkHttpError(HTTPMGS1, false, APPXML_UTF16LE, "UTF-16LE", null, null, null); checkHttpError(HTTPMGS1, false, APPXML_UTF16BE, "UTF-16BE", null, null, null); checkHttpError(HTTPMGS2, false, APPXML_UTF16, null, null, null, null); checkHttpError(HTTPMGS2, false, APPXML_UTF16, "UTF-8", null, null, null); checkHttpEncoding("UTF-16LE", false, APPXML_UTF16, "UTF-16LE", null, null, null); checkHttpEncoding("UTF-16BE", false, APPXML_UTF16, "UTF-16BE", null, null, null); checkHttpEncoding("UTF-8", false, APPXML_UTF8, null, null, null, null); checkHttpEncoding("UTF-8", false, APPXML_UTF8, "UTF-16BE", "UTF-16BE", "UTF-16BE", "UTF-16BE"); } @Test public void testCalculateHttpEncodingUtf32() throws IOException { // No BOM Expected Lenient cType BOM Guess XML Default checkHttpEncoding("UTF-32LE", true, null, null, null, "UTF-32LE", null); checkHttpEncoding("UTF-32BE", false, TXTXML, null, null, null, "UTF-32BE"); checkHttpEncoding("UTF-32BE", false, APPXML, null, null, null, "UTF-32BE"); checkHttpEncoding("UTF-32LE", false, APPXML_UTF32LE, null, null, null, null); checkHttpEncoding("UTF-32BE", false, APPXML_UTF32BE, null, null, null, null); checkHttpError(HTTPMGS1, false, APPXML_UTF32LE, "UTF-32LE", null, null, null); checkHttpError(HTTPMGS1, false, APPXML_UTF32BE, "UTF-32BE", null, null, null); checkHttpError(HTTPMGS2, false, APPXML_UTF32, null, null, null, null); checkHttpError(HTTPMGS2, false, APPXML_UTF32, "UTF-8", null, null, null); checkHttpEncoding("UTF-32LE", false, APPXML_UTF32, "UTF-32LE", null, null, null); checkHttpEncoding("UTF-32BE", false, APPXML_UTF32, "UTF-32BE", null, null, null); checkHttpEncoding("UTF-8", false, APPXML_UTF8, "UTF-32BE", "UTF-32BE", "UTF-32BE", "UTF-32BE"); } private void checkHttpEncoding(final String expected, final boolean lenient, final String httpContentType, final String bomEnc, final String xmlGuessEnc, final String xmlEnc, final String defaultEncoding) throws IOException { final StringBuilder builder = new StringBuilder(); builder.append("HttpEncoding=[").append(bomEnc).append("], "); builder.append("lenient=[").append(lenient).append("], "); builder.append("httpContentType=[").append(httpContentType).append("], "); builder.append("bomEnc=[").append(bomEnc).append("], "); builder.append("xmlGuessEnc=[").append(xmlGuessEnc).append("], "); builder.append("xmlEnc=[").append(xmlEnc).append("], "); builder.append("defaultEncoding=[").append(defaultEncoding).append("],"); final String encoding = calculateHttpEncoding(httpContentType, bomEnc, xmlGuessEnc, xmlEnc, lenient, defaultEncoding); assertEquals(expected, encoding, builder.toString()); } protected String calculateHttpEncoding(final String httpContentType, final String bomEnc, final String xmlGuessEnc, final String xmlEnc, final boolean lenient, final String defaultEncoding) throws IOException { final MockXmlStreamReader mock = new MockXmlStreamReader(defaultEncoding); final String enc = mock.calculateHttpEncoding(httpContentType, bomEnc, xmlGuessEnc, xmlEnc, lenient); mock.close(); return enc; } private void checkHttpError(final String msgSuffix, final boolean lenient, final String httpContentType, final String bomEnc, final String xmlGuessEnc, final String xmlEnc, final String defaultEncoding) { try { checkHttpEncoding("XmlStreamReaderException", lenient, httpContentType, bomEnc, xmlGuessEnc, xmlEnc, defaultEncoding); fail("Expected XmlStreamReaderException"); } catch (final XmlStreamReaderException e) { assertTrue(e.getMessage().startsWith("Invalid encoding"), "Msg Start: " + e.getMessage()); assertTrue(e.getMessage().endsWith(msgSuffix), "Msg End: " + e.getMessage()); assertEquals(bomEnc, e.getBomEncoding(), "bomEnc"); assertEquals(xmlGuessEnc, e.getXmlGuessEncoding(), "xmlGuessEnc"); assertEquals(xmlEnc, e.getXmlEncoding(), "xmlEnc"); assertEquals(XmlStreamReader.getContentTypeEncoding(httpContentType), e.getContentTypeEncoding(), "ContentTypeEncoding"); assertEquals(XmlStreamReader.getContentTypeMime(httpContentType), e.getContentTypeMime(), "ContentTypeMime"); } catch (final Exception e) { fail("Expected XmlStreamReaderException, but threw " + e); } } /** Mock {@link XmlStreamReader} implementation */ private static class MockXmlStreamReader extends XmlStreamReader { MockXmlStreamReader(final String defaultEncoding) throws IOException { super(new ByteArrayInputStream("".getBytes()), null, true, defaultEncoding); } } } ././@LongLink0100644 0000000 0000000 00000000152 13612062727 011637 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/buffer/CircularBufferInputStreamTest.javacommons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/buffer/CircularBufferInputStreamTest0100644 0000000 0000000 00000007117 13612062727 034061 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input.buffer; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.Random; import org.junit.jupiter.api.Test; public class CircularBufferInputStreamTest { private final Random rnd = new Random(1530960934483L); // System.currentTimeMillis(), when this test was written. // Always using the same seed should ensure a reproducible test. @Test public void testRandomRead() throws Exception { final byte[] inputBuffer = newInputBuffer(); final byte[] bufferCopy = new byte[inputBuffer.length]; final ByteArrayInputStream bais = new ByteArrayInputStream(inputBuffer); @SuppressWarnings("resource") final CircularBufferInputStream cbis = new CircularBufferInputStream(bais, 253); int offset = 0; final byte[] readBuffer = new byte[256]; while (offset < bufferCopy.length) { switch (rnd.nextInt(2)) { case 0: { final int res = cbis.read(); if (res == -1) { throw new IllegalStateException("Unexpected EOF at offset " + offset); } if (inputBuffer[offset] != (byte) res) { // compare as bytes throw new IllegalStateException("Expected " + inputBuffer[offset] + " at offset " + offset + ", got " + res); } ++offset; break; } case 1: { final int res = cbis.read(readBuffer, 0, rnd.nextInt(readBuffer.length+1)); if (res == -1) { throw new IllegalStateException("Unexpected EOF at offset " + offset); } if (res == 0) { throw new IllegalStateException("Unexpected zero-byte-result at offset " + offset); } for (int i = 0; i < res; i++) { if (inputBuffer[offset] != readBuffer[i]) { throw new IllegalStateException("Expected " + inputBuffer[offset] + " at offset " + offset + ", got " + readBuffer[i]); } ++offset; } break; } default: throw new IllegalStateException("Unexpected random choice value"); } } assertTrue(true, "Test finished OK"); } @Test public void testIO683() throws IOException { final byte[] buffer = {0,1,-2,-2,-1,4}; try ( final ByteArrayInputStream bais = new ByteArrayInputStream(buffer); final CircularBufferInputStream cbis = new CircularBufferInputStream(bais) ){ int b; int i = 0; while((b = cbis.read()) != -1) { assertEquals(buffer[i] & 0xFF,b, "byte at index " + i + " should be equal"); i++; } assertEquals(buffer.length, i, "Should have read all the bytes"); } } /** * Create a large, but random input buffer. */ private byte[] newInputBuffer() { final byte[] buffer = new byte[16*512+rnd.nextInt(512)]; rnd.nextBytes(buffer); return buffer; } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/compatibility/XmlStreamReader.java0100644 0000000 0000000 00000074002 13612062727 033503 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input.compatibility; import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.io.StringReader; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLConnection; import java.nio.file.Files; import java.text.MessageFormat; import java.util.Locale; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.commons.io.IOUtils; import org.apache.commons.io.output.XmlStreamWriter; /** * Character stream that handles all the necessary Voodoo to figure out the * charset encoding of the XML document within the stream. *

* IMPORTANT: This class is not related in any way to the org.xml.sax.XMLReader. * This one IS a character stream. *

*

* All this has to be done without consuming characters from the stream, if not * the XML parser will not recognized the document as a valid XML. This is not * 100% true, but it's close enough (UTF-8 BOM is not handled by all parsers * right now, XmlStreamReader handles it and things work in all parsers). *

*

* The XmlStreamReader class handles the charset encoding of XML documents in * Files, raw streams and HTTP streams by offering a wide set of constructors. *

*

* By default the charset encoding detection is lenient, the constructor with * the lenient flag can be used for a script (following HTTP MIME and XML * specifications). All this is nicely explained by Mark Pilgrim in his blog, * Determining the character encoding of a feed. *

*

* Originally developed for ROME under * Apache License 2.0. *

* * @see XmlStreamWriter */ public class XmlStreamReader extends Reader { private static final String UTF_8 = "UTF-8"; private static final String US_ASCII = "US-ASCII"; private static final String UTF_16BE = "UTF-16BE"; private static final String UTF_16LE = "UTF-16LE"; private static final String UTF_16 = "UTF-16"; private static final String UTF_32BE = "UTF-32BE"; private static final String UTF_32LE = "UTF-32LE"; private static final String UTF_32 = "UTF-32"; private static final String EBCDIC = "CP1047"; private static String staticDefaultEncoding; private Reader reader; private String encoding; private final String defaultEncoding; /** * Sets the default encoding to use if none is set in HTTP content-type, XML * prolog and the rules based on content-type are not adequate. *

* If it is set to NULL the content-type based rules are used. *

* By default it is NULL. * * @param encoding charset encoding to default to. */ public static void setDefaultEncoding(final String encoding) { staticDefaultEncoding = encoding; } /** * Returns the default encoding to use if none is set in HTTP content-type, * XML prolog and the rules based on content-type are not adequate. *

* If it is NULL the content-type based rules are used. * * @return the default encoding to use. */ public static String getDefaultEncoding() { return staticDefaultEncoding; } /** * Creates a Reader for a File. *

* It looks for the UTF-8 BOM first, if none sniffs the XML prolog charset, * if this is also missing defaults to UTF-8. *

* It does a lenient charset encoding detection, check the constructor with * the lenient parameter for details. * * @param file File to create a Reader from. * @throws IOException thrown if there is a problem reading the file. */ @SuppressWarnings("resource") // FileInputStream is closed when this closed when this object is closed. public XmlStreamReader(final File file) throws IOException { this(Files.newInputStream(file.toPath())); } /** * Creates a Reader for a raw InputStream. *

* It follows the same logic used for files. *

* It does a lenient charset encoding detection, check the constructor with * the lenient parameter for details. * * @param inputStream InputStream to create a Reader from. * @throws IOException thrown if there is a problem reading the stream. */ public XmlStreamReader(final InputStream inputStream) throws IOException { this(inputStream, true); } /** * Creates a Reader for a raw InputStream. *

* It follows the same logic used for files. *

* If lenient detection is indicated and the detection above fails as per * specifications it then attempts the following: *

* If the content type was 'text/html' it replaces it with 'text/xml' and * tries the detection again. *

* Else if the XML prolog had a charset encoding that encoding is used. *

* Else if the content type had a charset encoding that encoding is used. *

* Else 'UTF-8' is used. *

* If lenient detection is indicated an XmlStreamReaderException is never * thrown. * * @param inputStream InputStream to create a Reader from. * @param lenient indicates if the charset encoding detection should be * relaxed. * @throws IOException thrown if there is a problem reading the stream. * @throws XmlStreamReaderException thrown if the charset encoding could not * be determined according to the specs. */ public XmlStreamReader(final InputStream inputStream, final boolean lenient) throws IOException, XmlStreamReaderException { defaultEncoding = staticDefaultEncoding; try { doRawStream(inputStream); } catch (final XmlStreamReaderException ex) { if (!lenient) { throw ex; } doLenientDetection(null, ex); } } /** * Creates a Reader using the InputStream of a URL. *

* If the URL is not of type HTTP and there is not 'content-type' header in * the fetched data it uses the same logic used for Files. *

* If the URL is a HTTP Url or there is a 'content-type' header in the * fetched data it uses the same logic used for an InputStream with * content-type. *

* It does a lenient charset encoding detection, check the constructor with * the lenient parameter for details. * * @param url URL to create a Reader from. * @throws IOException thrown if there is a problem reading the stream of * the URL. */ public XmlStreamReader(final URL url) throws IOException { this(url.openConnection()); } /** * Creates a Reader using the InputStream of a URLConnection. *

* If the URLConnection is not of type HttpURLConnection and there is not * 'content-type' header in the fetched data it uses the same logic used for * files. *

* If the URLConnection is a HTTP Url or there is a 'content-type' header in * the fetched data it uses the same logic used for an InputStream with * content-type. *

* It does a lenient charset encoding detection, check the constructor with * the lenient parameter for details. * * @param conn URLConnection to create a Reader from. * @throws IOException thrown if there is a problem reading the stream of * the URLConnection. */ public XmlStreamReader(final URLConnection conn) throws IOException { defaultEncoding = staticDefaultEncoding; final boolean lenient = true; if (conn instanceof HttpURLConnection) { try { doHttpStream(conn.getInputStream(), conn.getContentType(), lenient); } catch (final XmlStreamReaderException ex) { doLenientDetection(conn.getContentType(), ex); } } else if (conn.getContentType() != null) { try { doHttpStream(conn.getInputStream(), conn.getContentType(), lenient); } catch (final XmlStreamReaderException ex) { doLenientDetection(conn.getContentType(), ex); } } else { try { doRawStream(conn.getInputStream()); } catch (final XmlStreamReaderException ex) { doLenientDetection(null, ex); } } } /** * Creates a Reader using an InputStream and the associated content-type * header. *

* First it checks if the stream has BOM. If there is not BOM checks the * content-type encoding. If there is not content-type encoding checks the * XML prolog encoding. If there is not XML prolog encoding uses the default * encoding mandated by the content-type MIME type. *

* It does a lenient charset encoding detection, check the constructor with * the lenient parameter for details. * * @param inputStream InputStream to create the reader from. * @param httpContentType content-type header to use for the resolution of * the charset encoding. * @throws IOException thrown if there is a problem reading the file. */ public XmlStreamReader(final InputStream inputStream, final String httpContentType) throws IOException { this(inputStream, httpContentType, true); } /** * Creates a Reader using an InputStream and the associated content-type * header. This constructor is lenient regarding the encoding detection. *

* First it checks if the stream has BOM. If there is not BOM checks the * content-type encoding. If there is not content-type encoding checks the * XML prolog encoding. If there is not XML prolog encoding uses the default * encoding mandated by the content-type MIME type. *

* If lenient detection is indicated and the detection above fails as per * specifications it then attempts the following: *

* If the content type was 'text/html' it replaces it with 'text/xml' and * tries the detection again. *

* Else if the XML prolog had a charset encoding that encoding is used. *

* Else if the content type had a charset encoding that encoding is used. *

* Else 'UTF-8' is used. *

* If lenient detection is indicated an XmlStreamReaderException is never * thrown. * * @param inputStream InputStream to create the reader from. * @param httpContentType content-type header to use for the resolution of * the charset encoding. * @param lenient indicates if the charset encoding detection should be * relaxed. * @param defaultEncoding the default encoding to use * @throws IOException thrown if there is a problem reading the file. * @throws XmlStreamReaderException thrown if the charset encoding could not * be determined according to the specs. */ public XmlStreamReader(final InputStream inputStream, final String httpContentType, final boolean lenient, final String defaultEncoding) throws IOException, XmlStreamReaderException { this.defaultEncoding = defaultEncoding == null ? staticDefaultEncoding : defaultEncoding; try { doHttpStream(inputStream, httpContentType, lenient); } catch (final XmlStreamReaderException ex) { if (!lenient) { throw ex; } doLenientDetection(httpContentType, ex); } } /** * Creates a Reader using an InputStream and the associated content-type * header. This constructor is lenient regarding the encoding detection. *

* First it checks if the stream has BOM. If there is not BOM checks the * content-type encoding. If there is not content-type encoding checks the * XML prolog encoding. If there is not XML prolog encoding uses the default * encoding mandated by the content-type MIME type. *

* If lenient detection is indicated and the detection above fails as per * specifications it then attempts the following: *

* If the content type was 'text/html' it replaces it with 'text/xml' and * tries the detection again. *

* Else if the XML prolog had a charset encoding that encoding is used. *

* Else if the content type had a charset encoding that encoding is used. *

* Else 'UTF-8' is used. *

* If lenient detection is indicated an XmlStreamReaderException is never * thrown. * * @param inputStream InputStream to create the reader from. * @param httpContentType content-type header to use for the resolution of * the charset encoding. * @param lenient indicates if the charset encoding detection should be * relaxed. * @throws IOException thrown if there is a problem reading the file. * @throws XmlStreamReaderException thrown if the charset encoding could not * be determined according to the specs. */ public XmlStreamReader(final InputStream inputStream, final String httpContentType, final boolean lenient) throws IOException, XmlStreamReaderException { this(inputStream, httpContentType, lenient, null); } private void doLenientDetection(String httpContentType, XmlStreamReaderException ex) throws IOException { if ((httpContentType != null) && httpContentType.startsWith("text/html")) { httpContentType = httpContentType.substring("text/html" .length()); httpContentType = "text/xml" + httpContentType; try { doHttpStream(ex.getInputStream(), httpContentType, true); ex = null; } catch (final XmlStreamReaderException ex2) { ex = ex2; } } if (ex != null) { String encoding = ex.getXmlEncoding(); if (encoding == null) { encoding = ex.getContentTypeEncoding(); } if (encoding == null) { encoding = defaultEncoding == null ? UTF_8 : defaultEncoding; } prepareReader(ex.getInputStream(), encoding); } } /** * Returns the charset encoding of the XmlStreamReader. * * @return charset encoding. */ public String getEncoding() { return encoding; } @Override public int read(final char[] buf, final int offset, final int len) throws IOException { return reader.read(buf, offset, len); } /** * Closes the XmlStreamReader stream. * * @throws IOException thrown if there was a problem closing the stream. */ @Override public void close() throws IOException { reader.close(); } private void doRawStream(final InputStream inputStream) throws IOException { final BufferedInputStream pis = new BufferedInputStream(inputStream, IOUtils.DEFAULT_BUFFER_SIZE); final String bomEnc = getBOMEncoding(pis); final String xmlGuessEnc = getXMLGuessEncoding(pis); final String xmlEnc = getXmlProlog(pis, xmlGuessEnc); final String encoding = calculateRawEncoding(bomEnc, xmlGuessEnc, xmlEnc, pis); prepareReader(pis, encoding); } private void doHttpStream(final InputStream inputStream, final String httpContentType, final boolean lenient) throws IOException { final BufferedInputStream pis = new BufferedInputStream(inputStream, IOUtils.DEFAULT_BUFFER_SIZE); final String cTMime = getContentTypeMime(httpContentType); final String cTEnc = getContentTypeEncoding(httpContentType); final String bomEnc = getBOMEncoding(pis); final String xmlGuessEnc = getXMLGuessEncoding(pis); final String xmlEnc = getXmlProlog(pis, xmlGuessEnc); final String encoding = calculateHttpEncoding(cTMime, cTEnc, bomEnc, xmlGuessEnc, xmlEnc, pis, lenient); prepareReader(pis, encoding); } private void prepareReader(final InputStream inputStream, final String encoding) throws IOException { reader = new InputStreamReader(inputStream, encoding); this.encoding = encoding; } // InputStream is passed for XmlStreamReaderException creation only String calculateRawEncoding(final String bomEnc, final String xmlGuessEnc, final String xmlEnc, final InputStream is) throws IOException { final String encoding; if (bomEnc == null) { if (xmlGuessEnc == null || xmlEnc == null) { encoding = defaultEncoding == null ? UTF_8 : defaultEncoding; } else if (xmlEnc.equals(UTF_16) && (xmlGuessEnc.equals(UTF_16BE) || xmlGuessEnc .equals(UTF_16LE))) { encoding = xmlGuessEnc; } else if (xmlEnc.equals(UTF_32) && (xmlGuessEnc.equals(UTF_32BE) || xmlGuessEnc .equals(UTF_32LE))) { encoding = xmlGuessEnc; } else { encoding = xmlEnc; } } else if (bomEnc.equals(UTF_8)) { if (xmlGuessEnc != null && !xmlGuessEnc.equals(UTF_8)) { throw new XmlStreamReaderException(RAW_EX_1 .format(new Object[] { bomEnc, xmlGuessEnc, xmlEnc }), bomEnc, xmlGuessEnc, xmlEnc, is); } if (xmlEnc != null && !xmlEnc.equals(UTF_8)) { throw new XmlStreamReaderException(RAW_EX_1 .format(new Object[] { bomEnc, xmlGuessEnc, xmlEnc }), bomEnc, xmlGuessEnc, xmlEnc, is); } encoding = UTF_8; } else if (bomEnc.equals(UTF_16BE) || bomEnc.equals(UTF_16LE)) { if (xmlGuessEnc != null && !xmlGuessEnc.equals(bomEnc)) { throw new XmlStreamReaderException(RAW_EX_1.format(new Object[] { bomEnc, xmlGuessEnc, xmlEnc }), bomEnc, xmlGuessEnc, xmlEnc, is); } if (xmlEnc != null && !xmlEnc.equals(UTF_16) && !xmlEnc.equals(bomEnc)) { throw new XmlStreamReaderException(RAW_EX_1 .format(new Object[] { bomEnc, xmlGuessEnc, xmlEnc }), bomEnc, xmlGuessEnc, xmlEnc, is); } encoding = bomEnc; } else if (bomEnc.equals(UTF_32BE) || bomEnc.equals(UTF_32LE)) { if (xmlGuessEnc != null && !xmlGuessEnc.equals(bomEnc)) { throw new XmlStreamReaderException(RAW_EX_1.format(new Object[] { bomEnc, xmlGuessEnc, xmlEnc }), bomEnc, xmlGuessEnc, xmlEnc, is); } if (xmlEnc != null && !xmlEnc.equals(UTF_32) && !xmlEnc.equals(bomEnc)) { throw new XmlStreamReaderException(RAW_EX_1 .format(new Object[] { bomEnc, xmlGuessEnc, xmlEnc }), bomEnc, xmlGuessEnc, xmlEnc, is); } encoding = bomEnc; } else { throw new XmlStreamReaderException(RAW_EX_2.format(new Object[] { bomEnc, xmlGuessEnc, xmlEnc }), bomEnc, xmlGuessEnc, xmlEnc, is); } return encoding; } // InputStream is passed for XmlStreamReaderException creation only String calculateHttpEncoding(final String cTMime, final String cTEnc, final String bomEnc, final String xmlGuessEnc, final String xmlEnc, final InputStream is, final boolean lenient) throws IOException { final String encoding; if (lenient && (xmlEnc != null)) { encoding = xmlEnc; } else { final boolean appXml = isAppXml(cTMime); final boolean textXml = isTextXml(cTMime); if (!appXml && !textXml) { throw new XmlStreamReaderException(HTTP_EX_3 .format(new Object[] { cTMime, cTEnc, bomEnc, xmlGuessEnc, xmlEnc }), cTMime, cTEnc, bomEnc, xmlGuessEnc, xmlEnc, is); } if (cTEnc == null) { if (appXml) { encoding = calculateRawEncoding(bomEnc, xmlGuessEnc, xmlEnc, is); } else { encoding = defaultEncoding == null ? US_ASCII : defaultEncoding; } } else if (bomEnc != null && (cTEnc.equals(UTF_16BE) || cTEnc.equals(UTF_16LE))) { throw new XmlStreamReaderException(HTTP_EX_1 .format(new Object[] { cTMime, cTEnc, bomEnc, xmlGuessEnc, xmlEnc }), cTMime, cTEnc, bomEnc, xmlGuessEnc, xmlEnc, is); } else if (cTEnc.equals(UTF_16)) { if ((bomEnc == null) || !bomEnc.startsWith(UTF_16)) { throw new XmlStreamReaderException(HTTP_EX_2 .format(new Object[] { cTMime, cTEnc, bomEnc, xmlGuessEnc, xmlEnc }), cTMime, cTEnc, bomEnc, xmlGuessEnc, xmlEnc, is); } encoding = bomEnc; } else if (bomEnc != null && (cTEnc.equals(UTF_32BE) || cTEnc.equals(UTF_32LE))) { throw new XmlStreamReaderException(HTTP_EX_1 .format(new Object[] { cTMime, cTEnc, bomEnc, xmlGuessEnc, xmlEnc }), cTMime, cTEnc, bomEnc, xmlGuessEnc, xmlEnc, is); } else if (cTEnc.equals(UTF_32)) { if ((bomEnc == null) || !bomEnc.startsWith(UTF_32)) { throw new XmlStreamReaderException(HTTP_EX_2 .format(new Object[] { cTMime, cTEnc, bomEnc, xmlGuessEnc, xmlEnc }), cTMime, cTEnc, bomEnc, xmlGuessEnc, xmlEnc, is); } encoding = bomEnc; } else { encoding = cTEnc; } } return encoding; } // returns MIME type or NULL if httpContentType is NULL static String getContentTypeMime(final String httpContentType) { String mime = null; if (httpContentType != null) { final int i = httpContentType.indexOf(";"); mime = (i == -1 ? httpContentType : httpContentType.substring(0, i)).trim(); } return mime; } private static final Pattern CHARSET_PATTERN = Pattern .compile("charset=[\"']?([.[^; \"']]*)[\"']?"); // returns charset parameter value, NULL if not present, NULL if // httpContentType is NULL static String getContentTypeEncoding(final String httpContentType) { String encoding = null; if (httpContentType != null) { final int i = httpContentType.indexOf(";"); if (i > -1) { final String postMime = httpContentType.substring(i + 1); final Matcher m = CHARSET_PATTERN.matcher(postMime); encoding = m.find() ? m.group(1) : null; encoding = encoding != null ? encoding.toUpperCase(Locale.ROOT) : null; } } return encoding; } // returns the BOM in the stream, NULL if not present, // if there was BOM the in the stream it is consumed static String getBOMEncoding(final BufferedInputStream is) throws IOException { String encoding = null; final int[] bytes = new int[3]; is.mark(3); bytes[0] = is.read(); bytes[1] = is.read(); bytes[2] = is.read(); if (bytes[0] == 0xFE && bytes[1] == 0xFF) { encoding = UTF_16BE; is.reset(); is.read(); is.read(); } else if (bytes[0] == 0xFF && bytes[1] == 0xFE) { encoding = UTF_16LE; is.reset(); is.read(); is.read(); } else if (bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF) { encoding = UTF_8; } else { is.reset(); } return encoding; } // returns the best guess for the encoding by looking the first bytes of the // stream, ', NULL if none private static String getXmlProlog(final BufferedInputStream is, final String guessedEnc) throws IOException { String encoding = null; if (guessedEnc != null) { final byte[] bytes = IOUtils.byteArray(); is.mark(IOUtils.DEFAULT_BUFFER_SIZE); int offset = 0; int max = IOUtils.DEFAULT_BUFFER_SIZE; int c = is.read(bytes, offset, max); int firstGT = -1; String xmlProlog = ""; // avoid possible NPE warning (cannot happen; this just silences the warning) while (c != -1 && firstGT == -1 && offset < IOUtils.DEFAULT_BUFFER_SIZE) { offset += c; max -= c; c = is.read(bytes, offset, max); xmlProlog = new String(bytes, 0, offset, guessedEnc); firstGT = xmlProlog.indexOf('>'); } if (firstGT == -1) { if (c == -1) { throw new IOException("Unexpected end of XML stream"); } throw new IOException( "XML prolog or ROOT element not found on first " + offset + " bytes"); } final int bytesRead = offset; if (bytesRead > 0) { is.reset(); final BufferedReader bReader = new BufferedReader(new StringReader( xmlProlog.substring(0, firstGT + 1))); final StringBuffer prolog = new StringBuffer(); String line; while ((line = bReader.readLine()) != null) { prolog.append(line); } final Matcher m = ENCODING_PATTERN.matcher(prolog); if (m.find()) { encoding = m.group(1).toUpperCase(Locale.ROOT); encoding = encoding.substring(1, encoding.length() - 1); } } } return encoding; } // indicates if the MIME type belongs to the APPLICATION XML family static boolean isAppXml(final String mime) { return mime != null && (mime.equals("application/xml") || mime.equals("application/xml-dtd") || mime .equals("application/xml-external-parsed-entity") || mime .startsWith("application/") && mime.endsWith("+xml")); } // indicates if the MIME type belongs to the TEXT XML family static boolean isTextXml(final String mime) { return mime != null && (mime.equals("text/xml") || mime.equals("text/xml-external-parsed-entity") || mime .startsWith("text/") && mime.endsWith("+xml")); } private static final MessageFormat RAW_EX_1 = new MessageFormat( "Invalid encoding, BOM [{0}] XML guess [{1}] XML prolog [{2}] encoding mismatch"); private static final MessageFormat RAW_EX_2 = new MessageFormat( "Invalid encoding, BOM [{0}] XML guess [{1}] XML prolog [{2}] unknown BOM"); private static final MessageFormat HTTP_EX_1 = new MessageFormat( "Invalid encoding, CT-MIME [{0}] CT-Enc [{1}] BOM [{2}] XML guess [{3}] XML prolog [{4}], BOM must be NULL"); private static final MessageFormat HTTP_EX_2 = new MessageFormat( "Invalid encoding, CT-MIME [{0}] CT-Enc [{1}] BOM [{2}] XML guess [{3}] XML prolog [{4}], encoding mismatch"); private static final MessageFormat HTTP_EX_3 = new MessageFormat( "Invalid encoding, CT-MIME [{0}] CT-Enc [{1}] BOM [{2}] XML guess [{3}] XML prolog [{4}], Invalid MIME"); } ././@LongLink0100644 0000000 0000000 00000000154 13612062727 011641 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/compatibility/XmlStreamReaderException.javacommons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/compatibility/XmlStreamReaderExcepti0100644 0000000 0000000 00000006413 13612062727 034106 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input.compatibility; import java.io.InputStream; /** * The XmlStreamReaderException is thrown by the XmlStreamReader constructors if * the charset encoding can not be determined according to the XML 1.0 * specification and RFC 3023. *

* The exception returns the unconsumed InputStream to allow the application to * do an alternate processing with the stream. Note that the original * InputStream given to the XmlStreamReader cannot be used as that one has been * already read. *

* */ public class XmlStreamReaderException extends org.apache.commons.io.input.XmlStreamReaderException { private static final long serialVersionUID = 1L; private final InputStream inputStream; /** * Creates an exception instance if the charset encoding could not be * determined. *

* Instances of this exception are thrown by the XmlStreamReader. * * @param msg message describing the reason for the exception. * @param bomEnc BOM encoding. * @param xmlGuessEnc XML guess encoding. * @param xmlEnc XML prolog encoding. * @param is the unconsumed InputStream. */ public XmlStreamReaderException(final String msg, final String bomEnc, final String xmlGuessEnc, final String xmlEnc, final InputStream is) { this(msg, null, null, bomEnc, xmlGuessEnc, xmlEnc, is); } /** * Creates an exception instance if the charset encoding could not be * determined. *

* Instances of this exception are thrown by the XmlStreamReader. * * @param msg message describing the reason for the exception. * @param ctMime MIME type in the content-type. * @param ctEnc encoding in the content-type. * @param bomEnc BOM encoding. * @param xmlGuessEnc XML guess encoding. * @param xmlEnc XML prolog encoding. * @param inputStream the unconsumed InputStream. */ public XmlStreamReaderException(final String msg, final String ctMime, final String ctEnc, final String bomEnc, final String xmlGuessEnc, final String xmlEnc, final InputStream inputStream) { super(msg, ctMime, ctEnc, bomEnc, xmlGuessEnc, xmlEnc); this.inputStream = inputStream; } /** * Returns the unconsumed InputStream to allow the application to do an * alternate encoding detection on the InputStream. * * @return the unconsumed InputStream. */ public InputStream getInputStream() { return inputStream; } } ././@LongLink0100644 0000000 0000000 00000000175 13612062727 011644 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/compatibility/XmlStreamReaderUtilitiesCompatibilityTest.javacommons-io-2.11.0-src/src/test/java/org/apache/commons/io/input/compatibility/XmlStreamReaderUtiliti0100644 0000000 0000000 00000004666 13612062727 034140 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.input.compatibility; import java.io.ByteArrayInputStream; import java.io.IOException; import org.apache.commons.io.input.XmlStreamReaderUtilitiesTest; /** * Test compatibility of the original XmlStreamReader (before all the refactoring). */ public class XmlStreamReaderUtilitiesCompatibilityTest extends XmlStreamReaderUtilitiesTest { @Override protected String calculateRawEncoding(final String bomEnc, final String xmlGuessEnc, final String xmlEnc, final String defaultEncoding) throws IOException { try (final MockXmlStreamReader mock = new MockXmlStreamReader(defaultEncoding)) { return mock.calculateRawEncoding(bomEnc, xmlGuessEnc, xmlEnc, null); } } @Override protected String calculateHttpEncoding(final String httpContentType, final String bomEnc, final String xmlGuessEnc, final String xmlEnc, final boolean lenient, final String defaultEncoding) throws IOException { try (final MockXmlStreamReader mock = new MockXmlStreamReader(defaultEncoding)) { return mock.calculateHttpEncoding( XmlStreamReader.getContentTypeMime(httpContentType), XmlStreamReader.getContentTypeEncoding(httpContentType), bomEnc, xmlGuessEnc, xmlEnc, null, lenient); } } /** Mock {@link XmlStreamReader} implementation */ private static class MockXmlStreamReader extends XmlStreamReader { MockXmlStreamReader(final String defaultEncoding) throws IOException { super(new ByteArrayInputStream("".getBytes()), null, true, defaultEncoding); } } } ././@LongLink0100644 0000000 0000000 00000000155 13612062727 011642 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/java/org/apache/commons/io/jmh/IOUtilsContentEqualsInputStreamsBenchmark.javacommons-io-2.11.0-src/src/test/java/org/apache/commons/io/jmh/IOUtilsContentEqualsInputStreamsBenchm0100644 0000000 0000000 00000023735 13612062727 034033 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.jmh; import static org.apache.commons.io.IOUtils.DEFAULT_BUFFER_SIZE; import static org.apache.commons.io.IOUtils.EOF; import static org.apache.commons.io.IOUtils.buffer; import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.nio.charset.Charset; import java.util.concurrent.TimeUnit; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; import org.openjdk.jmh.annotations.Measurement; import org.openjdk.jmh.annotations.Mode; import org.openjdk.jmh.annotations.OutputTimeUnit; import org.openjdk.jmh.annotations.Scope; import org.openjdk.jmh.annotations.State; import org.openjdk.jmh.annotations.Warmup; import org.openjdk.jmh.infra.Blackhole; /** * Test different implementations of {@link IOUtils#contentEquals(InputStream, InputStream)}. * *

 * IOUtilsContentEqualsInputStreamsBenchmark.testFileCurrent          avgt    5      1518342.821 ▒     201890.705  ns/op
 * IOUtilsContentEqualsInputStreamsBenchmark.testFilePr118            avgt    5      1578606.938 ▒      66980.718  ns/op
 * IOUtilsContentEqualsInputStreamsBenchmark.testFileRelease_2_8_0    avgt    5      2439163.068 ▒     265765.294  ns/op
 * IOUtilsContentEqualsInputStreamsBenchmark.testStringCurrent        avgt    5  10389834700.000 ▒  330301175.219  ns/op
 * IOUtilsContentEqualsInputStreamsBenchmark.testStringPr118          avgt    5  10890915400.000 ▒ 3251289634.067  ns/op
 * IOUtilsContentEqualsInputStreamsBenchmark.testStringRelease_2_8_0  avgt    5  12522802960.000 ▒  111147669.527  ns/op
 * 
*/ @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.NANOSECONDS) @State(Scope.Thread) @Warmup(iterations = 5, time = 10, timeUnit = TimeUnit.SECONDS) @Measurement(iterations = 5, time = 10, timeUnit = TimeUnit.SECONDS) @Fork(value = 1, jvmArgs = {"-server"}) public class IOUtilsContentEqualsInputStreamsBenchmark { private static final String TEST_PATH_A = "/org/apache/commons/io/testfileBOM.xml"; private static final String TEST_PATH_16K_A = "/org/apache/commons/io/abitmorethan16k.txt"; private static final String TEST_PATH_16K_A_COPY = "/org/apache/commons/io/abitmorethan16kcopy.txt"; private static final String TEST_PATH_B = "/org/apache/commons/io/testfileNoBOM.xml"; private static final Charset DEFAULT_CHARSET = Charset.defaultCharset(); static String[] STRINGS = new String[5]; static { STRINGS[0] = StringUtils.repeat("ab", 1 << 24); STRINGS[1] = STRINGS[0] + 'c'; STRINGS[2] = STRINGS[0] + 'd'; STRINGS[3] = StringUtils.repeat("ab\rab\n", 1 << 24); STRINGS[4] = StringUtils.repeat("ab\r\nab\r", 1 << 24); } static String SPECIAL_CASE_STRING_0 = StringUtils.repeat(StringUtils.repeat("ab", 1 << 24) + '\n', 2); static String SPECIAL_CASE_STRING_1 = StringUtils.repeat(StringUtils.repeat("cd", 1 << 24) + '\n', 2); @SuppressWarnings("resource") public static boolean contentEquals_release_2_8_0(final InputStream input1, final InputStream input2) throws IOException { if (input1 == input2) { return true; } if (input1 == null ^ input2 == null) { return false; } final BufferedInputStream bufferedInput1 = buffer(input1); final BufferedInputStream bufferedInput2 = buffer(input2); int ch = bufferedInput1.read(); while (EOF != ch) { final int ch2 = bufferedInput2.read(); if (ch != ch2) { return false; } ch = bufferedInput1.read(); } return bufferedInput2.read() == EOF; } public static boolean contentEqualsPr118(final InputStream input1, final InputStream input2) throws IOException { if (input1 == input2) { return true; } if (input1 == null || input2 == null) { return false; } final byte[] array1 = new byte[DEFAULT_BUFFER_SIZE]; final byte[] array2 = new byte[DEFAULT_BUFFER_SIZE]; int pos1; int pos2; int count1; int count2; while (true) { pos1 = 0; pos2 = 0; for (int index = 0; index < DEFAULT_BUFFER_SIZE; index++) { if (pos1 == index) { do { count1 = input1.read(array1, pos1, DEFAULT_BUFFER_SIZE - pos1); } while (count1 == 0); if (count1 == EOF) { return pos2 == index && input2.read() == EOF; } pos1 += count1; } if (pos2 == index) { do { count2 = input2.read(array2, pos2, DEFAULT_BUFFER_SIZE - pos2); } while (count2 == 0); if (count2 == EOF) { return pos1 == index && input1.read() == EOF; } pos2 += count2; } if (array1[index] != array2[index]) { return false; } } } } @Benchmark public boolean[] testFileCurrent() throws IOException { final boolean[] res = new boolean[3]; try (InputStream input1 = getClass().getResourceAsStream(TEST_PATH_A); InputStream input2 = getClass().getResourceAsStream(TEST_PATH_B)) { res[0] = IOUtils.contentEquals(input1, input1); } try (InputStream input1 = getClass().getResourceAsStream(TEST_PATH_A); InputStream input2 = getClass().getResourceAsStream(TEST_PATH_A);) { res[1] = IOUtils.contentEquals(input1, input2); } try (InputStream input1 = getClass().getResourceAsStream(TEST_PATH_16K_A); InputStream input2 = getClass().getResourceAsStream(TEST_PATH_16K_A_COPY);) { res[2] = IOUtils.contentEquals(input1, input2); } return res; } @Benchmark public boolean[] testFilePr118() throws IOException { final boolean[] res = new boolean[3]; try (InputStream input1 = getClass().getResourceAsStream(TEST_PATH_A); InputStream input2 = getClass().getResourceAsStream(TEST_PATH_B)) { res[0] = contentEqualsPr118(input1, input1); } try (InputStream input1 = getClass().getResourceAsStream(TEST_PATH_A); InputStream input2 = getClass().getResourceAsStream(TEST_PATH_A)) { res[1] = contentEqualsPr118(input1, input2); } try (InputStream input1 = getClass().getResourceAsStream(TEST_PATH_16K_A); InputStream input2 = getClass().getResourceAsStream(TEST_PATH_16K_A_COPY)) { res[2] = contentEqualsPr118(input1, input2); } return res; } @Benchmark public boolean[] testFileRelease_2_8_0() throws IOException { final boolean[] res = new boolean[3]; try (InputStream input1 = getClass().getResourceAsStream(TEST_PATH_A); InputStream input2 = getClass().getResourceAsStream(TEST_PATH_B)) { res[0] = contentEquals_release_2_8_0(input1, input1); } try (InputStream input1 = getClass().getResourceAsStream(TEST_PATH_A); InputStream input2 = getClass().getResourceAsStream(TEST_PATH_A);) { res[1] = contentEquals_release_2_8_0(input1, input2); } try (InputStream input1 = getClass().getResourceAsStream(TEST_PATH_16K_A); InputStream input2 = getClass().getResourceAsStream(TEST_PATH_16K_A_COPY)) { res[2] = contentEquals_release_2_8_0(input1, input2); } return res; } @Benchmark public void testStringCurrent(final Blackhole blackhole) throws IOException { for (int i = 0; i < 5; i++) { for (int j = 0; j < 5; j++) { try (InputStream inputReader1 = IOUtils.toInputStream(STRINGS[i], DEFAULT_CHARSET); InputStream inputReader2 = IOUtils.toInputStream(STRINGS[j], DEFAULT_CHARSET)) { blackhole.consume(IOUtils.contentEquals(inputReader1, inputReader2)); } } } } @Benchmark public void testStringPr118(final Blackhole blackhole) throws IOException { for (int i = 0; i < 5; i++) { for (int j = 0; j < 5; j++) { try (InputStream input1 = IOUtils.toInputStream(STRINGS[i], DEFAULT_CHARSET); InputStream input2 = IOUtils.toInputStream(STRINGS[j], DEFAULT_CHARSET)) { blackhole.consume(contentEqualsPr118(input1, input2)); } } } } @Benchmark public void testStringRelease_2_8_0(final Blackhole blackhole) throws IOException { for (int i = 0; i < 5; i++) { for (int j = 0; j < 5; j++) { try (InputStream input1 = IOUtils.toInputStream(STRINGS[i], DEFAULT_CHARSET); InputStream input2 = IOUtils.toInputStream(STRINGS[j], DEFAULT_CHARSET)) { blackhole.consume(contentEquals_release_2_8_0(input1, input2)); } } } } } ././@LongLink0100644 0000000 0000000 00000000150 13612062727 011635 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/java/org/apache/commons/io/jmh/IOUtilsContentEqualsReadersBenchmark.javacommons-io-2.11.0-src/src/test/java/org/apache/commons/io/jmh/IOUtilsContentEqualsReadersBenchmark.j0100644 0000000 0000000 00000024745 13612062727 033712 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.jmh; import static org.apache.commons.io.IOUtils.DEFAULT_BUFFER_SIZE; import static org.apache.commons.io.IOUtils.EOF; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.Reader; import java.io.StringReader; import java.nio.charset.Charset; import java.util.concurrent.TimeUnit; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; import org.openjdk.jmh.annotations.Measurement; import org.openjdk.jmh.annotations.Mode; import org.openjdk.jmh.annotations.OutputTimeUnit; import org.openjdk.jmh.annotations.Scope; import org.openjdk.jmh.annotations.State; import org.openjdk.jmh.annotations.Warmup; import org.openjdk.jmh.infra.Blackhole; /** * Test different implementations of {@link IOUtils#contentEquals(Reader, Reader)}. * *
 * IOUtilsContentEqualsReadersBenchmark.testFileCurrent               avgt    5      1670968.050 ▒     67526.308  ns/op
 * IOUtilsContentEqualsReadersBenchmark.testFilePr118                 avgt    5      1660143.543 ▒    733178.893  ns/op
 * IOUtilsContentEqualsReadersBenchmark.testFileRelease_2_8_0         avgt    5      1785283.975 ▒    214177.764  ns/op
 * IOUtilsContentEqualsReadersBenchmark.testStringCurrent             avgt    5   1144495273.333 ▒  50706166.907  ns/op
 * IOUtilsContentEqualsReadersBenchmark.testStringPr118               avgt    5   1075059231.455 ▒ 275364676.487  ns/op
 * IOUtilsContentEqualsReadersBenchmark.testStringRelease_2_8_0       avgt    5   4767157193.333 ▒ 139567775.251  ns/op
 * 
*/ @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.NANOSECONDS) @State(Scope.Thread) @Warmup(iterations = 5, time = 10, timeUnit = TimeUnit.SECONDS) @Measurement(iterations = 5, time = 10, timeUnit = TimeUnit.SECONDS) @Fork(value = 1, jvmArgs = {"-server"}) public class IOUtilsContentEqualsReadersBenchmark { private static final int STRING_LEN = 1 << 24; private static final String TEST_PATH_A = "/org/apache/commons/io/testfileBOM.xml"; private static final String TEST_PATH_16K_A = "/org/apache/commons/io/abitmorethan16k.txt"; private static final String TEST_PATH_16K_A_COPY = "/org/apache/commons/io/abitmorethan16kcopy.txt"; private static final String TEST_PATH_B = "/org/apache/commons/io/testfileNoBOM.xml"; private static final Charset DEFAULT_CHARSET = Charset.defaultCharset(); static String[] STRINGS = new String[5]; static { STRINGS[0] = StringUtils.repeat("ab", STRING_LEN); STRINGS[1] = STRINGS[0] + 'c'; STRINGS[2] = STRINGS[0] + 'd'; STRINGS[3] = StringUtils.repeat("ab\rab\n", STRING_LEN); STRINGS[4] = StringUtils.repeat("ab\r\nab\r", STRING_LEN); } static String SPECIAL_CASE_STRING_0 = StringUtils.repeat(StringUtils.repeat("ab", STRING_LEN) + '\n', 2); static String SPECIAL_CASE_STRING_1 = StringUtils.repeat(StringUtils.repeat("cd", STRING_LEN) + '\n', 2); @SuppressWarnings("resource") public static boolean contentEquals_release_2_8_0(final Reader input1, final Reader input2) throws IOException { if (input1 == input2) { return true; } if (input1 == null ^ input2 == null) { return false; } final BufferedReader bufferedInput1 = IOUtils.toBufferedReader(input1); final BufferedReader bufferedInput2 = IOUtils.toBufferedReader(input2); int ch = bufferedInput1.read(); while (EOF != ch) { final int ch2 = bufferedInput2.read(); if (ch != ch2) { return false; } ch = bufferedInput1.read(); } return bufferedInput2.read() == EOF; } public static boolean contentEqualsPr118(final Reader input1, final Reader input2) throws IOException { if (input1 == input2) { return true; } if (input1 == null || input2 == null) { return false; } final char[] array1 = new char[DEFAULT_BUFFER_SIZE]; final char[] array2 = new char[DEFAULT_BUFFER_SIZE]; int pos1; int pos2; int count1; int count2; while (true) { pos1 = 0; pos2 = 0; for (int index = 0; index < DEFAULT_BUFFER_SIZE; index++) { if (pos1 == index) { do { count1 = input1.read(array1, pos1, DEFAULT_BUFFER_SIZE - pos1); } while (count1 == 0); if (count1 == EOF) { return pos2 == index && input2.read() == EOF; } pos1 += count1; } if (pos2 == index) { do { count2 = input2.read(array2, pos2, DEFAULT_BUFFER_SIZE - pos2); } while (count2 == 0); if (count2 == EOF) { return pos1 == index && input1.read() == EOF; } pos2 += count2; } if (array1[index] != array2[index]) { return false; } } } } @Benchmark public boolean[] testFileCurrent() throws IOException { final boolean[] res = new boolean[3]; try (Reader input1 = new InputStreamReader(getClass().getResourceAsStream(TEST_PATH_A), DEFAULT_CHARSET); Reader input2 = new InputStreamReader(getClass().getResourceAsStream(TEST_PATH_B), DEFAULT_CHARSET)) { res[0] = IOUtils.contentEquals(input1, input1); } try (Reader input1 = new InputStreamReader(getClass().getResourceAsStream(TEST_PATH_A), DEFAULT_CHARSET); Reader input2 = new InputStreamReader(getClass().getResourceAsStream(TEST_PATH_A), DEFAULT_CHARSET)) { res[1] = IOUtils.contentEquals(input1, input2); } try (Reader input1 = new InputStreamReader(getClass().getResourceAsStream(TEST_PATH_16K_A), DEFAULT_CHARSET); Reader input2 = new InputStreamReader(getClass().getResourceAsStream(TEST_PATH_16K_A_COPY), DEFAULT_CHARSET)) { res[2] = IOUtils.contentEquals(input1, input2); } return res; } @Benchmark public boolean[] testFilePr118() throws IOException { final boolean[] res = new boolean[3]; try (Reader input1 = new InputStreamReader(getClass().getResourceAsStream(TEST_PATH_A), DEFAULT_CHARSET); Reader input2 = new InputStreamReader(getClass().getResourceAsStream(TEST_PATH_B), DEFAULT_CHARSET)) { res[0] = contentEqualsPr118(input1, input1); } try (Reader input1 = new InputStreamReader(getClass().getResourceAsStream(TEST_PATH_A), DEFAULT_CHARSET); Reader input2 = new InputStreamReader(getClass().getResourceAsStream(TEST_PATH_A), DEFAULT_CHARSET)) { res[1] = contentEqualsPr118(input1, input2); } try (Reader input1 = new InputStreamReader(getClass().getResourceAsStream(TEST_PATH_16K_A)); Reader input2 = new InputStreamReader(getClass().getResourceAsStream(TEST_PATH_16K_A_COPY))) { res[2] = contentEqualsPr118(input1, input2); } return res; } @Benchmark public boolean[] testFileRelease_2_8_0() throws IOException { final boolean[] res = new boolean[3]; try (Reader input1 = new InputStreamReader(getClass().getResourceAsStream(TEST_PATH_A), DEFAULT_CHARSET); Reader input2 = new InputStreamReader(getClass().getResourceAsStream(TEST_PATH_B), DEFAULT_CHARSET)) { res[0] = contentEquals_release_2_8_0(input1, input1); } try (Reader input1 = new InputStreamReader(getClass().getResourceAsStream(TEST_PATH_A), DEFAULT_CHARSET); Reader input2 = new InputStreamReader(getClass().getResourceAsStream(TEST_PATH_A), DEFAULT_CHARSET)) { res[1] = contentEquals_release_2_8_0(input1, input2); } try (Reader input1 = new InputStreamReader(getClass().getResourceAsStream(TEST_PATH_16K_A), DEFAULT_CHARSET); Reader input2 = new InputStreamReader(getClass().getResourceAsStream(TEST_PATH_16K_A_COPY), DEFAULT_CHARSET)) { res[2] = contentEquals_release_2_8_0(input1, input2); } return res; } @Benchmark public void testStringCurrent(final Blackhole blackhole) throws IOException { for (int i = 0; i < 5; i++) { for (int j = 0; j < 5; j++) { try (StringReader input1 = new StringReader(STRINGS[i]); StringReader input2 = new StringReader(STRINGS[j])) { blackhole.consume(IOUtils.contentEquals(input1, input2)); } } } } @Benchmark public void testStringPr118(final Blackhole blackhole) throws IOException { for (int i = 0; i < 5; i++) { for (int j = 0; j < 5; j++) { try (StringReader input1 = new StringReader(STRINGS[i]); StringReader input2 = new StringReader(STRINGS[j])) { blackhole.consume(contentEqualsPr118(input1, input2)); } } } } @Benchmark public void testStringRelease_2_8_0(final Blackhole blackhole) throws IOException { for (int i = 0; i < 5; i++) { for (int j = 0; j < 5; j++) { try (StringReader input1 = new StringReader(STRINGS[i]); StringReader input2 = new StringReader(STRINGS[j])) { blackhole.consume(contentEquals_release_2_8_0(input1, input2)); } } } } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/monitor/AbstractMonitorTestCase.java0100644 0000000 0000000 00000014147 13612062727 032676 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.monitor; import static org.apache.commons.io.test.TestUtils.sleepQuietly; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import java.io.File; import java.io.FileFilter; import java.io.IOException; import org.apache.commons.io.FileUtils; import org.apache.commons.io.filefilter.FileFilterUtils; import org.apache.commons.io.filefilter.HiddenFileFilter; import org.apache.commons.io.filefilter.IOFileFilter; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.io.TempDir; /** * {@link FileAlterationObserver} Test Case. */ public abstract class AbstractMonitorTestCase { /** File observer */ protected FileAlterationObserver observer; /** Listener which collects file changes */ protected CollectionFileListener listener; /** Directory for test files */ @TempDir protected File testDir; /** Time in milliseconds to pause in tests */ protected final long pauseTime = 100L; @BeforeEach public void setUp() { final IOFileFilter files = FileFilterUtils.fileFileFilter(); final IOFileFilter javaSuffix = FileFilterUtils.suffixFileFilter(".java"); final IOFileFilter fileFilter = FileFilterUtils.and(files, javaSuffix); final IOFileFilter directories = FileFilterUtils.directoryFileFilter(); final IOFileFilter visible = HiddenFileFilter.VISIBLE; final IOFileFilter dirFilter = FileFilterUtils.and(directories, visible); final IOFileFilter filter = FileFilterUtils.or(dirFilter, fileFilter); createObserver(testDir, filter); } /** * Create a {@link FileAlterationObserver}. * * @param file The directory to observe * @param fileFilter The file filter to apply */ protected void createObserver(final File file, final FileFilter fileFilter) { observer = new FileAlterationObserver(file, fileFilter); observer.addListener(listener); observer.addListener(new FileAlterationListenerAdaptor()); try { observer.initialize(); } catch (final Exception e) { fail("Observer init() threw " + e); } } /** * Check all the Collections are empty * * @param label the label to use for this check */ protected void checkCollectionsEmpty(final String label) { checkCollectionSizes("EMPTY-" + label, 0, 0, 0, 0, 0, 0); } /** * Check all the Collections have the expected sizes. * * @param label the label to use for this check * @param dirCreate expected number of dirs created * @param dirChange expected number of dirs changed * @param dirDelete expected number of dirs deleted * @param fileCreate expected number of files created * @param fileChange expected number of files changed * @param fileDelete expected number of files deleted */ protected void checkCollectionSizes(String label, final int dirCreate, final int dirChange, final int dirDelete, final int fileCreate, final int fileChange, final int fileDelete) { label = label + "[" + listener.getCreatedDirectories().size() + " " + listener.getChangedDirectories().size() + " " + listener.getDeletedDirectories().size() + " " + listener.getCreatedFiles().size() + " " + listener.getChangedFiles().size() + " " + listener.getDeletedFiles().size() + "]"; assertEquals(dirCreate, listener.getCreatedDirectories().size(), label + ": No. of directories created"); assertEquals(dirChange, listener.getChangedDirectories().size(), label + ": No. of directories changed"); assertEquals(dirDelete, listener.getDeletedDirectories().size(), label + ": No. of directories deleted"); assertEquals(fileCreate, listener.getCreatedFiles().size(), label + ": No. of files created"); assertEquals(fileChange, listener.getChangedFiles().size(), label + ": No. of files changed"); assertEquals(fileDelete, listener.getDeletedFiles().size(), label + ": No. of files deleted"); } /** * Either creates a file if it doesn't exist or updates the last modified date/time * if it does. * * @param file The file to touch * @return The file * @throws IOException if an I/O error occurs. */ protected File touch(File file) throws IOException { final long lastModified = file.exists() ? FileUtils.lastModified(file) : 0; try { FileUtils.touch(file); assertTrue(file.exists()); file = new File(file.getParent(), file.getName()); while (lastModified == FileUtils.lastModified(file)) { sleepQuietly(pauseTime); FileUtils.touch(file); file = new File(file.getParent(), file.getName()); } } catch (final Exception e) { fail("Touching " + file + ": " + e); } sleepQuietly(pauseTime); return file; } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/monitor/CollectionFileListener.java0100644 0000000 0000000 00000012072 13612062727 032523 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.monitor; import java.io.File; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; /** * {@link FileAlterationListener} implementation that adds created, changed and deleted * files/directories to a set of {@link Collection}s. */ public class CollectionFileListener implements FileAlterationListener, Serializable { private static final long serialVersionUID = 939724715678693963L; private final boolean clearOnStart; private final Collection createdFiles = new ArrayList<>(); private final Collection changedFiles = new ArrayList<>(); private final Collection deletedFiles = new ArrayList<>(); private final Collection createdDirectories = new ArrayList<>(); private final Collection changedDirectories = new ArrayList<>(); private final Collection deletedDirectories = new ArrayList<>(); /** * Create a new observer. * * @param clearOnStart true if clear() should be called by onStart(). */ public CollectionFileListener(final boolean clearOnStart) { this.clearOnStart = clearOnStart; } /** * File system observer started checking event. * * @param observer The file system observer */ @Override public void onStart(final FileAlterationObserver observer) { if (clearOnStart) { clear(); } } /** * Clear file collections. */ public void clear() { createdFiles.clear(); changedFiles.clear(); deletedFiles.clear(); createdDirectories.clear(); changedDirectories.clear(); deletedDirectories.clear(); } /** * Return the set of changed directories. * * @return Directories which have changed */ public Collection getChangedDirectories() { return changedDirectories; } /** * Return the set of changed files. * * @return Files which have changed */ public Collection getChangedFiles() { return changedFiles; } /** * Return the set of created directories. * * @return Directories which have been created */ public Collection getCreatedDirectories() { return createdDirectories; } /** * Return the set of created files. * * @return Files which have been created */ public Collection getCreatedFiles() { return createdFiles; } /** * Return the set of deleted directories. * * @return Directories which been deleted */ public Collection getDeletedDirectories() { return deletedDirectories; } /** * Return the set of deleted files. * * @return Files which been deleted */ public Collection getDeletedFiles() { return deletedFiles; } /** * Directory created Event. * * @param directory The directory created */ @Override public void onDirectoryCreate(final File directory) { createdDirectories.add(directory); } /** * Directory changed Event. * * @param directory The directory changed */ @Override public void onDirectoryChange(final File directory) { changedDirectories.add(directory); } /** * Directory deleted Event. * * @param directory The directory deleted */ @Override public void onDirectoryDelete(final File directory) { deletedDirectories.add(directory); } /** * File created Event. * * @param file The file created */ @Override public void onFileCreate(final File file) { createdFiles.add(file); } /** * File changed Event. * * @param file The file changed */ @Override public void onFileChange(final File file) { changedFiles.add(file); } /** * File deleted Event. * * @param file The file deleted */ @Override public void onFileDelete(final File file) { deletedFiles.add(file); } /** * File system observer finished checking event. * * @param observer The file system observer */ @Override public void onStop(final FileAlterationObserver observer) { // noop } } ././@LongLink0100644 0000000 0000000 00000000145 13612062727 011641 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/java/org/apache/commons/io/monitor/FileAlterationMonitorTestCase.javacommons-io-2.11.0-src/src/test/java/org/apache/commons/io/monitor/FileAlterationMonitorTestCase.java0100644 0000000 0000000 00000020356 13612062727 034034 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.monitor; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Iterator; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; import org.apache.commons.io.test.TestUtils; import org.junit.jupiter.api.Test; /** * {@link FileAlterationMonitor} Test Case. */ public class FileAlterationMonitorTestCase extends AbstractMonitorTestCase { /** * Construct a new test case. * */ public FileAlterationMonitorTestCase() { listener = new CollectionFileListener(false); } /** * Test default constructor. */ @Test public void testDefaultConstructor() { final FileAlterationMonitor monitor = new FileAlterationMonitor(); assertEquals(10000, monitor.getInterval(), "Interval"); } @Test public void testCollectionConstructorShouldDoNothingWithNullCollection() { final Collection observers = null; final FileAlterationMonitor monitor = new FileAlterationMonitor(0, observers); assertFalse(monitor.getObservers().iterator().hasNext()); } @Test public void testCollectionConstructorShouldDoNothingWithNullObservers() { final Collection observers = new ArrayList<>(5); final FileAlterationMonitor monitor = new FileAlterationMonitor(0, observers); assertFalse(monitor.getObservers().iterator().hasNext()); } @Test public void testCollectionConstructor() { observer = new FileAlterationObserver("foo"); final Collection observers = Arrays.asList(observer); final FileAlterationMonitor monitor = new FileAlterationMonitor(0, observers); final Iterator iterator = monitor.getObservers().iterator(); assertEquals(observer, iterator.next()); } /** * Test add/remove observers. */ @Test public void testAddRemoveObservers() { FileAlterationObserver[] observers = null; // Null Observers FileAlterationMonitor monitor = new FileAlterationMonitor(123, observers); assertEquals(123, monitor.getInterval(), "Interval"); assertFalse(monitor.getObservers().iterator().hasNext(), "Observers[1]"); // Null Observer observers = new FileAlterationObserver[1]; // observer is null monitor = new FileAlterationMonitor(456, observers); assertFalse(monitor.getObservers().iterator().hasNext(), "Observers[2]"); // Null Observer monitor.addObserver(null); assertFalse(monitor.getObservers().iterator().hasNext(), "Observers[3]"); monitor.removeObserver(null); // Add Observer final FileAlterationObserver observer = new FileAlterationObserver("foo"); monitor.addObserver(observer); final Iterator it = monitor.getObservers().iterator(); assertTrue(it.hasNext(), "Observers[4]"); assertEquals(observer, it.next(), "Added"); assertFalse(it.hasNext(), "Observers[5]"); // Remove Observer monitor.removeObserver(observer); assertFalse(monitor.getObservers().iterator().hasNext(), "Observers[6]"); } /** * Test checkAndNotify() method * @throws Exception */ @Test public void testMonitor() throws Exception { final long interval = 100; listener.clear(); final FileAlterationMonitor monitor = new FileAlterationMonitor(interval, observer); assertEquals(interval, monitor.getInterval(), "Interval"); monitor.start(); try { monitor.start(); // try and start again fail("Expected IllegalStateException"); } catch (final IllegalStateException e) { // expected result, monitor already running } // Create a File checkCollectionsEmpty("A"); File file1 = touch(new File(testDir, "file1.java")); checkFile("Create", file1, listener.getCreatedFiles()); listener.clear(); // Update a file checkCollectionsEmpty("B"); file1 = touch(file1); checkFile("Update", file1, listener.getChangedFiles()); listener.clear(); // Delete a file checkCollectionsEmpty("C"); file1.delete(); checkFile("Delete", file1, listener.getDeletedFiles()); listener.clear(); // Stop monitoring monitor.stop(); try { monitor.stop(); // try and stop again fail("Expected IllegalStateException"); } catch (final IllegalStateException e) { // expected result, monitor already stopped } } /** * Test using a thread factory. * @throws Exception */ @Test public void testThreadFactory() throws Exception { final long interval = 100; listener.clear(); final FileAlterationMonitor monitor = new FileAlterationMonitor(interval, observer); monitor.setThreadFactory(Executors.defaultThreadFactory()); assertEquals(interval, monitor.getInterval(), "Interval"); monitor.start(); // Create a File checkCollectionsEmpty("A"); final File file2 = touch(new File(testDir, "file2.java")); checkFile("Create", file2, listener.getCreatedFiles()); listener.clear(); // Delete a file checkCollectionsEmpty("B"); file2.delete(); checkFile("Delete", file2, listener.getDeletedFiles()); listener.clear(); // Stop monitoring monitor.stop(); } /** * Check all the File Collections have the expected sizes. */ private void checkFile(final String label, final File file, final Collection files) { for (int i = 0; i < 20; i++) { if (files.contains(file)) { return; // found, test passes } TestUtils.sleepQuietly(pauseTime); } fail(label + " " + file + " not found"); } /** * Test case for IO-535 * * Verify that {@link FileAlterationMonitor#stop()} stops the created thread */ @Test public void testStopWhileWaitingForNextInterval() throws Exception { final Collection createdThreads = new ArrayList<>(1); final ThreadFactory threadFactory = new ThreadFactory() { private final ThreadFactory delegate = Executors.defaultThreadFactory(); @Override public Thread newThread(final Runnable r) { final Thread thread = delegate.newThread(r); thread.setDaemon(true); //do not leak threads if the test fails createdThreads.add(thread); return thread; } }; final FileAlterationMonitor monitor = new FileAlterationMonitor(1_000); monitor.setThreadFactory(threadFactory); monitor.start(); assertFalse(createdThreads.isEmpty()); Thread.sleep(10); // wait until the watcher thread enters Thread.sleep() monitor.stop(100); for (final Thread thread : createdThreads) { assertFalse(thread.isAlive(), "The FileAlterationMonitor did not stop the threads it created."); } } } ././@LongLink0100644 0000000 0000000 00000000146 13612062727 011642 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/java/org/apache/commons/io/monitor/FileAlterationObserverTestCase.javacommons-io-2.11.0-src/src/test/java/org/apache/commons/io/monitor/FileAlterationObserverTestCase.jav0100644 0000000 0000000 00000041466 13612062727 034040 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.monitor; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.File; import java.io.FileFilter; import java.io.IOException; import java.util.Iterator; import org.apache.commons.io.FileUtils; import org.apache.commons.io.filefilter.CanReadFileFilter; import org.apache.commons.io.filefilter.FileFilterUtils; import org.junit.jupiter.api.Test; /** * {@link FileAlterationObserver} Test Case. */ public class FileAlterationObserverTestCase extends AbstractMonitorTestCase { /** * Construct a new test case. * */ public FileAlterationObserverTestCase() { listener = new CollectionFileListener(true); } /** * Test add/remove listeners. */ @Test public void testAddRemoveListeners() { final FileAlterationObserver observer = new FileAlterationObserver("/foo"); // Null Listener observer.addListener(null); assertFalse(observer.getListeners().iterator().hasNext(), "Listeners[1]"); observer.removeListener(null); assertFalse(observer.getListeners().iterator().hasNext(), "Listeners[2]"); // Add Listener final FileAlterationListenerAdaptor listener = new FileAlterationListenerAdaptor(); observer.addListener(listener); final Iterator it = observer.getListeners().iterator(); assertTrue(it.hasNext(), "Listeners[3]"); assertEquals(listener, it.next(), "Added"); assertFalse(it.hasNext(), "Listeners[4]"); // Remove Listener observer.removeListener(listener); assertFalse(observer.getListeners().iterator().hasNext(), "Listeners[5]"); } /** * Test toString(). */ @Test public void testToString() { final File file = new File("/foo"); FileAlterationObserver observer = new FileAlterationObserver(file); assertEquals("FileAlterationObserver[file='" + file.getPath() + "', listeners=0]", observer.toString()); observer = new FileAlterationObserver(file, CanReadFileFilter.CAN_READ); assertEquals("FileAlterationObserver[file='" + file.getPath() + "', CanReadFileFilter, listeners=0]", observer.toString()); assertEquals(file, observer.getDirectory()); } /** * Test checkAndNotify() method * @throws Exception */ @Test public void testDirectory() throws Exception { checkAndNotify(); checkCollectionsEmpty("A"); final File testDirA = new File(testDir, "test-dir-A"); final File testDirB = new File(testDir, "test-dir-B"); final File testDirC = new File(testDir, "test-dir-C"); testDirA.mkdir(); testDirB.mkdir(); testDirC.mkdir(); final File testDirAFile1 = touch(new File(testDirA, "A-file1.java")); final File testDirAFile2 = touch(new File(testDirA, "A-file2.txt")); // filter should ignore this final File testDirAFile3 = touch(new File(testDirA, "A-file3.java")); File testDirAFile4 = touch(new File(testDirA, "A-file4.java")); final File testDirBFile1 = touch(new File(testDirB, "B-file1.java")); checkAndNotify(); checkCollectionSizes("B", 3, 0, 0, 4, 0, 0); assertTrue(listener.getCreatedDirectories().contains(testDirA), "B testDirA"); assertTrue(listener.getCreatedDirectories().contains(testDirB), "B testDirB"); assertTrue(listener.getCreatedDirectories().contains(testDirC), "B testDirC"); assertTrue(listener.getCreatedFiles().contains(testDirAFile1), "B testDirAFile1"); assertFalse(listener.getCreatedFiles().contains(testDirAFile2), "B testDirAFile2"); assertTrue(listener.getCreatedFiles().contains(testDirAFile3), "B testDirAFile3"); assertTrue(listener.getCreatedFiles().contains(testDirAFile4), "B testDirAFile4"); assertTrue(listener.getCreatedFiles().contains(testDirBFile1), "B testDirBFile1"); checkAndNotify(); checkCollectionsEmpty("C"); testDirAFile4 = touch(testDirAFile4); FileUtils.deleteDirectory(testDirB); checkAndNotify(); checkCollectionSizes("D", 0, 0, 1, 0, 1, 1); assertTrue(listener.getDeletedDirectories().contains(testDirB), "D testDirB"); assertTrue(listener.getChangedFiles().contains(testDirAFile4), "D testDirAFile4"); assertTrue(listener.getDeletedFiles().contains(testDirBFile1), "D testDirBFile1"); FileUtils.deleteDirectory(testDir); checkAndNotify(); checkCollectionSizes("E", 0, 0, 2, 0, 0, 3); assertTrue(listener.getDeletedDirectories().contains(testDirA), "E testDirA"); assertTrue(listener.getDeletedFiles().contains(testDirAFile1), "E testDirAFile1"); assertFalse(listener.getDeletedFiles().contains(testDirAFile2), "E testDirAFile2"); assertTrue(listener.getDeletedFiles().contains(testDirAFile3), "E testDirAFile3"); assertTrue(listener.getDeletedFiles().contains(testDirAFile4), "E testDirAFile4"); testDir.mkdir(); checkAndNotify(); checkCollectionsEmpty("F"); checkAndNotify(); checkCollectionsEmpty("G"); } /** * Test checkAndNotify() creating * @throws IOException if an I/O error occurs. */ @Test public void testFileCreate() throws IOException { checkAndNotify(); checkCollectionsEmpty("A"); File testDirA = new File(testDir, "test-dir-A"); testDirA.mkdir(); testDir = touch(testDir); testDirA = touch(testDirA); File testDirAFile1 = new File(testDirA, "A-file1.java"); final File testDirAFile2 = touch(new File(testDirA, "A-file2.java")); File testDirAFile3 = new File(testDirA, "A-file3.java"); final File testDirAFile4 = touch(new File(testDirA, "A-file4.java")); File testDirAFile5 = new File(testDirA, "A-file5.java"); checkAndNotify(); checkCollectionSizes("B", 1, 0, 0, 2, 0, 0); assertFalse(listener.getCreatedFiles().contains(testDirAFile1), "B testDirAFile1"); assertTrue(listener.getCreatedFiles().contains(testDirAFile2), "B testDirAFile2"); assertFalse(listener.getCreatedFiles().contains(testDirAFile3), "B testDirAFile3"); assertTrue(listener.getCreatedFiles().contains(testDirAFile4), "B testDirAFile4"); assertFalse(listener.getCreatedFiles().contains(testDirAFile5), "B testDirAFile5"); assertFalse(testDirAFile1.exists(), "B testDirAFile1 exists"); assertTrue(testDirAFile2.exists(), "B testDirAFile2 exists"); assertFalse(testDirAFile3.exists(), "B testDirAFile3 exists"); assertTrue(testDirAFile4.exists(), "B testDirAFile4 exists"); assertFalse(testDirAFile5.exists(), "B testDirAFile5 exists"); checkAndNotify(); checkCollectionsEmpty("C"); // Create file with name < first entry testDirAFile1 = touch(testDirAFile1); testDirA = touch(testDirA); checkAndNotify(); checkCollectionSizes("D", 0, 1, 0, 1, 0, 0); assertTrue(testDirAFile1.exists(), "D testDirAFile1 exists"); assertTrue(listener.getCreatedFiles().contains(testDirAFile1), "D testDirAFile1"); // Create file with name between 2 entries testDirAFile3 = touch(testDirAFile3); testDirA = touch(testDirA); checkAndNotify(); checkCollectionSizes("E", 0, 1, 0, 1, 0, 0); assertTrue(testDirAFile3.exists(), "E testDirAFile3 exists"); assertTrue(listener.getCreatedFiles().contains(testDirAFile3), "E testDirAFile3"); // Create file with name > last entry testDirAFile5 = touch(testDirAFile5); testDirA = touch(testDirA); checkAndNotify(); checkCollectionSizes("F", 0, 1, 0, 1, 0, 0); assertTrue(testDirAFile5.exists(), "F testDirAFile5 exists"); assertTrue(listener.getCreatedFiles().contains(testDirAFile5), "F testDirAFile5"); } /** * Test checkAndNotify() creating * @throws IOException if an I/O error occurs. */ @Test public void testFileUpdate() throws IOException { checkAndNotify(); checkCollectionsEmpty("A"); File testDirA = new File(testDir, "test-dir-A"); testDirA.mkdir(); testDir = touch(testDir); testDirA = touch(testDirA); File testDirAFile1 = touch(new File(testDirA, "A-file1.java")); final File testDirAFile2 = touch(new File(testDirA, "A-file2.java")); File testDirAFile3 = touch(new File(testDirA, "A-file3.java")); final File testDirAFile4 = touch(new File(testDirA, "A-file4.java")); File testDirAFile5 = touch(new File(testDirA, "A-file5.java")); checkAndNotify(); checkCollectionSizes("B", 1, 0, 0, 5, 0, 0); assertTrue(listener.getCreatedFiles().contains(testDirAFile1), "B testDirAFile1"); assertTrue(listener.getCreatedFiles().contains(testDirAFile2), "B testDirAFile2"); assertTrue(listener.getCreatedFiles().contains(testDirAFile3), "B testDirAFile3"); assertTrue(listener.getCreatedFiles().contains(testDirAFile4), "B testDirAFile4"); assertTrue(listener.getCreatedFiles().contains(testDirAFile5), "B testDirAFile5"); assertTrue(testDirAFile1.exists(), "B testDirAFile1 exists"); assertTrue(testDirAFile2.exists(), "B testDirAFile2 exists"); assertTrue(testDirAFile3.exists(), "B testDirAFile3 exists"); assertTrue(testDirAFile4.exists(), "B testDirAFile4 exists"); assertTrue(testDirAFile5.exists(), "B testDirAFile5 exists"); checkAndNotify(); checkCollectionsEmpty("C"); // Update first entry testDirAFile1 = touch(testDirAFile1); testDirA = touch(testDirA); checkAndNotify(); checkCollectionSizes("D", 0, 1, 0, 0, 1, 0); assertTrue(listener.getChangedFiles().contains(testDirAFile1), "D testDirAFile1"); // Update file with name between 2 entries testDirAFile3 = touch(testDirAFile3); testDirA = touch(testDirA); checkAndNotify(); checkCollectionSizes("E", 0, 1, 0, 0, 1, 0); assertTrue(listener.getChangedFiles().contains(testDirAFile3), "E testDirAFile3"); // Update last entry testDirAFile5 = touch(testDirAFile5); testDirA = touch(testDirA); checkAndNotify(); checkCollectionSizes("F", 0, 1, 0, 0, 1, 0); assertTrue(listener.getChangedFiles().contains(testDirAFile5), "F testDirAFile5"); } /** * Test checkAndNotify() deleting * @throws IOException if an I/O error occurs. */ @Test public void testFileDelete() throws IOException { checkAndNotify(); checkCollectionsEmpty("A"); File testDirA = new File(testDir, "test-dir-A"); testDirA.mkdir(); testDir = touch(testDir); testDirA = touch(testDirA); final File testDirAFile1 = touch(new File(testDirA, "A-file1.java")); final File testDirAFile2 = touch(new File(testDirA, "A-file2.java")); final File testDirAFile3 = touch(new File(testDirA, "A-file3.java")); final File testDirAFile4 = touch(new File(testDirA, "A-file4.java")); final File testDirAFile5 = touch(new File(testDirA, "A-file5.java")); assertTrue(testDirAFile1.exists(), "B testDirAFile1 exists"); assertTrue(testDirAFile2.exists(), "B testDirAFile2 exists"); assertTrue(testDirAFile3.exists(), "B testDirAFile3 exists"); assertTrue(testDirAFile4.exists(), "B testDirAFile4 exists"); assertTrue(testDirAFile5.exists(), "B testDirAFile5 exists"); checkAndNotify(); checkCollectionSizes("B", 1, 0, 0, 5, 0, 0); assertTrue(listener.getCreatedFiles().contains(testDirAFile1), "B testDirAFile1"); assertTrue(listener.getCreatedFiles().contains(testDirAFile2), "B testDirAFile2"); assertTrue(listener.getCreatedFiles().contains(testDirAFile3), "B testDirAFile3"); assertTrue(listener.getCreatedFiles().contains(testDirAFile4), "B testDirAFile4"); assertTrue(listener.getCreatedFiles().contains(testDirAFile5), "B testDirAFile5"); checkAndNotify(); checkCollectionsEmpty("C"); // Delete first entry FileUtils.deleteQuietly(testDirAFile1); testDirA = touch(testDirA); checkAndNotify(); checkCollectionSizes("D", 0, 1, 0, 0, 0, 1); assertFalse(testDirAFile1.exists(), "D testDirAFile1 exists"); assertTrue(listener.getDeletedFiles().contains(testDirAFile1), "D testDirAFile1"); // Delete file with name between 2 entries FileUtils.deleteQuietly(testDirAFile3); testDirA = touch(testDirA); checkAndNotify(); checkCollectionSizes("E", 0, 1, 0, 0, 0, 1); assertFalse(testDirAFile3.exists(), "E testDirAFile3 exists"); assertTrue(listener.getDeletedFiles().contains(testDirAFile3), "E testDirAFile3"); // Delete last entry FileUtils.deleteQuietly(testDirAFile5); testDirA = touch(testDirA); checkAndNotify(); checkCollectionSizes("F", 0, 1, 0, 0, 0, 1); assertFalse(testDirAFile5.exists(), "F testDirAFile5 exists"); assertTrue(listener.getDeletedFiles().contains(testDirAFile5), "F testDirAFile5"); } /** * Test checkAndNotify() method * @throws IOException if an I/O error occurs. */ @Test public void testObserveSingleFile() throws IOException { final File testDirA = new File(testDir, "test-dir-A"); File testDirAFile1 = new File(testDirA, "A-file1.java"); testDirA.mkdir(); final FileFilter nameFilter = FileFilterUtils.nameFileFilter(testDirAFile1.getName()); createObserver(testDirA, nameFilter); checkAndNotify(); checkCollectionsEmpty("A"); assertFalse(testDirAFile1.exists(), "A testDirAFile1 exists"); // Create testDirAFile1 = touch(testDirAFile1); File testDirAFile2 = touch(new File(testDirA, "A-file2.txt")); /* filter should ignore */ File testDirAFile3 = touch(new File(testDirA, "A-file3.java")); /* filter should ignore */ assertTrue(testDirAFile1.exists(), "B testDirAFile1 exists"); assertTrue(testDirAFile2.exists(), "B testDirAFile2 exists"); assertTrue(testDirAFile3.exists(), "B testDirAFile3 exists"); checkAndNotify(); checkCollectionSizes("C", 0, 0, 0, 1, 0, 0); assertTrue(listener.getCreatedFiles().contains(testDirAFile1), "C created"); assertFalse(listener.getCreatedFiles().contains(testDirAFile2), "C created"); assertFalse(listener.getCreatedFiles().contains(testDirAFile3), "C created"); // Modify testDirAFile1 = touch(testDirAFile1); testDirAFile2 = touch(testDirAFile2); testDirAFile3 = touch(testDirAFile3); checkAndNotify(); checkCollectionSizes("D", 0, 0, 0, 0, 1, 0); assertTrue(listener.getChangedFiles().contains(testDirAFile1), "D changed"); assertFalse(listener.getChangedFiles().contains(testDirAFile2), "D changed"); assertFalse(listener.getChangedFiles().contains(testDirAFile3), "D changed"); // Delete FileUtils.deleteQuietly(testDirAFile1); FileUtils.deleteQuietly(testDirAFile2); FileUtils.deleteQuietly(testDirAFile3); assertFalse(testDirAFile1.exists(), "E testDirAFile1 exists"); assertFalse(testDirAFile2.exists(), "E testDirAFile2 exists"); assertFalse(testDirAFile3.exists(), "E testDirAFile3 exists"); checkAndNotify(); checkCollectionSizes("E", 0, 0, 0, 0, 0, 1); assertTrue(listener.getDeletedFiles().contains(testDirAFile1), "E deleted"); assertFalse(listener.getDeletedFiles().contains(testDirAFile2), "E deleted"); assertFalse(listener.getDeletedFiles().contains(testDirAFile3), "E deleted"); } /** * Call {@link FileAlterationObserver#checkAndNotify()}. */ protected void checkAndNotify() { observer.checkAndNotify(); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/output/AppendableOutputStreamTest.java0100644 0000000 0000000 00000003136 13612062727 033264 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Unit tests for {@link AppendableOutputStream}. * */ public class AppendableOutputStreamTest { private AppendableOutputStream out; @BeforeEach public void setUp() { out = new AppendableOutputStream<>(new StringBuilder()); } @Test public void testWriteStringBuilder() throws Exception { final String testData = "ABCD"; out.write(testData.getBytes()); assertEquals(testData, out.getAppendable().toString()); } @Test public void testWriteInt() throws Exception { out.write('F'); assertEquals("F", out.getAppendable().toString()); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/output/AppendableWriterTest.java0100644 0000000 0000000 00000004661 13612062727 032070 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Unit tests for {@link AppendableWriter}. * */ public class AppendableWriterTest { private AppendableWriter out; @BeforeEach public void setUp() { out = new AppendableWriter<>(new StringBuilder()); } @Test public void testWriteInt() throws Exception { out.write('F'); assertEquals("F", out.getAppendable().toString()); } @Test public void testWriteChars() throws Exception { final String testData = "ABCD"; out.write(testData.toCharArray()); assertEquals(testData, out.getAppendable().toString()); } @Test public void testWriteString() throws Exception { final String testData = "ABCD"; out.write(testData); assertEquals(testData, out.getAppendable().toString()); } @Test public void testAppendCharSequence() throws Exception { final String testData = "ABCD"; out.append(testData); out.append(null); assertEquals(testData + "null", out.getAppendable().toString()); } @Test public void testAppendSubSequence() throws Exception { final String testData = "ABCD"; out.append(testData, 1, 3); out.append(null, 1, 3); assertEquals(testData.substring(1, 3) + "ul", out.getAppendable().toString()); } @Test public void testAppendChar() throws Exception { out.append('F'); assertEquals("F", out.getAppendable().toString()); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/output/BrokenOutputStreamTest.java0100644 0000000 0000000 00000004716 13612062727 032456 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; import java.io.IOException; import java.io.OutputStream; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * JUnit Test Case for {@link BrokenOutputStream}. */ public class BrokenOutputStreamTest { private IOException exception; private OutputStream stream; @BeforeEach public void setUp() { exception = new IOException("test exception"); stream = new BrokenOutputStream(exception); } @Test public void testWrite() { try { stream.write(1); fail("Expected exception not thrown."); } catch (final IOException e) { assertEquals(exception, e); } try { stream.write(new byte[1]); fail("Expected exception not thrown."); } catch (final IOException e) { assertEquals(exception, e); } try { stream.write(new byte[1], 0, 1); fail("Expected exception not thrown."); } catch (final IOException e) { assertEquals(exception, e); } } @Test public void testFlush() { try { stream.flush(); fail("Expected exception not thrown."); } catch (final IOException e) { assertEquals(exception, e); } } @Test public void testClose() { try { stream.close(); fail("Expected exception not thrown."); } catch (final IOException e) { assertEquals(exception, e); } } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/output/BrokenWriterTest.java0100644 0000000 0000000 00000004660 13612062727 031254 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; import java.io.IOException; import java.io.Writer; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * JUnit Test Case for {@link BrokenWriter}. */ public class BrokenWriterTest { private IOException exception; private Writer writer; @BeforeEach public void setUp() { exception = new IOException("test exception"); writer = new BrokenWriter(exception); } @Test public void testWrite() { try { writer.write(1); fail("Expected exception not thrown."); } catch (final IOException e) { assertEquals(exception, e); } try { writer.write(new char[1]); fail("Expected exception not thrown."); } catch (final IOException e) { assertEquals(exception, e); } try { writer.write(new char[1], 0, 1); fail("Expected exception not thrown."); } catch (final IOException e) { assertEquals(exception, e); } } @Test public void testFlush() { try { writer.flush(); fail("Expected exception not thrown."); } catch (final IOException e) { assertEquals(exception, e); } } @Test public void testClose() { try { writer.close(); fail("Expected exception not thrown."); } catch (final IOException e) { assertEquals(exception, e); } } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/output/ByteArrayOutputStreamTestCase.java0100644 0000000 0000000 00000040135 13612062727 033727 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.util.stream.Stream; import org.apache.commons.io.IOUtils; import org.apache.commons.io.function.IOFunction; import org.apache.commons.io.input.ClosedInputStream; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; /** * Basic unit tests for the alternative ByteArrayOutputStream implementations. */ public class ByteArrayOutputStreamTestCase { private static final byte[] DATA; static { DATA = new byte[64]; for (byte i = 0; i < 64; i++) { DATA[i] = i; } } private int writeData(final AbstractByteArrayOutputStream baout, final java.io.ByteArrayOutputStream ref, final int count) { if (count > DATA.length) { throw new IllegalArgumentException("Requesting too many bytes"); } if (count == 0) { baout.write(100); ref.write(100); return 1; } baout.write(DATA, 0, count); ref.write(DATA, 0, count); return count; } private int writeData(final AbstractByteArrayOutputStream baout, final java.io.ByteArrayOutputStream ref, final int[] instructions) { int written = 0; for (final int instruction : instructions) { written += writeData(baout, ref, instruction); } return written; } private static boolean byteCmp(final byte[] src, final byte[] cmp) { for (int i = 0; i < cmp.length; i++) { if (src[i] != cmp[i]) { return false; } } return true; } private void checkByteArrays(final byte[] expected, final byte[] actual) { if (expected.length != actual.length) { fail("Resulting byte arrays are not equally long"); } if (!byteCmp(expected, actual)) { fail("Resulting byte arrays are not equal"); } } private void checkStreams( final AbstractByteArrayOutputStream actual, final java.io.ByteArrayOutputStream expected) { assertEquals(expected.size(), actual.size(), "Sizes are not equal"); final byte[] buf = actual.toByteArray(); final byte[] refbuf = expected.toByteArray(); checkByteArrays(buf, refbuf); } @ParameterizedTest(name = "[{index}] {0}") @MethodSource("baosFactories") public void testWriteZero(final String baosName, final BAOSFactory baosFactory) throws IOException { try (final AbstractByteArrayOutputStream baout = baosFactory.newInstance()) { baout.write(IOUtils.EMPTY_BYTE_ARRAY, 0, 0); assertTrue(true, "Dummy"); } } @ParameterizedTest(name = "[{index}] {0}") @MethodSource("baosFactories") public void testInvalidWriteOffsetUnder(final String baosName, final BAOSFactory baosFactory) throws IOException { try (final AbstractByteArrayOutputStream baout = baosFactory.newInstance()) { assertThrows(IndexOutOfBoundsException.class, () -> baout.write(null, -1, 0)); } } @ParameterizedTest(name = "[{index}] {0}") @MethodSource("baosFactories") public void testInvalidWriteOffsetOver(final String baosName, final BAOSFactory baosFactory) throws IOException { try (final AbstractByteArrayOutputStream baout = baosFactory.newInstance()) { assertThrows(IndexOutOfBoundsException.class, () -> baout.write(IOUtils.EMPTY_BYTE_ARRAY, 1, 0)); } } @ParameterizedTest(name = "[{index}] {0}") @MethodSource("baosFactories") public void testInvalidWriteLenUnder(final String baosName, final BAOSFactory baosFactory) throws IOException { try (final AbstractByteArrayOutputStream baout = baosFactory.newInstance()) { assertThrows(IndexOutOfBoundsException.class, () -> baout.write(new byte[1], 0, -1)); } } @ParameterizedTest(name = "[{index}] {0}") @MethodSource("baosFactories") public void testInvalidWriteOffsetAndLenUnder(final String baosName, final BAOSFactory baosFactory) throws IOException { try (final AbstractByteArrayOutputStream baout = baosFactory.newInstance()) { assertThrows(IndexOutOfBoundsException.class, () -> baout.write(new byte[1], 1, -2)); } } @ParameterizedTest(name = "[{index}] {0}") @MethodSource("baosFactories") public void testInvalidWriteOffsetAndLenOver(final String baosName, final BAOSFactory baosFactory) throws IOException { try (final AbstractByteArrayOutputStream baout = baosFactory.newInstance()) { assertThrows(IndexOutOfBoundsException.class, () -> baout.write(new byte[1], 0, 2)); } } @ParameterizedTest(name = "[{index}] {0}") @MethodSource("baosFactories") public void testInvalidParameterizedConstruction(final String baosName, final BAOSFactory baosFactory) { assertThrows(IllegalArgumentException.class, () -> baosFactory.newInstance(-1) ); } @ParameterizedTest(name = "[{index}] {0}") @MethodSource("baosFactories") public void testToInputStreamEmpty(final String baosName, final BAOSFactory baosFactory) throws IOException { try (final AbstractByteArrayOutputStream baout = baosFactory.newInstance(); // Get data before more writes final InputStream in = baout.toInputStream()) { assertEquals(0, in.available()); assertTrue(in instanceof ClosedInputStream); } } @ParameterizedTest(name = "[{index}] {0}") @MethodSource("toBufferedInputStreamFunctionFactories") public void testToBufferedInputStreamEmpty(final String baosName, final IOFunction toBufferedInputStreamFunction) throws IOException { try (final ByteArrayInputStream bain = new ByteArrayInputStream(IOUtils.EMPTY_BYTE_ARRAY)) { assertEquals(0, bain.available()); try (final InputStream buffered = toBufferedInputStreamFunction.apply(bain)) { assertEquals(0, buffered.available()); } } } @ParameterizedTest(name = "[{index}] {0}") @MethodSource("toBufferedInputStreamFunctionFactories") public void testToBufferedInputStream(final String baosName, final IOFunction toBufferedInputStreamFunction) throws IOException { final byte data[] = {(byte)0xCA, (byte)0xFE, (byte)0xBA, (byte)0xBE}; try (final ByteArrayInputStream bain = new ByteArrayInputStream(data)) { assertEquals(data.length, bain.available()); try (final InputStream buffered = toBufferedInputStreamFunction.apply(bain)) { assertEquals(data.length, buffered.available()); assertArrayEquals(data, IOUtils.toByteArray(buffered)); } } } @ParameterizedTest(name = "[{index}] {0}") @MethodSource("baosFactories") public void testToInputStream(final String baosName, final BAOSFactory baosFactory) throws IOException { try (final AbstractByteArrayOutputStream baout = baosFactory.newInstance(); final java.io.ByteArrayOutputStream ref = new java.io.ByteArrayOutputStream()) { // Write 8224 bytes writeData(baout, ref, 32); for (int i = 0; i < 128; i++) { writeData(baout, ref, 64); } // Get data before more writes try (final InputStream in = baout.toInputStream()) { byte refData[] = ref.toByteArray(); // Write some more data writeData(baout, ref, new int[] {2, 4, 8, 16}); // Check original data byte baoutData[] = IOUtils.toByteArray(in); assertEquals(8224, baoutData.length); checkByteArrays(refData, baoutData); // Check all data written try (final InputStream in2 = baout.toInputStream()) { baoutData = IOUtils.toByteArray(in2); } refData = ref.toByteArray(); assertEquals(8254, baoutData.length); checkByteArrays(refData, baoutData); } } } @ParameterizedTest(name = "[{index}] {0}") @MethodSource("baosFactories") public void testToInputStreamWithReset(final String baosName, final BAOSFactory baosFactory) throws IOException { // Make sure reset() do not destroy InputStream returned from toInputStream() try (final AbstractByteArrayOutputStream baout = baosFactory.newInstance(); final java.io.ByteArrayOutputStream ref = new java.io.ByteArrayOutputStream()) { // Write 8224 bytes writeData(baout, ref, 32); for (int i = 0; i < 128; i++) { writeData(baout, ref, 64); } // Get data before reset try (final InputStream in = baout.toInputStream()) { byte refData[] = ref.toByteArray(); // Reset and write some new data baout.reset(); ref.reset(); writeData(baout, ref, new int[] {2, 4, 8, 16}); // Check original data byte baoutData[] = IOUtils.toByteArray(in); assertEquals(8224, baoutData.length); checkByteArrays(refData, baoutData); // Check new data written after reset try (final InputStream in2 = baout.toInputStream()) { baoutData = IOUtils.toByteArray(in2); } refData = ref.toByteArray(); assertEquals(30, baoutData.length); checkByteArrays(refData, baoutData); } } } @ParameterizedTest(name = "[{index}] {0}") @MethodSource("baosFactories") public void testStream(final String baosName, final BAOSFactory baosFactory) throws Exception { int written; // The ByteArrayOutputStream is initialized with 32 bytes to match // the original more closely for this test. try (final AbstractByteArrayOutputStream baout = baosFactory.newInstance(32); final java.io.ByteArrayOutputStream ref = new java.io.ByteArrayOutputStream()) { // First three writes written = writeData(baout, ref, new int[] {4, 10, 22}); assertEquals(36, written); checkStreams(baout, ref); // Another two writes to see if there are any bad effects after toByteArray() written = writeData(baout, ref, new int[] {20, 12}); assertEquals(32, written); checkStreams(baout, ref); // Now reset the streams baout.reset(); ref.reset(); // Test again to see if reset() had any bad effects written = writeData(baout, ref, new int[] {5, 47, 33, 60, 1, 0, 8}); assertEquals(155, written); checkStreams(baout, ref); // Test the readFrom(InputStream) method baout.reset(); written = baout.write(new ByteArrayInputStream(ref.toByteArray())); assertEquals(155, written); checkStreams(baout, ref); // Write the commons Byte[]OutputStream to a java.io.Byte[]OutputStream // and vice-versa to test the writeTo() method. try (final AbstractByteArrayOutputStream baout1 = baosFactory.newInstance(32)) { ref.writeTo(baout1); final java.io.ByteArrayOutputStream ref1 = new java.io.ByteArrayOutputStream(); baout.writeTo(ref1); checkStreams(baout1, ref1); // Testing toString(String) final String baoutString = baout.toString("ASCII"); final String refString = ref.toString("ASCII"); assertEquals(refString, baoutString, "ASCII decoded String must be equal"); // Make sure that empty ByteArrayOutputStreams really don't create garbage // on toByteArray() try (final AbstractByteArrayOutputStream baos1 = baosFactory.newInstance(); final AbstractByteArrayOutputStream baos2 = baosFactory.newInstance()) { assertSame(baos1.toByteArray(), baos2.toByteArray()); } } } } private static Stream baosFactories() { return Stream.of( Arguments.of(ByteArrayOutputStream.class.getSimpleName(), new ByteArrayOutputStreamFactory()), Arguments.of(UnsynchronizedByteArrayOutputStream.class.getSimpleName(), new UnsynchronizedByteArrayOutputStreamFactory()) ); } private static class ByteArrayOutputStreamFactory implements BAOSFactory { @Override public ByteArrayOutputStream newInstance() { return new ByteArrayOutputStream(); } @Override public ByteArrayOutputStream newInstance(final int size) { return new ByteArrayOutputStream(size); } } private static class UnsynchronizedByteArrayOutputStreamFactory implements BAOSFactory { @Override public UnsynchronizedByteArrayOutputStream newInstance() { return new UnsynchronizedByteArrayOutputStream(); } @Override public UnsynchronizedByteArrayOutputStream newInstance(final int size) { return new UnsynchronizedByteArrayOutputStream(size); } } private interface BAOSFactory { T newInstance(); T newInstance(final int size); } private static Stream toBufferedInputStreamFunctionFactories() { final IOFunction syncBaosToBufferedInputStream = ByteArrayOutputStream::toBufferedInputStream; final IOFunction syncBaosToBufferedInputStreamWithSize = is -> ByteArrayOutputStream.toBufferedInputStream(is, 1024); final IOFunction unSyncBaosToBufferedInputStream = UnsynchronizedByteArrayOutputStream::toBufferedInputStream; final IOFunction unSyncBaosToBufferedInputStreamWithSize = is -> UnsynchronizedByteArrayOutputStream.toBufferedInputStream(is, 1024); return Stream.of( Arguments.of("ByteArrayOutputStream.toBufferedInputStream(InputStream)", syncBaosToBufferedInputStream), Arguments.of("ByteArrayOutputStream.toBufferedInputStream(InputStream, int)", syncBaosToBufferedInputStreamWithSize), Arguments.of("UnsynchronizedByteArrayOutputStream.toBufferedInputStream(InputStream)", unSyncBaosToBufferedInputStream), Arguments.of("UnsynchronizedByteArrayOutputStream.toBufferedInputStream(InputStream, int)", unSyncBaosToBufferedInputStreamWithSize) ); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/output/ChunkedOutputStreamTest.java0100644 0000000 0000000 00000004764 13612062727 032622 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import java.io.IOException; import java.util.concurrent.atomic.AtomicInteger; import org.junit.jupiter.api.Test; /** * Test the chunked output stream */ public class ChunkedOutputStreamTest { @Test public void write_four_chunks() throws Exception { final AtomicInteger numWrites = new AtomicInteger(); try (final ByteArrayOutputStream baos = newByteArrayOutputStream(numWrites); final ChunkedOutputStream chunked = new ChunkedOutputStream(baos, 10)) { chunked.write("0123456789012345678901234567891".getBytes()); assertEquals(4, numWrites.get()); } } @Test public void negative_chunksize_not_permitted() { assertThrows(IllegalArgumentException.class, () -> new ChunkedOutputStream(new ByteArrayOutputStream(), 0)); } @Test public void defaultConstructor() throws IOException { final AtomicInteger numWrites = new AtomicInteger(); try (final ByteArrayOutputStream baos = newByteArrayOutputStream(numWrites); final ChunkedOutputStream chunked = new ChunkedOutputStream(baos)) { chunked.write(new byte[1024 * 4 + 1]); assertEquals(2, numWrites.get()); } } private ByteArrayOutputStream newByteArrayOutputStream(final AtomicInteger numWrites) { return new ByteArrayOutputStream() { @Override public void write(final byte[] b, final int off, final int len) { numWrites.incrementAndGet(); super.write(b, off, len); } }; } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/output/ChunkedWriterTest.java0100644 0000000 0000000 00000005311 13612062727 031407 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import java.io.IOException; import java.io.OutputStreamWriter; import java.util.concurrent.atomic.AtomicInteger; import org.junit.jupiter.api.Test; public class ChunkedWriterTest { @Test public void write_four_chunks() throws Exception { final AtomicInteger numWrites = new AtomicInteger(); try (final OutputStreamWriter osw = getOutputStreamWriter(numWrites)) { try (final ChunkedWriter chunked = new ChunkedWriter(osw, 10)) { chunked.write("0123456789012345678901234567891".toCharArray()); chunked.flush(); assertEquals(4, numWrites.get()); } } } @Test public void write_two_chunks_default_constructor() throws Exception { final AtomicInteger numWrites = new AtomicInteger(); try (final OutputStreamWriter osw = getOutputStreamWriter(numWrites)) { try (final ChunkedWriter chunked = new ChunkedWriter(osw)) { chunked.write(new char[1024 * 4 + 1]); chunked.flush(); assertEquals(2, numWrites.get()); } } } private OutputStreamWriter getOutputStreamWriter(final AtomicInteger numWrites) { final ByteArrayOutputStream baos = new ByteArrayOutputStream(); return new OutputStreamWriter(baos) { @Override public void write(final char[] cbuf, final int off, final int len) throws IOException { numWrites.incrementAndGet(); super.write(cbuf, off, len); } }; } @Test public void negative_chunksize_not_permitted() { assertThrows(IllegalArgumentException.class, () -> new ChunkedWriter(new OutputStreamWriter(new ByteArrayOutputStream()), 0)); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/output/CloseShieldOutputStreamTest.java0100644 0000000 0000000 00000003731 13612062727 033430 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; import java.io.IOException; import java.io.OutputStream; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * JUnit Test Case for {@link CloseShieldOutputStream}. */ public class CloseShieldOutputStreamTest { private ByteArrayOutputStream original; private OutputStream shielded; private boolean closed; @BeforeEach public void setUp() { original = new ByteArrayOutputStream() { @Override public void close() { closed = true; } }; shielded = CloseShieldOutputStream.wrap(original); closed = false; } @Test public void testClose() throws IOException { shielded.close(); assertFalse(closed, "closed"); assertThrows(IOException.class, () -> shielded.write('x'), "write(b)"); original.write('y'); assertEquals(1, original.size()); assertEquals('y', original.toByteArray()[0]); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/output/CloseShieldWriterTest.java0100644 0000000 0000000 00000003553 13612062727 032232 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import java.io.IOException; import java.io.Writer; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * JUnit Test Case for {@link CloseShieldWriter}. */ public class CloseShieldWriterTest { private StringBuilderWriter original; private Writer shielded; @BeforeEach public void setUp() { original = spy(new StringBuilderWriter()); shielded = CloseShieldWriter.wrap(original); } @Test public void testClose() throws IOException { shielded.close(); verify(original, never()).close(); assertThrows(IOException.class, () -> shielded.write('x'), "write(c)"); original.write('y'); assertEquals(1, original.getBuilder().length()); assertEquals('y', original.toString().charAt(0)); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/output/ClosedOutputStreamTest.java0100644 0000000 0000000 00000003174 13612062727 032444 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import static org.junit.jupiter.api.Assertions.fail; import java.io.IOException; import org.junit.jupiter.api.Test; /** * JUnit Test Case for {@link ClosedOutputStream}. */ public class ClosedOutputStreamTest { /** * Test the {@code write(b)} method. */ @Test public void testWrite() { try (ClosedOutputStream cos = new ClosedOutputStream()) { cos.write('x'); fail("write(b)"); } catch (final IOException e) { // expected } } /** * Test the {@code flush()} method. */ @Test public void testFlush() { try (ClosedOutputStream cos = new ClosedOutputStream()) { cos.flush(); fail("flush()"); } catch (final IOException e) { // expected } } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/output/ClosedWriterTest.java0100644 0000000 0000000 00000003174 13612062727 031244 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import static org.junit.jupiter.api.Assertions.fail; import java.io.IOException; import org.junit.jupiter.api.Test; /** * JUnit Test Case for {@link ClosedWriter}. */ public class ClosedWriterTest { /** * Test the {@code write(cbuf, off, len)} method. */ @Test public void testWrite() { try (ClosedWriter cw = new ClosedWriter()) { cw.write(new char[0], 0, 0); fail("write(cbuf, off, len)"); } catch (final IOException e) { // expected } } /** * Test the {@code flush()} method. */ @Test public void testFlush() { try (ClosedWriter cw = new ClosedWriter()) { cw.flush(); fail("flush()"); } catch (final IOException e) { // expected } } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/output/CountingOutputStreamTest.java0100644 0000000 0000000 00000010025 13612062727 033012 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; import java.io.ByteArrayOutputStream; import java.io.IOException; import org.apache.commons.io.IOUtils; import org.apache.commons.io.input.NullInputStream; import org.junit.jupiter.api.Test; /** * */ public class CountingOutputStreamTest { @Test public void testCounting() throws IOException { final ByteArrayOutputStream baos = new ByteArrayOutputStream(); try (final CountingOutputStream cos = new CountingOutputStream(baos)) { for (int i = 0; i < 20; i++) { cos.write(i); } assertByteArrayEquals("CountingOutputStream.write(int)", baos.toByteArray(), 0, 20); assertEquals(cos.getCount(), 20, "CountingOutputStream.getCount()"); final byte[] array = new byte[10]; for (int i = 20; i < 30; i++) { array[i - 20] = (byte) i; } cos.write(array); assertByteArrayEquals("CountingOutputStream.write(byte[])", baos.toByteArray(), 0, 30); assertEquals(cos.getCount(), 30, "CountingOutputStream.getCount()"); for (int i = 25; i < 35; i++) { array[i - 25] = (byte) i; } cos.write(array, 5, 5); assertByteArrayEquals("CountingOutputStream.write(byte[], int, int)", baos.toByteArray(), 0, 35); assertEquals(cos.getCount(), 35, "CountingOutputStream.getCount()"); final int count = cos.resetCount(); assertEquals(count, 35, "CountingOutputStream.resetCount()"); for (int i = 0; i < 10; i++) { cos.write(i); } assertByteArrayEquals("CountingOutputStream.write(int)", baos.toByteArray(), 35, 45); assertEquals(cos.getCount(), 10, "CountingOutputStream.getCount()"); } } /* * Test for files > 2GB in size - see issue IO-84 */ @Test public void testLargeFiles_IO84() throws Exception { final long size = (long) Integer.MAX_VALUE + (long) 1; final NullInputStream mock = new NullInputStream(size); final CountingOutputStream cos = new CountingOutputStream(NullOutputStream.NULL_OUTPUT_STREAM); // Test integer methods IOUtils.copyLarge(mock, cos); try { cos.getCount(); fail("Expected getCount() to throw an ArithmeticException"); } catch (final ArithmeticException ae) { // expected result } try { cos.resetCount(); fail("Expected resetCount() to throw an ArithmeticException"); } catch (final ArithmeticException ae) { // expected result } mock.close(); // Test long methods IOUtils.copyLarge(mock, cos); assertEquals(size, cos.getByteCount(), "getByteCount()"); assertEquals(size, cos.resetByteCount(), "resetByteCount()"); } private void assertByteArrayEquals(final String msg, final byte[] array, final int start, final int end) { for (int i = start; i < end; i++) { assertEquals(array[i], i-start, msg+": array[" + i + "] mismatch"); } } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/output/DeferredFileOutputStreamTest.java0100644 0000000 0000000 00000036165 13612062727 033561 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Path; import java.util.stream.IntStream; import org.apache.commons.io.IOUtils; import org.junit.jupiter.api.io.TempDir; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; /** * Unit tests for the {@code DeferredFileOutputStream} class. * */ public class DeferredFileOutputStreamTest { public static IntStream data() { return IntStream.of(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096); } /** * The test data as a string (which is the simplest form). */ private final String testString = "0123456789"; /** * The test data as a byte array, derived from the string. */ private final byte[] testBytes = testString.getBytes(); /** * Tests the case where the amount of data exceeds the threshold, and is therefore written to disk. The actual data * written to disk is verified, as is the file itself. */ @ParameterizedTest(name = "initialBufferSize = {0}") @MethodSource("data") public void testAboveThreshold(final int initialBufferSize) { final File testFile = new File("testAboveThreshold.dat"); // Ensure that the test starts from a clean base. testFile.delete(); final DeferredFileOutputStream dfos = new DeferredFileOutputStream(testBytes.length - 5, initialBufferSize, testFile); try { dfos.write(testBytes, 0, testBytes.length); dfos.close(); } catch (final IOException e) { fail("Unexpected IOException"); } assertFalse(dfos.isInMemory()); assertNull(dfos.getData()); verifyResultFile(testFile); // Ensure that the test starts from a clean base. testFile.delete(); } /** * Tests the case where the amount of data exceeds the threshold, and is therefore written to disk. The actual data * written to disk is verified, as is the file itself. * Testing the getInputStream() method. */ @ParameterizedTest(name = "initialBufferSize = {0}") @MethodSource("data") public void testAboveThresholdGetInputStream(final int initialBufferSize, final @TempDir Path tempDir) throws IOException { final File testFile = tempDir.resolve("testAboveThreshold.dat").toFile(); final DeferredFileOutputStream dfos = new DeferredFileOutputStream(testBytes.length - 5, initialBufferSize, testFile); dfos.write(testBytes, 0, testBytes.length); dfos.close(); assertFalse(dfos.isInMemory()); try (InputStream is = dfos.toInputStream()) { assertArrayEquals(testBytes, IOUtils.toByteArray(is)); } verifyResultFile(testFile); } /** * Tests the case where the amount of data is exactly the same as the threshold. The behavior should be the same as * that for the amount of data being below (i.e. not exceeding) the threshold. */ @ParameterizedTest(name = "initialBufferSize = {0}") @MethodSource("data") public void testAtThreshold(final int initialBufferSize) { final DeferredFileOutputStream dfos = new DeferredFileOutputStream(testBytes.length, initialBufferSize, null); try { dfos.write(testBytes, 0, testBytes.length); dfos.close(); } catch (final IOException e) { fail("Unexpected IOException"); } assertTrue(dfos.isInMemory()); final byte[] resultBytes = dfos.getData(); assertEquals(testBytes.length, resultBytes.length); assertArrayEquals(resultBytes, testBytes); } /** * Tests the case where the amount of data falls below the threshold, and is therefore confined to memory. */ @ParameterizedTest(name = "initialBufferSize = {0}") @MethodSource("data") public void testBelowThreshold(final int initialBufferSize) { final DeferredFileOutputStream dfos = new DeferredFileOutputStream(testBytes.length + 42, initialBufferSize, null); try { dfos.write(testBytes, 0, testBytes.length); dfos.close(); } catch (final IOException e) { fail("Unexpected IOException"); } assertTrue(dfos.isInMemory()); final byte[] resultBytes = dfos.getData(); assertEquals(testBytes.length, resultBytes.length); assertArrayEquals(resultBytes, testBytes); } /** * Tests the case where the amount of data falls below the threshold, and is therefore confined to memory. * Testing the getInputStream() method. */ @ParameterizedTest(name = "initialBufferSize = {0}") @MethodSource("data") public void testBelowThresholdGetInputStream(final int initialBufferSize) throws IOException { final DeferredFileOutputStream dfos = new DeferredFileOutputStream(testBytes.length + 42, initialBufferSize, null); dfos.write(testBytes, 0, testBytes.length); dfos.close(); assertTrue(dfos.isInMemory()); try (InputStream is = dfos.toInputStream()) { assertArrayEquals(testBytes, IOUtils.toByteArray(is)); } } /** * Test specifying a temporary file and the threshold is reached. */ @ParameterizedTest(name = "initialBufferSize = {0}") @MethodSource("data") public void testTempFileAboveThreshold(final int initialBufferSize) { final String prefix = "commons-io-test"; final String suffix = ".out"; final File tempDir = new File("."); final DeferredFileOutputStream dfos = new DeferredFileOutputStream(testBytes.length - 5, initialBufferSize, prefix, suffix, tempDir); assertNull(dfos.getFile(), "Check file is null-A"); try { dfos.write(testBytes, 0, testBytes.length); dfos.close(); } catch (final IOException e) { fail("Unexpected IOException"); } assertFalse(dfos.isInMemory()); assertNull(dfos.getData()); assertNotNull(dfos.getFile(), "Check file not null"); assertTrue(dfos.getFile().exists(), "Check file exists"); assertTrue(dfos.getFile().getName().startsWith(prefix), "Check prefix"); assertTrue(dfos.getFile().getName().endsWith(suffix), "Check suffix"); assertEquals(tempDir.getPath(), dfos.getFile().getParent(), "Check dir"); verifyResultFile(dfos.getFile()); // Delete the temporary file. dfos.getFile().delete(); } /** * Test specifying a temporary file and the threshold is reached. */ @ParameterizedTest(name = "initialBufferSize = {0}") @MethodSource("data") public void testTempFileAboveThresholdPrefixOnly(final int initialBufferSize) { final String prefix = "commons-io-test"; final String suffix = null; final File tempDir = null; final DeferredFileOutputStream dfos = new DeferredFileOutputStream(testBytes.length - 5, initialBufferSize, prefix, suffix, tempDir); assertNull(dfos.getFile(), "Check file is null-A"); try { dfos.write(testBytes, 0, testBytes.length); dfos.close(); } catch (final IOException e) { fail("Unexpected IOException"); } assertFalse(dfos.isInMemory()); assertNull(dfos.getData()); assertNotNull(dfos.getFile(), "Check file not null"); assertTrue(dfos.getFile().exists(), "Check file exists"); assertTrue(dfos.getFile().getName().startsWith(prefix), "Check prefix"); assertTrue(dfos.getFile().getName().endsWith(".tmp"), "Check suffix"); // ".tmp" is default verifyResultFile(dfos.getFile()); // Delete the temporary file. dfos.getFile().delete(); } /** * Test specifying a temporary file and the threshold not reached. */ @ParameterizedTest(name = "initialBufferSize = {0}") @MethodSource("data") public void testTempFileBelowThreshold(final int initialBufferSize) { final String prefix = "commons-io-test"; final String suffix = ".out"; final File tempDir = new File("."); final DeferredFileOutputStream dfos = new DeferredFileOutputStream(testBytes.length + 42, initialBufferSize, prefix, suffix, tempDir); assertNull(dfos.getFile(), "Check file is null-A"); try { dfos.write(testBytes, 0, testBytes.length); dfos.close(); } catch (final IOException e) { fail("Unexpected IOException"); } assertTrue(dfos.isInMemory()); assertNull(dfos.getFile(), "Check file is null-B"); } /** * Test specifying a temporary file and the threshold is reached. * * @throws Exception */ @Test public void testTempFileError() throws Exception { final String prefix = null; final String suffix = ".out"; final File tempDir = new File("."); try { new DeferredFileOutputStream(testBytes.length - 5, prefix, suffix, tempDir).close(); fail("Expected IllegalArgumentException "); } catch (final IllegalArgumentException e) { // expected } } /** * Tests the case where there are multiple writes beyond the threshold, to ensure that the * {@code thresholdReached()} method is only called once, as the threshold is crossed for the first time. */ @ParameterizedTest(name = "initialBufferSize = {0}") @MethodSource("data") public void testThresholdReached(final int initialBufferSize) { final File testFile = new File("testThresholdReached.dat"); // Ensure that the test starts from a clean base. testFile.delete(); final DeferredFileOutputStream dfos = new DeferredFileOutputStream(testBytes.length / 2, initialBufferSize, testFile); final int chunkSize = testBytes.length / 3; try { dfos.write(testBytes, 0, chunkSize); dfos.write(testBytes, chunkSize, chunkSize); dfos.write(testBytes, chunkSize * 2, testBytes.length - chunkSize * 2); dfos.close(); } catch (final IOException e) { fail("Unexpected IOException"); } assertFalse(dfos.isInMemory()); assertNull(dfos.getData()); verifyResultFile(testFile); // Ensure that the test starts from a clean base. testFile.delete(); } /** * Test whether writeTo() properly writes large content. */ @ParameterizedTest(name = "initialBufferSize = {0}") @MethodSource("data") public void testWriteToLarge(final int initialBufferSize) { final File testFile = new File("testWriteToFile.dat"); final ByteArrayOutputStream baos = new ByteArrayOutputStream(initialBufferSize); // Ensure that the test starts from a clean base. testFile.delete(); final DeferredFileOutputStream dfos = new DeferredFileOutputStream(testBytes.length / 2, testFile); try { dfos.write(testBytes); assertTrue(testFile.exists()); assertFalse(dfos.isInMemory()); try { dfos.writeTo(baos); fail("Should not have been able to write before closing"); } catch (final IOException ioe) { // ok, as expected } dfos.close(); dfos.writeTo(baos); } catch (final IOException ioe) { fail("Unexpected IOException"); } final byte[] copiedBytes = baos.toByteArray(); assertArrayEquals(testBytes, copiedBytes); verifyResultFile(testFile); testFile.delete(); } /** * Test whether writeTo() properly writes small content. */ @ParameterizedTest(name = "initialBufferSize = {0}") @MethodSource("data") public void testWriteToSmall(final int initialBufferSize) { final File testFile = new File("testWriteToMem.dat"); final ByteArrayOutputStream baos = new ByteArrayOutputStream(initialBufferSize); // Ensure that the test starts from a clean base. testFile.delete(); final DeferredFileOutputStream dfos = new DeferredFileOutputStream(testBytes.length * 2, initialBufferSize, testFile); try { dfos.write(testBytes); assertFalse(testFile.exists()); assertTrue(dfos.isInMemory()); try { dfos.writeTo(baos); fail("Should not have been able to write before closing"); } catch (final IOException ioe) { // ok, as expected } dfos.close(); dfos.writeTo(baos); } catch (final IOException ioe) { fail("Unexpected IOException"); } final byte[] copiedBytes = baos.toByteArray(); assertArrayEquals(testBytes, copiedBytes); testFile.delete(); } /** * Verifies that the specified file contains the same data as the original test data. * * @param testFile The file containing the test output. */ private void verifyResultFile(final File testFile) { try { final InputStream fis = Files.newInputStream(testFile.toPath()); assertEquals(testBytes.length, fis.available()); final byte[] resultBytes = new byte[testBytes.length]; assertEquals(testBytes.length, fis.read(resultBytes)); assertArrayEquals(resultBytes, testBytes); assertEquals(-1, fis.read(resultBytes)); try { fis.close(); } catch (final IOException e) { // Ignore an exception on close } } catch (final FileNotFoundException e) { fail("Unexpected FileNotFoundException"); } catch (final IOException e) { fail("Unexpected IOException"); } } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/output/FileWriterWithEncodingTest.java0100644 0000000 0000000 00000016335 13612062727 033220 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import static org.apache.commons.io.test.TestUtils.checkFile; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.Writer; import java.nio.charset.Charset; import java.nio.charset.CharsetEncoder; import java.nio.file.Files; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; /** * Tests that the encoding is actually set and used. * */ public class FileWriterWithEncodingTest { @TempDir public File temporaryFolder; private String defaultEncoding; private File file1; private File file2; private String textContent; private final char[] anotherTestContent = {'f', 'z', 'x'}; @BeforeEach public void setUp() throws Exception { final File encodingFinder = new File(temporaryFolder, "finder.txt"); try (OutputStreamWriter out = new OutputStreamWriter(Files.newOutputStream(encodingFinder.toPath()))) { defaultEncoding = out.getEncoding(); } file1 = new File(temporaryFolder, "testfile1.txt"); file2 = new File(temporaryFolder, "testfile2.txt"); final char[] arr = new char[1024]; final char[] chars = "ABCDEFGHIJKLMNOPQabcdefgihklmnopq".toCharArray(); for (int i = 0; i < arr.length; i++) { arr[i] = chars[i % chars.length]; } textContent = new String(arr); } @Test public void sameEncoding_string_constructor() throws Exception { successfulRun(new FileWriterWithEncoding(file2, defaultEncoding)); } @Test public void sameEncoding_string_string_constructor() throws Exception { successfulRun(new FileWriterWithEncoding(file2.getPath(), defaultEncoding)); } @Test public void sameEncoding_Charset_constructor() throws Exception { successfulRun(new FileWriterWithEncoding(file2, Charset.defaultCharset())); } @Test public void sameEncoding_string_Charset_constructor() throws Exception { successfulRun(new FileWriterWithEncoding(file2.getPath(), Charset.defaultCharset())); } @Test public void sameEncoding_CharsetEncoder_constructor() throws Exception { final CharsetEncoder enc = Charset.defaultCharset().newEncoder(); successfulRun(new FileWriterWithEncoding(file2, enc)); } @Test public void sameEncoding_string_CharsetEncoder_constructor() throws Exception { final CharsetEncoder enc = Charset.defaultCharset().newEncoder(); successfulRun(new FileWriterWithEncoding(file2.getPath(), enc)); } private void successfulRun(final FileWriterWithEncoding fw21) throws Exception { try ( FileWriter fw1 = new FileWriter(file1); // default encoding FileWriterWithEncoding fw2 = fw21 ){ writeTestPayload(fw1, fw2); checkFile(file1, file2); } assertTrue(file1.exists()); assertTrue(file2.exists()); } @Test public void testDifferentEncoding() throws Exception { if (Charset.isSupported("UTF-16BE")) { try ( FileWriter fw1 = new FileWriter(file1); // default encoding FileWriterWithEncoding fw2 = new FileWriterWithEncoding(file2, defaultEncoding) ){ writeTestPayload(fw1, fw2); try { checkFile(file1, file2); fail(); } catch (final AssertionError ex) { // success } } assertTrue(file1.exists()); assertTrue(file2.exists()); } if (Charset.isSupported("UTF-16LE")) { try ( FileWriter fw1 = new FileWriter(file1); // default encoding FileWriterWithEncoding fw2 = new FileWriterWithEncoding(file2, defaultEncoding) ){ writeTestPayload(fw1, fw2); try { checkFile(file1, file2); fail(); } catch (final AssertionError ex) { // success } } assertTrue(file1.exists()); assertTrue(file2.exists()); } } private void writeTestPayload(final FileWriter fw1, final FileWriterWithEncoding fw2) throws IOException { assertTrue(file1.exists()); assertTrue(file2.exists()); fw1.write(textContent); fw2.write(textContent); fw1.write(65); fw2.write(65); fw1.write(anotherTestContent); fw2.write(anotherTestContent); fw1.write(anotherTestContent, 1, 2); fw2.write(anotherTestContent, 1, 2); fw1.write("CAFE", 1, 2); fw2.write("CAFE", 1, 2); fw1.flush(); fw2.flush(); } @Test public void constructor_File_encoding_badEncoding() { assertThrows(IOException.class, () -> { try ( Writer writer = new FileWriterWithEncoding(file1, "BAD-ENCODE") ){ } }); assertFalse(file1.exists()); } @Test public void constructor_File_directory() { assertThrows(IOException.class, () -> { try ( Writer writer = new FileWriterWithEncoding(temporaryFolder, defaultEncoding) ){ } }); assertFalse(file1.exists()); } @Test public void constructor_File_nullFile() { assertThrows(NullPointerException.class, () -> { try ( Writer writer = new FileWriterWithEncoding((File) null, defaultEncoding) ){ } }); assertFalse(file1.exists()); } @Test public void constructor_fileName_nullFile() { assertThrows(NullPointerException.class, () -> { try ( Writer writer = new FileWriterWithEncoding((String) null, defaultEncoding) ){ } }); assertFalse(file1.exists()); } @Test public void sameEncoding_null_Charset_constructor() throws Exception { try { successfulRun(new FileWriterWithEncoding(file2, (Charset) null)); fail(); } catch (final NullPointerException ignore) { } } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/output/LockableFileWriterTest.java0100644 0000000 0000000 00000015033 13612062727 032344 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import java.io.File; import java.io.IOException; import java.io.Writer; import java.nio.charset.StandardCharsets; import java.nio.charset.UnsupportedCharsetException; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; /** * Tests that files really lock, although no writing is done as * the locking is tested only on construction. * */ public class LockableFileWriterTest { @TempDir public File temporaryFolder; private File file; private File lockDir; private File lockFile; private File altLockDir; private File altLockFile; @BeforeEach public void setUp() { file = new File(temporaryFolder, "testlockfile"); lockDir = new File(System.getProperty("java.io.tmpdir")); lockFile = new File(lockDir, file.getName() + ".lck"); altLockDir = temporaryFolder; altLockFile = new File(altLockDir, file.getName() + ".lck"); } @Test public void testFileLocked() throws IOException { // open a valid lockable writer try (LockableFileWriter lfw1 = new LockableFileWriter(file)) { assertTrue(file.exists()); assertTrue(lockFile.exists()); // try to open a second writer try (LockableFileWriter lfw2 = new LockableFileWriter(file)) { fail("Somehow able to open a locked file. "); } catch(final IOException ioe) { final String msg = ioe.getMessage(); assertTrue(msg.startsWith("Can't write file, lock "), "Exception message does not start correctly. "); assertTrue(file.exists()); assertTrue(lockFile.exists()); } // try to open a third writer try (LockableFileWriter lfw3 = new LockableFileWriter(file)) { fail("Somehow able to open a locked file. "); } catch(final IOException ioe) { final String msg = ioe.getMessage(); assertTrue(msg.startsWith("Can't write file, lock "), "Exception message does not start correctly. "); assertTrue(file.exists()); assertTrue(lockFile.exists()); } } assertTrue(file.exists()); assertFalse(lockFile.exists()); } @Test public void testAlternateLockDir() throws IOException { // open a valid lockable writer try (LockableFileWriter lfw1 = new LockableFileWriter(file, "UTF-8" ,true, altLockDir.getAbsolutePath())){ assertTrue(file.exists()); assertTrue(altLockFile.exists()); // try to open a second writer try (LockableFileWriter lfw2 = new LockableFileWriter(file, StandardCharsets.UTF_8, true, altLockDir.getAbsolutePath())){ fail("Somehow able to open a locked file. "); } catch(final IOException ioe) { final String msg = ioe.getMessage(); assertTrue(msg.startsWith("Can't write file, lock "), "Exception message does not start correctly. "); assertTrue(file.exists()); assertTrue(altLockFile.exists()); } } assertTrue(file.exists()); assertFalse(altLockFile.exists()); } @Test public void testFileNotLocked() throws IOException { // open a valid lockable writer try (LockableFileWriter lfw1 = new LockableFileWriter(file)) { assertTrue(file.exists()); assertTrue(lockFile.exists()); } assertTrue(file.exists()); assertFalse(lockFile.exists()); // open a second valid writer on the same file try (LockableFileWriter lfw2 = new LockableFileWriter(file)) { assertTrue(file.exists()); assertTrue(lockFile.exists()); } assertTrue(file.exists()); assertFalse(lockFile.exists()); } @Test public void testConstructor_File_encoding_badEncoding() throws IOException { try (Writer writer = new LockableFileWriter(file, "BAD-ENCODE")) { fail(); } catch (final UnsupportedCharsetException ex) { // expected assertFalse(file.exists()); assertFalse(lockFile.exists()); } assertFalse(file.exists()); assertFalse(lockFile.exists()); } @Test public void testConstructor_File_directory() { try (Writer writer = new LockableFileWriter(temporaryFolder)) { fail(); } catch (final IOException ex) { // expected assertFalse(file.exists()); assertFalse(lockFile.exists()); } assertFalse(file.exists()); assertFalse(lockFile.exists()); } @Test public void testConstructor_File_nullFile() throws IOException { try (Writer writer = new LockableFileWriter((File) null)) { fail(); } catch (final NullPointerException ex) { // expected assertFalse(file.exists()); assertFalse(lockFile.exists()); } assertFalse(file.exists()); assertFalse(lockFile.exists()); } @Test public void testConstructor_fileName_nullFile() throws IOException { try (Writer writer = new LockableFileWriter((String) null)) { fail(); } catch (final NullPointerException ex) { // expected assertFalse(file.exists()); assertFalse(lockFile.exists()); } assertFalse(file.exists()); assertFalse(lockFile.exists()); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/output/NullAppendableTest.java0100644 0000000 0000000 00000002472 13612062727 031524 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import java.io.IOException; import org.junit.jupiter.api.Test; /** * Really not a lot to do here, but checking that no Exceptions are thrown. */ public class NullAppendableTest { @Test public void testNull() throws IOException { final Appendable appendable = NullAppendable.INSTANCE; appendable.append('a'); appendable.append("A"); appendable.append("A", 0, 1); appendable.append(null, 0, 1); appendable.append(null, -1, -1); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/output/NullOutputStreamTest.java0100644 0000000 0000000 00000003306 13612062727 032142 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import java.io.IOException; import org.junit.jupiter.api.Test; /** * Really not a lot to do here, but checking that no Exceptions are thrown. */ public class NullOutputStreamTest { private void process(final NullOutputStream nos) throws IOException { nos.write("string".getBytes()); nos.write("some string".getBytes(), 3, 5); nos.write(1); nos.write(0x0f); nos.flush(); nos.close(); nos.write("allowed".getBytes()); nos.write(255); } @Test public void testNewInstance() throws IOException { try (final NullOutputStream nos = NullOutputStream.NULL_OUTPUT_STREAM) { process(nos); } } @Test public void testSingleton() throws IOException { try (final NullOutputStream nos = NullOutputStream.NULL_OUTPUT_STREAM) { process(nos); } } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/output/NullPrintStreamTest.java0100644 0000000 0000000 00000003272 13612062727 031740 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import java.io.IOException; import org.junit.jupiter.api.Test; /** * Really not a lot to do here, but checking that no Exceptions are thrown. */ public class NullPrintStreamTest { private void process(final NullPrintStream nos) throws IOException { nos.write("string".getBytes()); nos.write("some string".getBytes(), 3, 5); nos.write(1); nos.write(0x0f); nos.flush(); nos.close(); nos.write("allowed".getBytes()); nos.write(255); } @Test public void testNullNewInstance() throws IOException { try (final NullPrintStream nos = new NullPrintStream()) { process(nos); } } @Test public void testNullSingleton() throws IOException { try (final NullPrintStream nos = NullPrintStream.NULL_PRINT_STREAM) { process(nos); } } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/output/NullWriterTest.java0100644 0000000 0000000 00000002550 13612062727 030742 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import org.junit.jupiter.api.Test; /** * Really not a lot to do here, but checking that no * Exceptions are thrown. */ public class NullWriterTest { @Test public void testNull() { final char[] chars = { 'A', 'B', 'C' }; try (final NullWriter writer = NullWriter.NULL_WRITER) { writer.write(1); writer.write(chars); writer.write(chars, 1, 1); writer.write("some string"); writer.write("some string", 2, 2); writer.flush(); } } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/output/ProxyCollectionWriterTest.java0100644 0000000 0000000 00000046710 13612062727 033173 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import java.io.IOException; import java.io.StringWriter; import java.io.Writer; import java.util.Arrays; import java.util.Collection; import org.apache.commons.io.IOExceptionList; import org.apache.commons.io.IOIndexedException; import org.junit.jupiter.api.Test; /** * JUnit Test Case for {@link ProxyCollectionWriter}. */ public class ProxyCollectionWriterTest { @Test public void testArrayIOExceptionOnAppendChar1() throws IOException { final Writer badW = new BrokenWriter(); final StringWriter goodW = mock(StringWriter.class); @SuppressWarnings("resource") // not necessary to close this final ProxyCollectionWriter tw = new ProxyCollectionWriter(badW, goodW, null); final char data = 'A'; try { tw.append(data); fail("Expected " + IOException.class.getName()); } catch (final IOExceptionList e) { verify(goodW).append(data); assertEquals(1, e.getCauseList().size()); assertEquals(0, e.getCause(0, IOIndexedException.class).getIndex()); } } @Test public void testArrayIOExceptionOnAppendChar2() throws IOException { final Writer badW = new BrokenWriter(); final StringWriter goodW = mock(StringWriter.class); @SuppressWarnings("resource") // not necessary to close this final ProxyCollectionWriter tw = new ProxyCollectionWriter(goodW, badW, null); final char data = 'A'; try { tw.append(data); fail("Expected " + IOException.class.getName()); } catch (final IOExceptionList e) { verify(goodW).append(data); assertEquals(1, e.getCauseList().size()); assertEquals(1, e.getCause(0, IOIndexedException.class).getIndex()); } } @Test public void testArrayIOExceptionOnAppendCharSequence1() throws IOException { final Writer badW = new BrokenWriter(); final StringWriter goodW = mock(StringWriter.class); @SuppressWarnings("resource") // not necessary to close this final ProxyCollectionWriter tw = new ProxyCollectionWriter(badW, goodW, null); final CharSequence data = "A"; try { tw.append(data); fail("Expected " + IOException.class.getName()); } catch (final IOExceptionList e) { verify(goodW).append(data); assertEquals(1, e.getCauseList().size()); assertEquals(0, e.getCause(0, IOIndexedException.class).getIndex()); } } @Test public void testArrayIOExceptionOnAppendCharSequence2() throws IOException { final Writer badW = new BrokenWriter(); final StringWriter goodW = mock(StringWriter.class); @SuppressWarnings("resource") // not necessary to close this final ProxyCollectionWriter tw = new ProxyCollectionWriter(goodW, badW, null); final CharSequence data = "A"; try { tw.append(data); fail("Expected " + IOException.class.getName()); } catch (final IOExceptionList e) { verify(goodW).append(data); assertEquals(1, e.getCauseList().size()); assertEquals(1, e.getCause(0, IOIndexedException.class).getIndex()); } } @Test public void testArrayIOExceptionOnAppendCharSequenceIntInt1() throws IOException { final Writer badW = new BrokenWriter(); final StringWriter goodW = mock(StringWriter.class); @SuppressWarnings("resource") // not necessary to close this final ProxyCollectionWriter tw = new ProxyCollectionWriter(badW, goodW, null); final CharSequence data = "A"; try { tw.append(data, 0, 0); fail("Expected " + IOException.class.getName()); } catch (final IOExceptionList e) { verify(goodW).append(data, 0, 0); assertEquals(1, e.getCauseList().size()); assertEquals(0, e.getCause(0, IOIndexedException.class).getIndex()); } } @Test public void testArrayIOExceptionOnAppendCharSequenceIntInt2() throws IOException { final Writer badW = new BrokenWriter(); final StringWriter goodW = mock(StringWriter.class); @SuppressWarnings("resource") // not necessary to close this final ProxyCollectionWriter tw = new ProxyCollectionWriter(goodW, badW, null); final CharSequence data = "A"; try { tw.append(data, 0, 0); fail("Expected " + IOException.class.getName()); } catch (final IOExceptionList e) { verify(goodW).append(data, 0, 0); assertEquals(1, e.getCauseList().size()); assertEquals(1, e.getCause(0, IOIndexedException.class).getIndex()); } } @Test public void testArrayIOExceptionOnClose1() throws IOException { final Writer badW = new BrokenWriter(); final StringWriter goodW = mock(StringWriter.class); @SuppressWarnings("resource") // not necessary to close this final ProxyCollectionWriter tw = new ProxyCollectionWriter(badW, goodW, null); try { tw.close(); fail("Expected " + IOException.class.getName()); } catch (final IOExceptionList e) { verify(goodW).close(); assertEquals(1, e.getCauseList().size()); assertEquals(0, e.getCause(0, IOIndexedException.class).getIndex()); } } @Test public void testArrayIOExceptionOnClose2() throws IOException { final Writer badW = new BrokenWriter(); final StringWriter goodW = mock(StringWriter.class); @SuppressWarnings("resource") // not necessary to close this final ProxyCollectionWriter tw = new ProxyCollectionWriter(goodW, badW, null); try { tw.close(); fail("Expected " + IOException.class.getName()); } catch (final IOExceptionList e) { verify(goodW).close(); assertEquals(1, e.getCauseList().size()); assertEquals(1, e.getCause(0, IOIndexedException.class).getIndex()); } } @Test public void testArrayIOExceptionOnFlush1() throws IOException { final Writer badW = new BrokenWriter(); final StringWriter goodW = mock(StringWriter.class); @SuppressWarnings("resource") // not necessary to close this final ProxyCollectionWriter tw = new ProxyCollectionWriter(badW, goodW, null); try { tw.flush(); fail("Expected " + IOException.class.getName()); } catch (final IOExceptionList e) { verify(goodW).flush(); assertEquals(1, e.getCauseList().size()); assertEquals(0, e.getCause(0, IOIndexedException.class).getIndex()); } } @Test public void testArrayIOExceptionOnFlush2() throws IOException { final Writer badW = new BrokenWriter(); final StringWriter goodW = mock(StringWriter.class); @SuppressWarnings("resource") // not necessary to close this final ProxyCollectionWriter tw = new ProxyCollectionWriter(goodW, badW, null); try { tw.flush(); fail("Expected " + IOException.class.getName()); } catch (final IOExceptionList e) { verify(goodW).flush(); assertEquals(1, e.getCauseList().size()); assertEquals(1, e.getCause(0, IOIndexedException.class).getIndex()); } } @Test public void testArrayIOExceptionOnWriteCharArray1() throws IOException { final Writer badW = new BrokenWriter(); final StringWriter goodW = mock(StringWriter.class); @SuppressWarnings("resource") // not necessary to close this final ProxyCollectionWriter tw = new ProxyCollectionWriter(badW, goodW, null); final char[] data = { 'a' }; try { tw.write(data); fail("Expected " + IOException.class.getName()); } catch (final IOExceptionList e) { verify(goodW).write(data); assertEquals(1, e.getCauseList().size()); assertEquals(0, e.getCause(0, IOIndexedException.class).getIndex()); } } @Test public void testArrayIOExceptionOnWriteCharArray2() throws IOException { final Writer badW = new BrokenWriter(); final StringWriter goodW = mock(StringWriter.class); @SuppressWarnings("resource") // not necessary to close this final ProxyCollectionWriter tw = new ProxyCollectionWriter(goodW, badW, null); final char[] data = { 'a' }; try { tw.write(data); fail("Expected " + IOException.class.getName()); } catch (final IOExceptionList e) { verify(goodW).write(data); assertEquals(1, e.getCauseList().size()); assertEquals(1, e.getCause(0, IOIndexedException.class).getIndex()); } } @Test public void testArrayIOExceptionOnWriteCharArrayIntInt1() throws IOException { final Writer badW = new BrokenWriter(); final StringWriter goodW = mock(StringWriter.class); @SuppressWarnings("resource") // not necessary to close this final ProxyCollectionWriter tw = new ProxyCollectionWriter(badW, goodW, null); final char[] data = { 'a' }; try { tw.write(data, 0, 0); fail("Expected " + IOException.class.getName()); } catch (final IOExceptionList e) { verify(goodW).write(data, 0, 0); assertEquals(1, e.getCauseList().size()); assertEquals(0, e.getCause(0, IOIndexedException.class).getIndex()); } } @Test public void testArrayIOExceptionOnWriteCharArrayIntInt2() throws IOException { final Writer badW = new BrokenWriter(); final StringWriter goodW = mock(StringWriter.class); @SuppressWarnings("resource") // not necessary to close this final ProxyCollectionWriter tw = new ProxyCollectionWriter(goodW, badW, null); final char[] data = { 'a' }; try { tw.write(data, 0, 0); fail("Expected " + IOException.class.getName()); } catch (final IOExceptionList e) { verify(goodW).write(data, 0, 0); assertEquals(1, e.getCauseList().size()); assertEquals(1, e.getCause(0, IOIndexedException.class).getIndex()); } } @Test public void testArrayIOExceptionOnWriteInt1() throws IOException { final Writer badW = new BrokenWriter(); final StringWriter goodW = mock(StringWriter.class); @SuppressWarnings("resource") // not necessary to close this final ProxyCollectionWriter tw = new ProxyCollectionWriter(badW, goodW, null); final int data = 32; try { tw.write(data); fail("Expected " + IOException.class.getName()); } catch (final IOExceptionList e) { verify(goodW).write(data); assertEquals(1, e.getCauseList().size()); assertEquals(0, e.getCause(0, IOIndexedException.class).getIndex()); } } @Test public void testArrayIOExceptionOnWriteInt2() throws IOException { final Writer badW = new BrokenWriter(); final StringWriter goodW = mock(StringWriter.class); @SuppressWarnings("resource") // not necessary to close this final ProxyCollectionWriter tw = new ProxyCollectionWriter(goodW, badW, null); try { tw.write(32); fail("Expected " + IOException.class.getName()); } catch (final IOExceptionList e) { verify(goodW).write(32); assertEquals(1, e.getCauseList().size()); assertEquals(1, e.getCause(0, IOIndexedException.class).getIndex()); } } @Test public void testArrayIOExceptionOnWriteString1() throws IOException { final Writer badW = new BrokenWriter(); final StringWriter goodW = mock(StringWriter.class); @SuppressWarnings("resource") // not necessary to close this final ProxyCollectionWriter tw = new ProxyCollectionWriter(badW, goodW, null); final String data = "A"; try { tw.write(data); fail("Expected " + IOException.class.getName()); } catch (final IOExceptionList e) { verify(goodW).write(data); assertEquals(1, e.getCauseList().size()); assertEquals(0, e.getCause(0, IOIndexedException.class).getIndex()); } } @Test public void testArrayIOExceptionOnWriteString2() throws IOException { final Writer badW = new BrokenWriter(); final StringWriter goodW = mock(StringWriter.class); @SuppressWarnings("resource") // not necessary to close this final ProxyCollectionWriter tw = new ProxyCollectionWriter(goodW, badW, null); final String data = "A"; try { tw.write(data); fail("Expected " + IOException.class.getName()); } catch (final IOExceptionList e) { verify(goodW).write(data); assertEquals(1, e.getCauseList().size()); assertEquals(1, e.getCause(0, IOIndexedException.class).getIndex()); } } @Test public void testArrayIOExceptionOnWriteStringIntInt1() throws IOException { final Writer badW = new BrokenWriter(); final StringWriter goodW = mock(StringWriter.class); @SuppressWarnings("resource") // not necessary to close this final ProxyCollectionWriter tw = new ProxyCollectionWriter(badW, goodW, null); final String data = "A"; try { tw.write(data, 0, 0); fail("Expected " + IOException.class.getName()); } catch (final IOExceptionList e) { verify(goodW).write(data, 0, 0); assertEquals(1, e.getCauseList().size()); assertEquals(0, e.getCause(0, IOIndexedException.class).getIndex()); } } @Test public void testArrayIOExceptionOnWriteStringIntInt2() throws IOException { final Writer badW = new BrokenWriter(); final StringWriter goodW = mock(StringWriter.class); @SuppressWarnings("resource") // not necessary to close this final ProxyCollectionWriter tw = new ProxyCollectionWriter(goodW, badW, null); final String data = "A"; try { tw.write(data, 0, 0); fail("Expected " + IOException.class.getName()); } catch (final IOExceptionList e) { verify(goodW).write(data, 0, 0); assertEquals(1, e.getCauseList().size()); assertEquals(1, e.getCause(0, IOIndexedException.class).getIndex()); } } @Test public void testCollectionCloseBranchIOException() throws IOException { final Writer badW = new BrokenWriter(); final StringWriter goodW = mock(StringWriter.class); @SuppressWarnings("resource") // not necessary to close this final ProxyCollectionWriter tw = new ProxyCollectionWriter(Arrays.asList(goodW, badW, null)); try { tw.close(); fail("Expected " + IOException.class.getName()); } catch (final IOExceptionList e) { verify(goodW).close(); assertEquals(1, e.getCauseList().size()); assertEquals(1, e.getCause(0, IOIndexedException.class).getIndex()); } } @Test public void testConstructorsNull() throws IOException { try (final ProxyCollectionWriter teeWriter = new ProxyCollectionWriter((Writer[]) null)) { // Call any method, should not throw teeWriter.append('a'); teeWriter.flush(); } try (final ProxyCollectionWriter teeWriter = new ProxyCollectionWriter((Collection) null)) { // Call any method, should not throw teeWriter.append('a'); teeWriter.flush(); } assertTrue(true, "Dummy to show test completed OK"); } @Test public void testTee() throws IOException { final StringBuilderWriter sbw1 = new StringBuilderWriter(); final StringBuilderWriter sbw2 = new StringBuilderWriter(); final StringBuilderWriter expected = new StringBuilderWriter(); try (final ProxyCollectionWriter tw = new ProxyCollectionWriter(sbw1, sbw2, null)) { for (int i = 0; i < 20; i++) { tw.write(i); expected.write(i); } assertEquals(expected.toString(), sbw1.toString(), "ProxyCollectionWriter.write(int)"); assertEquals(expected.toString(), sbw2.toString(), "ProxyCollectionWriter.write(int)"); final char[] array = new char[10]; for (int i = 20; i < 30; i++) { array[i - 20] = (char) i; } tw.write(array); expected.write(array); assertEquals(expected.toString(), sbw1.toString(), "ProxyCollectionWriter.write(char[])"); assertEquals(expected.toString(), sbw2.toString(), "ProxyCollectionWriter.write(char[])"); for (int i = 25; i < 35; i++) { array[i - 25] = (char) i; } tw.write(array, 5, 5); expected.write(array, 5, 5); assertEquals(expected.toString(), sbw1.toString(), "TeeOutputStream.write(byte[], int, int)"); assertEquals(expected.toString(), sbw2.toString(), "TeeOutputStream.write(byte[], int, int)"); for (int i = 0; i < 20; i++) { tw.append((char) i); expected.append((char) i); } assertEquals(expected.toString(), sbw1.toString(), "ProxyCollectionWriter.append(char)"); assertEquals(expected.toString(), sbw2.toString(), "ProxyCollectionWriter.append(char)"); for (int i = 20; i < 30; i++) { array[i - 20] = (char) i; } tw.append(new String(array)); expected.append(new String(array)); assertEquals(expected.toString(), sbw1.toString(), "ProxyCollectionWriter.append(CharSequence)"); assertEquals(expected.toString(), sbw2.toString(), "ProxyCollectionWriter.write(CharSequence)"); for (int i = 25; i < 35; i++) { array[i - 25] = (char) i; } tw.append(new String(array), 5, 5); expected.append(new String(array), 5, 5); assertEquals(expected.toString(), sbw1.toString(), "ProxyCollectionWriter.append(CharSequence, int, int)"); assertEquals(expected.toString(), sbw2.toString(), "ProxyCollectionWriter.append(CharSequence, int, int)"); expected.flush(); expected.close(); tw.flush(); } } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/output/ProxyOutputStreamTest.java0100644 0000000 0000000 00000003606 13612062727 032354 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import static org.junit.jupiter.api.Assertions.assertEquals; import java.io.IOException; import java.io.OutputStream; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * JUnit Test Case for {@link CloseShieldOutputStream}. */ public class ProxyOutputStreamTest { private ByteArrayOutputStream original; private OutputStream proxied; @BeforeEach public void setUp() { original = new ByteArrayOutputStream(){ @Override public void write(final byte[] ba) throws IOException { if (ba != null){ super.write(ba); } } }; proxied = new ProxyOutputStream(original); } @Test public void testWrite() throws Exception { proxied.write('y'); assertEquals(1, original.size()); assertEquals('y', original.toByteArray()[0]); } @Test public void testWriteNullBaSucceeds() throws Exception { final byte[] ba = null; original.write(ba); proxied.write(ba); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/output/ProxyWriterTest.java0100644 0000000 0000000 00000023567 13612062727 031164 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.UnsupportedEncodingException; import java.io.Writer; import org.junit.jupiter.api.Test; /** * Test {@link ProxyWriter}. * */ public class ProxyWriterTest { @Test public void appendCharSequence() throws Exception { try (final StringBuilderWriter writer = new StringBuilderWriter(); final ProxyWriter proxy = new ProxyWriter(writer)) { proxy.append("ABC"); assertEquals("ABC", writer.toString()); } } @Test public void appendCharSequence_with_offset() throws Exception { try (final StringBuilderWriter writer = new StringBuilderWriter(); final ProxyWriter proxy = new ProxyWriter(writer)) { proxy.append("ABC", 1, 3); proxy.flush(); assertEquals("BC", writer.toString()); } } @Test public void appendChar() throws Exception { try (final StringBuilderWriter writer = new StringBuilderWriter(); final ProxyWriter proxy = new ProxyWriter(writer)) { proxy.append('c'); assertEquals("c", writer.toString()); } } @Test public void writeString() throws Exception { try (final StringBuilderWriter writer = new StringBuilderWriter(); final ProxyWriter proxy = new ProxyWriter(writer)) { proxy.write("ABC"); assertEquals("ABC", writer.toString()); } } @Test public void writeStringPartial() throws Exception { try (final StringBuilderWriter writer = new StringBuilderWriter(); final ProxyWriter proxy = new ProxyWriter(writer)) { proxy.write("ABC", 1, 2); assertEquals("BC", writer.toString()); } } @Test public void writeCharArray() throws Exception { try (final StringBuilderWriter writer = new StringBuilderWriter(); final ProxyWriter proxy = new ProxyWriter(writer)) { proxy.write(new char[] { 'A', 'B', 'C' }); assertEquals("ABC", writer.toString()); } } @Test public void writeInt() throws Exception { try (final StringBuilderWriter writer = new StringBuilderWriter(); final ProxyWriter proxy = new ProxyWriter(writer)) { proxy.write(65); assertEquals("A", writer.toString()); } } @Test public void writeCharArrayPartial() throws Exception { try (final StringBuilderWriter writer = new StringBuilderWriter(); final ProxyWriter proxy = new ProxyWriter(writer)) { proxy.write(new char[] { 'A', 'B', 'C' }, 1, 2); assertEquals("BC", writer.toString()); } } @Test public void nullString() throws Exception { try (final ProxyWriter proxy = new ProxyWriter(NullWriter.NULL_WRITER)) { proxy.write((String) null); proxy.write((String) null, 0, 0); } } @Test public void nullCharArray() throws Exception { try (final ProxyWriter proxy = new ProxyWriter(NullWriter.NULL_WRITER)) { proxy.write((char[]) null); proxy.write((char[]) null, 0, 0); } } @Test public void nullCharSequence() throws Exception { try (final ProxyWriter proxy = new ProxyWriter(NullWriter.NULL_WRITER)) { proxy.append(null); } } @Test public void exceptions_in_append_char() throws IOException { try (final ByteArrayOutputStream baos = new ByteArrayOutputStream(); final OutputStreamWriter osw = new OutputStreamWriter(baos) { @Override public void write(final int c) throws IOException { throw new UnsupportedEncodingException("Bah"); } }) { try (ProxyWriter proxy = new ProxyWriter(osw)) { assertThrows(UnsupportedEncodingException.class, () -> proxy.append('c')); } } } @Test public void exceptions_in_append_charSequence() throws IOException { try (final OutputStreamWriter osw = new OutputStreamWriter(new ByteArrayOutputStream()) { @Override public Writer append(final CharSequence csq) throws IOException { throw new UnsupportedEncodingException("Bah"); } }) { try (ProxyWriter proxy = new ProxyWriter(osw)) { assertThrows(UnsupportedEncodingException.class, () -> proxy.append("ABCE")); } } } @Test public void exceptions_in_append_charSequence_offset() throws IOException { try (final OutputStreamWriter osw = new OutputStreamWriter(new ByteArrayOutputStream()) { @Override public Writer append(final CharSequence csq, final int start, final int end) throws IOException { throw new UnsupportedEncodingException("Bah"); } }) { try (ProxyWriter proxy = new ProxyWriter(osw)) { assertThrows(UnsupportedEncodingException.class, () -> proxy.append("ABCE", 1, 2)); } } } @Test public void exceptions_in_write_int() throws IOException { try (final OutputStreamWriter osw = new OutputStreamWriter(new ByteArrayOutputStream()) { @Override public void write(final int c) throws IOException { throw new UnsupportedEncodingException("Bah"); } }) { try (ProxyWriter proxy = new ProxyWriter(osw)) { assertThrows(UnsupportedEncodingException.class, () -> proxy.write('a')); } } } @Test public void exceptions_in_write_char_array() throws IOException { try (final OutputStreamWriter osw = new OutputStreamWriter(new ByteArrayOutputStream()) { @Override public void write(final char[] cbuf) throws IOException { throw new UnsupportedEncodingException("Bah"); } }) { try (ProxyWriter proxy = new ProxyWriter(osw)) { assertThrows(UnsupportedEncodingException.class, () -> proxy.write("ABCE".toCharArray())); } } } @Test public void exceptions_in_write_offset_char_array() throws IOException { try (final OutputStreamWriter osw = new OutputStreamWriter(new ByteArrayOutputStream()) { @Override public void write(final char[] cbuf, final int off, final int len) throws IOException { throw new UnsupportedEncodingException("Bah"); } }) { try (ProxyWriter proxy = new ProxyWriter(osw)) { assertThrows(UnsupportedEncodingException.class, () -> proxy.write("ABCE".toCharArray(), 2, 3)); } } } @Test public void exceptions_in_write_string() throws IOException { try (final OutputStreamWriter osw = new OutputStreamWriter(new ByteArrayOutputStream()) { @Override public void write(final String str) throws IOException { throw new UnsupportedEncodingException("Bah"); } }) { try (ProxyWriter proxy = new ProxyWriter(osw)) { assertThrows(UnsupportedEncodingException.class, () -> proxy.write("ABCE")); } } } @Test public void exceptions_in_write_string_offset() throws IOException { try (final OutputStreamWriter osw = new OutputStreamWriter(new ByteArrayOutputStream()) { @Override public void write(final String str, final int off, final int len) throws IOException { throw new UnsupportedEncodingException("Bah"); } }) { try (ProxyWriter proxy = new ProxyWriter(osw)) { assertThrows(UnsupportedEncodingException.class, () -> proxy.write("ABCE", 1, 3)); } } } @Test public void exceptions_in_flush() throws IOException { try (final OutputStreamWriter osw = new OutputStreamWriter(new ByteArrayOutputStream()) { @Override public void flush() throws IOException { throw new UnsupportedEncodingException("Bah"); } }) { try (ProxyWriter proxy = new ProxyWriter(osw)) { assertThrows(UnsupportedEncodingException.class, proxy::flush); } } } @Test public void exceptions_in_close() { assertThrows(UnsupportedEncodingException.class, () -> { try (final OutputStreamWriter osw = new OutputStreamWriter(new ByteArrayOutputStream()) { @Override public void close() throws IOException { throw new UnsupportedEncodingException("Bah"); } }) { try (final ProxyWriter proxy = new ProxyWriter(osw)) { // noop } } }); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/output/QueueOutputStreamTest.java0100644 0000000 0000000 00000011424 13612062727 032314 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import static java.nio.charset.StandardCharsets.UTF_8; import static java.util.concurrent.TimeUnit.SECONDS; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; import java.io.InterruptedIOException; import java.nio.charset.StandardCharsets; import java.util.concurrent.Callable; import java.util.concurrent.Exchanger; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.LinkedBlockingQueue; import org.apache.commons.io.IOUtils; import org.apache.commons.io.input.QueueInputStream; import org.apache.commons.io.input.QueueInputStreamTest; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Test; /** * Test {@link QueueOutputStream} and {@link QueueInputStream} * * @see QueueInputStreamTest */ public class QueueOutputStreamTest { private static final ExecutorService executorService = Executors.newFixedThreadPool(5); @AfterAll public static void afterAll() { executorService.shutdown(); } private static T callInThrowAwayThread(final Callable callable) throws Exception { final Exchanger exchanger = new Exchanger<>(); executorService.submit(() -> { final T value = callable.call(); exchanger.exchange(value); return null; }); return exchanger.exchange(null); } @Test public void testNullArgument() { assertThrows(NullPointerException.class, () -> new QueueOutputStream(null), "queue is required"); } @Test public void writeInterrupted() throws Exception { try (final QueueOutputStream outputStream = new QueueOutputStream(new LinkedBlockingQueue<>(1)); final QueueInputStream inputStream = outputStream.newQueueInputStream()) { final int timeout = 1; final Exchanger writerThreadExchanger = new Exchanger<>(); final Exchanger exceptionExchanger = new Exchanger<>(); executorService.submit(() -> { final Thread writerThread = writerThreadExchanger.exchange(null, timeout, SECONDS); writerThread.interrupt(); return null; }); executorService.submit(() -> { try { writerThreadExchanger.exchange(Thread.currentThread(), timeout, SECONDS); outputStream.write("ABC".getBytes(StandardCharsets.UTF_8)); } catch (final Exception e) { Thread.interrupted(); //clear interrupt exceptionExchanger.exchange(e, timeout, SECONDS); } return null; }); final Exception exception = exceptionExchanger.exchange(null, timeout, SECONDS); assertNotNull(exception); assertEquals(exception.getClass(), InterruptedIOException.class); } } @Test public void writeString() throws Exception { try (final QueueOutputStream outputStream = new QueueOutputStream(); final QueueInputStream inputStream = outputStream.newQueueInputStream()) { outputStream.write("ABC".getBytes(UTF_8)); final String value = IOUtils.toString(inputStream, UTF_8); assertEquals("ABC", value); } } @Test public void writeStringMultiThread() throws Exception { try (final QueueOutputStream outputStream = callInThrowAwayThread(QueueOutputStream::new); final QueueInputStream inputStream = callInThrowAwayThread(outputStream::newQueueInputStream)) { callInThrowAwayThread(() -> { outputStream.write("ABC".getBytes(UTF_8)); return null; }); final String value = callInThrowAwayThread(() -> IOUtils.toString(inputStream, UTF_8)); assertEquals("ABC", value); } } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/output/StringBuilderWriterTest.java0100644 0000000 0000000 00000012007 13612062727 032603 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.fail; import java.io.IOException; import java.io.Writer; import org.junit.jupiter.api.Test; /** * Test case for {@link StringBuilderWriter}. * */ public class StringBuilderWriterTest { private static final char[] FOOBAR_CHARS = {'F', 'o', 'o', 'B', 'a', 'r'}; @Test public void testAppendConstructCapacity() throws IOException { try (final Writer writer = new StringBuilderWriter(100)) { writer.append("Foo"); assertEquals("Foo", writer.toString()); } } @Test public void testAppendConstructStringBuilder() { final StringBuilder builder = new StringBuilder("Foo"); try (final StringBuilderWriter writer = new StringBuilderWriter(builder)) { writer.append("Bar"); assertEquals("FooBar", writer.toString()); assertSame(builder, writer.getBuilder()); } } @Test public void testAppendConstructNull() throws IOException { try (final Writer writer = new StringBuilderWriter(null)) { writer.append("Foo"); assertEquals("Foo", writer.toString()); } } @Test public void testAppendChar() throws IOException { try (final Writer writer = new StringBuilderWriter()) { writer.append('F').append('o').append('o'); assertEquals("Foo", writer.toString()); } } @Test public void testAppendCharSequence() throws IOException { try (final Writer writer = new StringBuilderWriter()) { writer.append("Foo").append("Bar"); assertEquals("FooBar", writer.toString()); } } @Test public void testAppendCharSequencePortion() throws IOException { try (final Writer writer = new StringBuilderWriter()) { writer.append("FooBar", 3, 6).append(new StringBuffer("FooBar"), 0, 3); assertEquals("BarFoo", writer.toString()); } } @Test public void testClose() throws IOException { try (final Writer writer = new StringBuilderWriter()) { try { writer.append("Foo"); writer.close(); writer.append("Bar"); } catch (final Throwable t) { fail("Threw: " + t); } assertEquals("FooBar", writer.toString()); } } @Test public void testWriteChar() throws IOException { try (final Writer writer = new StringBuilderWriter()) { writer.write('F'); assertEquals("F", writer.toString()); writer.write('o'); assertEquals("Fo", writer.toString()); writer.write('o'); assertEquals("Foo", writer.toString()); } } @Test public void testWriteCharArray() throws IOException { try (final Writer writer = new StringBuilderWriter()) { writer.write(new char[] { 'F', 'o', 'o' }); assertEquals("Foo", writer.toString()); writer.write(new char[] { 'B', 'a', 'r' }); assertEquals("FooBar", writer.toString()); } } @Test public void testWriteCharArrayPortion() throws IOException { try (final Writer writer = new StringBuilderWriter()) { writer.write(FOOBAR_CHARS, 3, 3); assertEquals("Bar", writer.toString()); writer.write(FOOBAR_CHARS, 0, 3); assertEquals("BarFoo", writer.toString()); } } @Test public void testWriteString() throws IOException { try (final Writer writer = new StringBuilderWriter()) { writer.write("Foo"); assertEquals("Foo", writer.toString()); writer.write("Bar"); assertEquals("FooBar", writer.toString()); } } @Test public void testWriteStringPortion() throws IOException { try (final Writer writer = new StringBuilderWriter()) { writer.write("FooBar", 3, 3); assertEquals("Bar", writer.toString()); writer.write("FooBar", 0, 3); assertEquals("BarFoo", writer.toString()); } } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/output/TaggedOutputStreamTest.java0100644 0000000 0000000 00000010547 13612062727 032430 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import java.io.IOException; import java.io.OutputStream; import java.util.UUID; import org.apache.commons.io.TaggedIOException; import org.junit.jupiter.api.Test; /** * JUnit Test Case for {@link TaggedOutputStream}. */ public class TaggedOutputStreamTest { @Test public void testNormalStream() { try (final ByteArrayOutputStream buffer = new ByteArrayOutputStream()) { try (final OutputStream stream = new TaggedOutputStream(buffer)) { stream.write('a'); stream.write(new byte[] { 'b' }); stream.write(new byte[] { 'c' }, 0, 1); stream.flush(); } assertEquals(3, buffer.size()); assertEquals('a', buffer.toByteArray()[0]); assertEquals('b', buffer.toByteArray()[1]); assertEquals('c', buffer.toByteArray()[2]); } catch (final IOException e) { fail("Unexpected exception thrown"); } } @Test public void testBrokenStream() { final IOException exception = new IOException("test exception"); final TaggedOutputStream stream = new TaggedOutputStream(new BrokenOutputStream(exception)); // Test the write() method try { stream.write('x'); fail("Expected exception not thrown."); } catch (final IOException e) { assertTrue(stream.isCauseOf(e)); try { stream.throwIfCauseOf(e); fail("Expected exception not thrown."); } catch (final IOException e2) { assertEquals(exception, e2); } } // Test the flush() method try { stream.flush(); fail("Expected exception not thrown."); } catch (final IOException e) { assertTrue(stream.isCauseOf(e)); try { stream.throwIfCauseOf(e); fail("Expected exception not thrown."); } catch (final IOException e2) { assertEquals(exception, e2); } } // Test the close() method try { stream.close(); fail("Expected exception not thrown."); } catch (final IOException e) { assertTrue(stream.isCauseOf(e)); try { stream.throwIfCauseOf(e); fail("Expected exception not thrown."); } catch (final IOException e2) { assertEquals(exception, e2); } } } @Test public void testOtherException() throws Exception { final IOException exception = new IOException("test exception"); try (final TaggedOutputStream stream = new TaggedOutputStream(ClosedOutputStream.CLOSED_OUTPUT_STREAM)) { assertFalse(stream.isCauseOf(exception)); assertFalse(stream.isCauseOf(new TaggedIOException(exception, UUID.randomUUID()))); try { stream.throwIfCauseOf(exception); } catch (final IOException e) { fail("Unexpected exception thrown"); } try { stream.throwIfCauseOf(new TaggedIOException(exception, UUID.randomUUID())); } catch (final IOException e) { fail("Unexpected exception thrown"); } } } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/output/TaggedWriterTest.java0100644 0000000 0000000 00000010520 13612062727 031217 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import java.io.IOException; import java.io.Writer; import java.util.UUID; import org.apache.commons.io.TaggedIOException; import org.junit.jupiter.api.Test; /** * JUnit Test Case for {@link TaggedWriter}. */ public class TaggedWriterTest { @Test public void testNormalWriter() { try (final StringBuilderWriter buffer = new StringBuilderWriter()) { try (final Writer writer = new TaggedWriter(buffer)) { writer.write('a'); writer.write(new char[] { 'b' }); writer.write(new char[] { 'c' }, 0, 1); writer.flush(); } assertEquals(3, buffer.getBuilder().length()); assertEquals('a', buffer.getBuilder().charAt(0)); assertEquals('b', buffer.getBuilder().charAt(1)); assertEquals('c', buffer.getBuilder().charAt(2)); } catch (final IOException e) { fail("Unexpected exception thrown"); } } @Test public void testBrokenWriter() { final IOException exception = new IOException("test exception"); final TaggedWriter writer = new TaggedWriter(new BrokenWriter(exception)); // Test the write() method try { writer.write(new char[] { 'x' }, 0, 1); fail("Expected exception not thrown."); } catch (final IOException e) { assertTrue(writer.isCauseOf(e)); try { writer.throwIfCauseOf(e); fail("Expected exception not thrown."); } catch (final IOException e2) { assertEquals(exception, e2); } } // Test the flush() method try { writer.flush(); fail("Expected exception not thrown."); } catch (final IOException e) { assertTrue(writer.isCauseOf(e)); try { writer.throwIfCauseOf(e); fail("Expected exception not thrown."); } catch (final IOException e2) { assertEquals(exception, e2); } } // Test the close() method try { writer.close(); fail("Expected exception not thrown."); } catch (final IOException e) { assertTrue(writer.isCauseOf(e)); try { writer.throwIfCauseOf(e); fail("Expected exception not thrown."); } catch (final IOException e2) { assertEquals(exception, e2); } } } @Test public void testOtherException() throws Exception { final IOException exception = new IOException("test exception"); try (final TaggedWriter writer = new TaggedWriter(ClosedWriter.CLOSED_WRITER)) { assertFalse(writer.isCauseOf(exception)); assertFalse(writer.isCauseOf(new TaggedIOException(exception, UUID.randomUUID()))); try { writer.throwIfCauseOf(exception); } catch (final IOException e) { fail("Unexpected exception thrown"); } try { writer.throwIfCauseOf(new TaggedIOException(exception, UUID.randomUUID())); } catch (final IOException e) { fail("Unexpected exception thrown"); } } } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/output/TeeOutputStreamTest.java0100644 0000000 0000000 00000011145 13612062727 031745 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import org.apache.commons.io.test.ThrowOnCloseOutputStream; import org.junit.jupiter.api.Test; /**On * JUnit Test Case for {@link TeeOutputStream}. */ public class TeeOutputStreamTest { /** * Tests that the branch {@code OutputStream} is closed when closing the main {@code OutputStream} throws an * exception on {@link TeeOutputStream#close()}. */ @Test public void testIOExceptionOnCloseBranch() throws IOException { final OutputStream badOs = new ThrowOnCloseOutputStream(); final ByteArrayOutputStream goodOs = mock(ByteArrayOutputStream.class); final TeeOutputStream tos = new TeeOutputStream(goodOs, badOs); try { tos.close(); fail("Expected " + IOException.class.getName()); } catch (final IOException e) { verify(goodOs).close(); } } /** * Tests that the main {@code OutputStream} is closed when closing the branch {@code OutputStream} throws an * exception on {@link TeeOutputStream#close()}. */ @Test public void testIOExceptionOnClose() throws IOException { final OutputStream badOs = new ThrowOnCloseOutputStream(); final ByteArrayOutputStream goodOs = mock(ByteArrayOutputStream.class); final TeeOutputStream tos = new TeeOutputStream(badOs, goodOs); try { tos.close(); fail("Expected " + IOException.class.getName()); } catch (final IOException e) { verify(goodOs).close(); } } @Test public void testTee() throws IOException { final ByteArrayOutputStream baos1 = new ByteArrayOutputStream(); final ByteArrayOutputStream baos2 = new ByteArrayOutputStream(); final ByteArrayOutputStream expected = new ByteArrayOutputStream(); try (final TeeOutputStream tos = new TeeOutputStream(baos1, baos2)) { for (int i = 0; i < 20; i++) { tos.write(i); expected.write(i); } assertByteArrayEquals("TeeOutputStream.write(int)", expected.toByteArray(), baos1.toByteArray()); assertByteArrayEquals("TeeOutputStream.write(int)", expected.toByteArray(), baos2.toByteArray()); final byte[] array = new byte[10]; for (int i = 20; i < 30; i++) { array[i - 20] = (byte) i; } tos.write(array); expected.write(array); assertByteArrayEquals("TeeOutputStream.write(byte[])", expected.toByteArray(), baos1.toByteArray()); assertByteArrayEquals("TeeOutputStream.write(byte[])", expected.toByteArray(), baos2.toByteArray()); for (int i = 25; i < 35; i++) { array[i - 25] = (byte) i; } tos.write(array, 5, 5); expected.write(array, 5, 5); assertByteArrayEquals("TeeOutputStream.write(byte[], int, int)", expected.toByteArray(), baos1.toByteArray()); assertByteArrayEquals("TeeOutputStream.write(byte[], int, int)", expected.toByteArray(), baos2.toByteArray()); expected.flush(); expected.close(); tos.flush(); } } private void assertByteArrayEquals(final String msg, final byte[] array1, final byte[] array2) { assertEquals(array1.length, array2.length, msg + ": array size mismatch"); for (int i = 0; i < array1.length; i++) { assertEquals(array1[i], array2[i], msg + ": array[ " + i + "] mismatch"); } } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/output/TeeWriterTest.java0100644 0000000 0000000 00000042660 13612062727 030553 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import java.io.IOException; import java.io.StringWriter; import java.io.Writer; import java.util.Arrays; import java.util.Collection; import org.apache.commons.io.IOExceptionList; import org.apache.commons.io.IOIndexedException; import org.junit.jupiter.api.Test; /** * JUnit Test Case for {@link TeeWriter}. */ @SuppressWarnings("resource") // not necessary to close these resources public class TeeWriterTest { @Test public void testArrayIOExceptionOnAppendChar1() throws IOException { final Writer badW = new BrokenWriter(); final StringWriter goodW = mock(StringWriter.class); final ProxyCollectionWriter tw = new ProxyCollectionWriter(badW, goodW, null); final char data = 'A'; try { tw.append(data); fail("Expected " + IOException.class.getName()); } catch (final IOExceptionList e) { verify(goodW).append(data); assertEquals(1, e.getCauseList().size()); assertEquals(0, e.getCause(0, IOIndexedException.class).getIndex()); } } @Test public void testArrayIOExceptionOnAppendChar2() throws IOException { final Writer badW = new BrokenWriter(); final StringWriter goodW = mock(StringWriter.class); final ProxyCollectionWriter tw = new ProxyCollectionWriter(goodW, badW, null); final char data = 'A'; try { tw.append(data); fail("Expected " + IOException.class.getName()); } catch (final IOExceptionList e) { verify(goodW).append(data); assertEquals(1, e.getCauseList().size()); assertEquals(1, e.getCause(0, IOIndexedException.class).getIndex()); } } @Test public void testArrayIOExceptionOnAppendCharSequence1() throws IOException { final Writer badW = new BrokenWriter(); final StringWriter goodW = mock(StringWriter.class); final TeeWriter tw = new TeeWriter(badW, goodW, null); final String data = "A"; try { tw.append(data); fail("Expected " + IOException.class.getName()); } catch (final IOExceptionList e) { verify(goodW).append(data); assertEquals(1, e.getCauseList().size()); assertEquals(0, e.getCause(0, IOIndexedException.class).getIndex()); } } @Test public void testArrayIOExceptionOnAppendCharSequence2() throws IOException { final Writer badW = new BrokenWriter(); final StringWriter goodW = mock(StringWriter.class); final TeeWriter tw = new TeeWriter(goodW, badW, null); final String data = "A"; try { tw.append(data); fail("Expected " + IOException.class.getName()); } catch (final IOExceptionList e) { verify(goodW).append(data); assertEquals(1, e.getCauseList().size()); assertEquals(1, e.getCause(0, IOIndexedException.class).getIndex()); } } @Test public void testArrayIOExceptionOnAppendCharSequenceIntInt1() throws IOException { final Writer badW = new BrokenWriter(); final StringWriter goodW = mock(StringWriter.class); final TeeWriter tw = new TeeWriter(badW, goodW, null); final String data = "A"; try { tw.append(data, 0, 0); fail("Expected " + IOException.class.getName()); } catch (final IOExceptionList e) { verify(goodW).append(data, 0, 0); assertEquals(1, e.getCauseList().size()); assertEquals(0, e.getCause(0, IOIndexedException.class).getIndex()); } } @Test public void testArrayIOExceptionOnAppendCharSequenceIntInt2() throws IOException { final Writer badW = new BrokenWriter(); final StringWriter goodW = mock(StringWriter.class); final TeeWriter tw = new TeeWriter(goodW, badW, null); final String data = "A"; try { tw.append(data, 0, 0); fail("Expected " + IOException.class.getName()); } catch (final IOExceptionList e) { verify(goodW).append(data, 0, 0); assertEquals(1, e.getCauseList().size()); assertEquals(1, e.getCause(0, IOIndexedException.class).getIndex()); } } @Test public void testArrayIOExceptionOnClose1() throws IOException { final Writer badW = new BrokenWriter(); final StringWriter goodW = mock(StringWriter.class); final TeeWriter tw = new TeeWriter(badW, goodW, null); try { tw.close(); fail("Expected " + IOException.class.getName()); } catch (final IOExceptionList e) { verify(goodW).close(); assertEquals(1, e.getCauseList().size()); assertEquals(0, e.getCause(0, IOIndexedException.class).getIndex()); } } @Test public void testArrayIOExceptionOnClose2() throws IOException { final Writer badW = new BrokenWriter(); final StringWriter goodW = mock(StringWriter.class); final TeeWriter tw = new TeeWriter(goodW, badW, null); try { tw.close(); fail("Expected " + IOException.class.getName()); } catch (final IOExceptionList e) { verify(goodW).close(); assertEquals(1, e.getCauseList().size()); assertEquals(1, e.getCause(0, IOIndexedException.class).getIndex()); } } @Test public void testArrayIOExceptionOnFlush1() throws IOException { final Writer badW = new BrokenWriter(); final StringWriter goodW = mock(StringWriter.class); final TeeWriter tw = new TeeWriter(badW, goodW, null); try { tw.flush(); fail("Expected " + IOException.class.getName()); } catch (final IOExceptionList e) { verify(goodW).flush(); assertEquals(1, e.getCauseList().size()); assertEquals(0, e.getCause(0, IOIndexedException.class).getIndex()); } } @Test public void testArrayIOExceptionOnFlush2() throws IOException { final Writer badW = new BrokenWriter(); final StringWriter goodW = mock(StringWriter.class); final TeeWriter tw = new TeeWriter(goodW, badW, null); try { tw.flush(); fail("Expected " + IOException.class.getName()); } catch (final IOExceptionList e) { verify(goodW).flush(); assertEquals(1, e.getCauseList().size()); assertEquals(1, e.getCause(0, IOIndexedException.class).getIndex()); } } @Test public void testArrayIOExceptionOnWriteCharArray1() throws IOException { final Writer badW = new BrokenWriter(); final StringWriter goodW = mock(StringWriter.class); final TeeWriter tw = new TeeWriter(badW, goodW, null); final char[] data = { 'a' }; try { tw.write(data); fail("Expected " + IOException.class.getName()); } catch (final IOExceptionList e) { verify(goodW).write(data); assertEquals(1, e.getCauseList().size()); assertEquals(0, e.getCause(0, IOIndexedException.class).getIndex()); } } @Test public void testArrayIOExceptionOnWriteCharArray2() throws IOException { final Writer badW = new BrokenWriter(); final StringWriter goodW = mock(StringWriter.class); final TeeWriter tw = new TeeWriter(goodW, badW, null); final char[] data = { 'a' }; try { tw.write(data); fail("Expected " + IOException.class.getName()); } catch (final IOExceptionList e) { verify(goodW).write(data); assertEquals(1, e.getCauseList().size()); assertEquals(1, e.getCause(0, IOIndexedException.class).getIndex()); } } @Test public void testArrayIOExceptionOnWriteCharArrayIntInt1() throws IOException { final Writer badW = new BrokenWriter(); final StringWriter goodW = mock(StringWriter.class); final TeeWriter tw = new TeeWriter(badW, goodW, null); final char[] data = { 'a' }; try { tw.write(data, 0, 0); fail("Expected " + IOException.class.getName()); } catch (final IOExceptionList e) { verify(goodW).write(data, 0, 0); assertEquals(1, e.getCauseList().size()); assertEquals(0, e.getCause(0, IOIndexedException.class).getIndex()); } } @Test public void testArrayIOExceptionOnWriteCharArrayIntInt2() throws IOException { final Writer badW = new BrokenWriter(); final StringWriter goodW = mock(StringWriter.class); final TeeWriter tw = new TeeWriter(goodW, badW, null); final char[] data = { 'a' }; try { tw.write(data, 0, 0); fail("Expected " + IOException.class.getName()); } catch (final IOExceptionList e) { verify(goodW).write(data, 0, 0); assertEquals(1, e.getCauseList().size()); assertEquals(1, e.getCause(0, IOIndexedException.class).getIndex()); } } @Test public void testArrayIOExceptionOnWriteInt1() throws IOException { final Writer badW = new BrokenWriter(); final StringWriter goodW = mock(StringWriter.class); final TeeWriter tw = new TeeWriter(badW, goodW, null); final int data = 32; try { tw.write(data); fail("Expected " + IOException.class.getName()); } catch (final IOExceptionList e) { verify(goodW).write(data); assertEquals(1, e.getCauseList().size()); assertEquals(0, e.getCause(0, IOIndexedException.class).getIndex()); } } @Test public void testArrayIOExceptionOnWriteInt2() throws IOException { final Writer badW = new BrokenWriter(); final StringWriter goodW = mock(StringWriter.class); final TeeWriter tw = new TeeWriter(goodW, badW, null); try { tw.write(32); fail("Expected " + IOException.class.getName()); } catch (final IOExceptionList e) { verify(goodW).write(32); assertEquals(1, e.getCauseList().size()); assertEquals(1, e.getCause(0, IOIndexedException.class).getIndex()); } } @Test public void testArrayIOExceptionOnWriteString1() throws IOException { final Writer badW = new BrokenWriter(); final StringWriter goodW = mock(StringWriter.class); final TeeWriter tw = new TeeWriter(badW, goodW, null); final String data = "A"; try { tw.write(data); fail("Expected " + IOException.class.getName()); } catch (final IOExceptionList e) { verify(goodW).write(data); assertEquals(1, e.getCauseList().size()); assertEquals(0, e.getCause(0, IOIndexedException.class).getIndex()); } } @Test public void testArrayIOExceptionOnWriteString2() throws IOException { final Writer badW = new BrokenWriter(); final StringWriter goodW = mock(StringWriter.class); final TeeWriter tw = new TeeWriter(goodW, badW, null); final String data = "A"; try { tw.write(data); fail("Expected " + IOException.class.getName()); } catch (final IOExceptionList e) { verify(goodW).write(data); assertEquals(1, e.getCauseList().size()); assertEquals(1, e.getCause(0, IOIndexedException.class).getIndex()); } } @Test public void testArrayIOExceptionOnWriteStringIntInt1() throws IOException { final Writer badW = new BrokenWriter(); final StringWriter goodW = mock(StringWriter.class); final TeeWriter tw = new TeeWriter(badW, goodW, null); final String data = "A"; try { tw.write(data, 0, 0); fail("Expected " + IOException.class.getName()); } catch (final IOExceptionList e) { verify(goodW).write(data, 0, 0); assertEquals(1, e.getCauseList().size()); assertEquals(0, e.getCause(0, IOIndexedException.class).getIndex()); } } @Test public void testArrayIOExceptionOnWriteStringIntInt2() throws IOException { final Writer badW = new BrokenWriter(); final StringWriter goodW = mock(StringWriter.class); final TeeWriter tw = new TeeWriter(goodW, badW, null); final String data = "A"; try { tw.write(data, 0, 0); fail("Expected " + IOException.class.getName()); } catch (final IOExceptionList e) { verify(goodW).write(data, 0, 0); assertEquals(1, e.getCauseList().size()); assertEquals(1, e.getCause(0, IOIndexedException.class).getIndex()); } } @Test public void testCollectionCloseBranchIOException() throws IOException { final Writer badW = new BrokenWriter(); final StringWriter goodW = mock(StringWriter.class); final TeeWriter tw = new TeeWriter(Arrays.asList(goodW, badW, null)); try { tw.close(); fail("Expected " + IOException.class.getName()); } catch (final IOExceptionList e) { verify(goodW).close(); assertEquals(1, e.getCauseList().size()); assertEquals(1, e.getCause(0, IOIndexedException.class).getIndex()); } } @Test public void testConstructorsNull() throws IOException { try (final TeeWriter teeWriter = new TeeWriter((Writer[]) null)) { // Call any method, should not throw teeWriter.append('a'); teeWriter.flush(); } try (final TeeWriter teeWriter = new TeeWriter((Collection) null)) { // Call any method, should not throw teeWriter.append('a'); teeWriter.flush(); } assertTrue(true, "Dummy to show test completed OK"); } @Test public void testTee() throws IOException { final StringBuilderWriter sbw1 = new StringBuilderWriter(); final StringBuilderWriter sbw2 = new StringBuilderWriter(); final StringBuilderWriter expected = new StringBuilderWriter(); try (final TeeWriter tw = new TeeWriter(sbw1, sbw2, null)) { for (int i = 0; i < 20; i++) { tw.write(i); expected.write(i); } assertEquals(expected.toString(), sbw1.toString(), "TeeWriter.write(int)"); assertEquals(expected.toString(), sbw2.toString(), "TeeWriter.write(int)"); final char[] array = new char[10]; for (int i = 20; i < 30; i++) { array[i - 20] = (char) i; } tw.write(array); expected.write(array); assertEquals(expected.toString(), sbw1.toString(), "TeeWriter.write(char[])"); assertEquals(expected.toString(), sbw2.toString(), "TeeWriter.write(char[])"); for (int i = 25; i < 35; i++) { array[i - 25] = (char) i; } tw.write(array, 5, 5); expected.write(array, 5, 5); assertEquals(expected.toString(), sbw1.toString(), "TeeOutputStream.write(byte[], int, int)"); assertEquals(expected.toString(), sbw2.toString(), "TeeOutputStream.write(byte[], int, int)"); for (int i = 0; i < 20; i++) { tw.append((char) i); expected.append((char) i); } assertEquals(expected.toString(), sbw1.toString(), "TeeWriter.append(char)"); assertEquals(expected.toString(), sbw2.toString(), "TeeWriter.append(char)"); for (int i = 20; i < 30; i++) { array[i - 20] = (char) i; } tw.append(new String(array)); expected.append(new String(array)); assertEquals(expected.toString(), sbw1.toString(), "TeeWriter.append(CharSequence)"); assertEquals(expected.toString(), sbw2.toString(), "TeeWriter.append(CharSequence)"); for (int i = 25; i < 35; i++) { array[i - 25] = (char) i; } tw.append(new String(array), 5, 5); expected.append(new String(array), 5, 5); assertEquals(expected.toString(), sbw1.toString(), "TeeWriter.append(CharSequence, int, int)"); assertEquals(expected.toString(), sbw2.toString(), "TeeWriter.append(CharSequence, int, int)"); expected.flush(); expected.close(); tw.flush(); } } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/output/ThresholdingOutputStreamTest.java0100644 0000000 0000000 00000007531 13612062727 033666 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; import java.io.OutputStream; import java.util.concurrent.atomic.AtomicBoolean; import org.junit.jupiter.api.Test; public class ThresholdingOutputStreamTest { @Test public void testSetByteCount() throws Exception { final AtomicBoolean reached = new AtomicBoolean(false); try (final ThresholdingOutputStream tos = new ThresholdingOutputStream(3) { { setByteCount(2); } @Override protected OutputStream getStream() throws IOException { return new ByteArrayOutputStream(4); } @Override protected void thresholdReached() throws IOException { reached.set(true); } }) { tos.write('a'); assertFalse(reached.get()); tos.write('a'); assertTrue(reached.get()); } } @Test public void testThresholdIOConsumer() throws Exception { final AtomicBoolean reached = new AtomicBoolean(); // Null threshold consumer reached.set(false); try (final ThresholdingOutputStream tos = new ThresholdingOutputStream(1, null, os -> new ByteArrayOutputStream(4))) { tos.write('a'); assertFalse(reached.get()); tos.write('a'); assertFalse(reached.get()); } // Null output stream function reached.set(false); try (final ThresholdingOutputStream tos = new ThresholdingOutputStream(1, os -> reached.set(true), null)) { tos.write('a'); assertFalse(reached.get()); tos.write('a'); assertTrue(reached.get()); } // non-null inputs. reached.set(false); try (final ThresholdingOutputStream tos = new ThresholdingOutputStream(1, os -> reached.set(true), os -> new ByteArrayOutputStream(4))) { tos.write('a'); assertFalse(reached.get()); tos.write('a'); assertTrue(reached.get()); } } @Test public void testThresholdIOConsumerIOException() throws Exception { try (final ThresholdingOutputStream tos = new ThresholdingOutputStream(1, os -> { throw new IOException("Threshold reached."); }, os -> new ByteArrayOutputStream(4))) { tos.write('a'); assertThrows(IOException.class, () -> tos.write('a')); } } @Test public void testThresholdIOConsumerUncheckedException() throws Exception { try (final ThresholdingOutputStream tos = new ThresholdingOutputStream(1, os -> { throw new IllegalStateException("Threshold reached."); }, os -> new ByteArrayOutputStream(4))) { tos.write('a'); assertThrows(IllegalStateException.class, () -> tos.write('a')); } } }commons-io-2.11.0-src/src/test/java/org/apache/commons/io/output/WriterOutputStreamTest.java0100644 0000000 0000000 00000012515 13612062727 032506 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; import java.io.IOException; import java.io.StringWriter; import java.nio.charset.StandardCharsets; import java.util.Random; import org.junit.jupiter.api.Test; public class WriterOutputStreamTest { private static final String TEST_STRING = "\u00e0 peine arriv\u00e9s nous entr\u00e2mes dans sa chambre"; private static final String LARGE_TEST_STRING; static { final StringBuilder buffer = new StringBuilder(); for (int i=0; i<100; i++) { buffer.append(TEST_STRING); } LARGE_TEST_STRING = buffer.toString(); } private final Random random = new Random(); private void testWithSingleByteWrite(final String testString, final String charsetName) throws IOException { final byte[] bytes = testString.getBytes(charsetName); final StringWriter writer = new StringWriter(); try (final WriterOutputStream out = new WriterOutputStream(writer, charsetName)) { for (final byte b : bytes) { out.write(b); } } assertEquals(testString, writer.toString()); } private void testWithBufferedWrite(final String testString, final String charsetName) throws IOException { final byte[] expected = testString.getBytes(charsetName); final StringWriter writer = new StringWriter(); try (final WriterOutputStream out = new WriterOutputStream(writer, charsetName)) { int offset = 0; while (offset < expected.length) { final int length = Math.min(random.nextInt(128), expected.length - offset); out.write(expected, offset, length); offset += length; } } assertEquals(testString, writer.toString()); } @Test public void testUTF8WithSingleByteWrite() throws IOException { testWithSingleByteWrite(TEST_STRING, "UTF-8"); } @Test public void testLargeUTF8WithSingleByteWrite() throws IOException { testWithSingleByteWrite(LARGE_TEST_STRING, "UTF-8"); } @Test public void testUTF8WithBufferedWrite() throws IOException { testWithBufferedWrite(TEST_STRING, "UTF-8"); } @Test public void testLargeUTF8WithBufferedWrite() throws IOException { testWithBufferedWrite(LARGE_TEST_STRING, "UTF-8"); } @Test public void testUTF16WithSingleByteWrite() throws IOException { try { testWithSingleByteWrite(TEST_STRING, "UTF-16"); } catch (final UnsupportedOperationException e){ if (!System.getProperty("java.vendor").contains("IBM")){ fail("This test should only throw UOE on IBM JDKs with broken UTF-16"); } } } @Test public void testUTF16WithBufferedWrite() throws IOException { try { testWithBufferedWrite(TEST_STRING, "UTF-16"); } catch (final UnsupportedOperationException e) { if (!System.getProperty("java.vendor").contains("IBM")) { fail("This test should only throw UOE on IBM JDKs with broken UTF-16"); } } } @Test public void testUTF16BEWithSingleByteWrite() throws IOException { testWithSingleByteWrite(TEST_STRING, "UTF-16BE"); } @Test public void testUTF16BEWithBufferedWrite() throws IOException { testWithBufferedWrite(TEST_STRING, "UTF-16BE"); } @Test public void testUTF16LEWithSingleByteWrite() throws IOException { testWithSingleByteWrite(TEST_STRING, "UTF-16LE"); } @Test public void testUTF16LEWithBufferedWrite() throws IOException { testWithBufferedWrite(TEST_STRING, "UTF-16LE"); } @Test public void testFlush() throws IOException { final StringWriter writer = new StringWriter(); try (final WriterOutputStream out = new WriterOutputStream(writer, "us-ascii", 1024, false)) { out.write("abc".getBytes(StandardCharsets.US_ASCII)); assertEquals(0, writer.getBuffer().length()); out.flush(); assertEquals("abc", writer.toString()); } } @Test public void testWriteImmediately() throws IOException { final StringWriter writer = new StringWriter(); try (final WriterOutputStream out = new WriterOutputStream(writer, "us-ascii", 1024, true)) { out.write("abc".getBytes(StandardCharsets.US_ASCII)); assertEquals("abc", writer.toString()); } } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/output/XmlStreamWriterTest.java0100644 0000000 0000000 00000012675 13612062727 031755 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.output; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.ByteArrayOutputStream; import java.io.IOException; import org.junit.jupiter.api.Test; import org.junitpioneer.jupiter.DefaultLocale; /** */ public class XmlStreamWriterTest { /** french */ private static final String TEXT_LATIN1 = "eacute: \u00E9"; /** greek */ private static final String TEXT_LATIN7 = "alpha: \u03B1"; /** euro support */ private static final String TEXT_LATIN15 = "euro: \u20AC"; /** japanese */ private static final String TEXT_EUC_JP = "hiragana A: \u3042"; /** Unicode: support everything */ private static final String TEXT_UNICODE = TEXT_LATIN1 + ", " + TEXT_LATIN7 + ", " + TEXT_LATIN15 + ", " + TEXT_EUC_JP; private static String createXmlContent(final String text, final String encoding) { String xmlDecl = ""; if (encoding != null) { xmlDecl = ""; } return xmlDecl + "\n" + text + ""; } private static void checkXmlContent(final String xml, final String encoding, final String defaultEncoding) throws IOException { final ByteArrayOutputStream out = new ByteArrayOutputStream(); final XmlStreamWriter writer = new XmlStreamWriter(out, defaultEncoding); writer.write(xml); writer.close(); final byte[] xmlContent = out.toByteArray(); assertTrue(encoding.equalsIgnoreCase(writer.getEncoding())); assertArrayEquals(xml.getBytes(encoding), xmlContent); } private static void checkXmlWriter(final String text, final String encoding) throws IOException { checkXmlWriter(text, encoding, null); } private static void checkXmlWriter(final String text, final String encoding, final String defaultEncoding) throws IOException { final String xml = createXmlContent(text, encoding); String effectiveEncoding = encoding; if (effectiveEncoding == null) { effectiveEncoding = defaultEncoding == null ? "UTF-8" : defaultEncoding; } checkXmlContent(xml, effectiveEncoding, defaultEncoding); } @Test public void testNoXmlHeader() throws IOException { final String xml = "text with no XML header"; checkXmlContent(xml, "UTF-8", null); } @Test public void testEmpty() throws IOException { final ByteArrayOutputStream out = new ByteArrayOutputStream(); try (final XmlStreamWriter writer = new XmlStreamWriter(out)) { writer.flush(); writer.write(""); writer.flush(); writer.write("."); writer.flush(); } } @Test public void testDefaultEncoding() throws IOException { checkXmlWriter(TEXT_UNICODE, null, null); checkXmlWriter(TEXT_UNICODE, null, "UTF-8"); checkXmlWriter(TEXT_UNICODE, null, "UTF-16"); checkXmlWriter(TEXT_UNICODE, null, "UTF-16BE"); checkXmlWriter(TEXT_UNICODE, null, "ISO-8859-1"); } // Turkish language has specific rules to convert dotted and dottless i character. @Test @DefaultLocale(language = "tr") public void testLowerCaseEncodingWithTurkishLocale_IO_557() throws IOException { checkXmlWriter(TEXT_UNICODE, "utf-8"); checkXmlWriter(TEXT_LATIN1, "iso-8859-1"); checkXmlWriter(TEXT_LATIN7, "iso-8859-7"); } @Test public void testUTF8Encoding() throws IOException { checkXmlWriter(TEXT_UNICODE, "UTF-8"); } @Test public void testUTF16Encoding() throws IOException { checkXmlWriter(TEXT_UNICODE, "UTF-16"); } @Test public void testUTF16BEEncoding() throws IOException { checkXmlWriter(TEXT_UNICODE, "UTF-16BE"); } @Test public void testUTF16LEEncoding() throws IOException { checkXmlWriter(TEXT_UNICODE, "UTF-16LE"); } @Test public void testLatin1Encoding() throws IOException { checkXmlWriter(TEXT_LATIN1, "ISO-8859-1"); } @Test public void testLatin7Encoding() throws IOException { checkXmlWriter(TEXT_LATIN7, "ISO-8859-7"); } @Test public void testLatin15Encoding() throws IOException { checkXmlWriter(TEXT_LATIN15, "ISO-8859-15"); } @Test public void testEUC_JPEncoding() throws IOException { checkXmlWriter(TEXT_EUC_JP, "EUC-JP"); } @Test public void testEBCDICEncoding() throws IOException { checkXmlWriter("simple text in EBCDIC", "CP1047"); } } ././@LongLink0100644 0000000 0000000 00000000147 13612062727 011643 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/java/org/apache/commons/io/serialization/AbstractCloseableListTest.javacommons-io-2.11.0-src/src/test/java/org/apache/commons/io/serialization/AbstractCloseableListTest.ja0100644 0000000 0000000 00000003514 13612062727 034033 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.commons.io.serialization; import java.io.Closeable; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; /** * Test base class that keeps track of Closeable objects and cleans them up. */ public abstract class AbstractCloseableListTest { private final List closeableList = new ArrayList<>(); /** * Adds a Closeable to close after each test. * * @param The Closeable type * @param t The Closeable. * @return The Closeable. */ protected T closeAfterEachTest(final T t) { closeableList.add(t); return t; } @BeforeEach public void setup() { closeableList.clear(); } @AfterEach public void cleanup() { for (final Closeable c : closeableList) { try { c.close(); } catch (final IOException ignored) { // ignore } } } }././@LongLink0100644 0000000 0000000 00000000146 13612062727 011642 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/java/org/apache/commons/io/serialization/FullClassNameMatcherTest.javacommons-io-2.11.0-src/src/test/java/org/apache/commons/io/serialization/FullClassNameMatcherTest.jav0100644 0000000 0000000 00000003026 13612062727 034003 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.commons.io.serialization; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; public class FullClassNameMatcherTest { private static final String [] NAMES_ARRAY = { Integer.class.getName(), Long.class.getName() }; @Test public void noNames() { final FullClassNameMatcher m = new FullClassNameMatcher(); assertFalse(m.matches(Integer.class.getName())); } @Test public void withNames() { final FullClassNameMatcher m = new FullClassNameMatcher(NAMES_ARRAY); assertTrue(m.matches(Integer.class.getName())); assertFalse(m.matches(String.class.getName())); } }commons-io-2.11.0-src/src/test/java/org/apache/commons/io/serialization/MockSerializedClass.java0100644 0000000 0000000 00000002607 13612062727 033206 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.commons.io.serialization; import java.io.Serializable; public class MockSerializedClass implements Serializable { private static final long serialVersionUID = 2139985988735372175L; private final String str; MockSerializedClass(final String str) { this.str = str; } @Override public int hashCode() { return str.hashCode(); } @Override public boolean equals(final Object obj) { if(!(obj instanceof MockSerializedClass)) { return false; } return str.equals(((MockSerializedClass)obj).str); } }commons-io-2.11.0-src/src/test/java/org/apache/commons/io/serialization/MoreComplexObject.java0100644 0000000 0000000 00000003653 13612062727 032676 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.commons.io.serialization; import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Random; import java.util.UUID; /** A test class that uses various java.* member objects, * to show which settings are necessary to deserialize * those. */ public class MoreComplexObject implements Serializable { private static final long serialVersionUID = -5187124661539240729L; private final Random random = new Random(System.currentTimeMillis()); private final String string = UUID.randomUUID().toString(); private final Integer integer = random.nextInt(); private final int pInt = random.nextInt(); private final long pLong = random.nextLong(); private final Integer [] intArray = { random.nextInt(), random.nextInt() }; private final List boolList = new ArrayList<>(); MoreComplexObject() { for(int i=0 ; i < 5; i++) { boolList.add(random.nextBoolean()); } } @Override public String toString() { return string + integer + pInt + pLong + Arrays.asList(intArray) + boolList; } }commons-io-2.11.0-src/src/test/java/org/apache/commons/io/serialization/MoreComplexObjectTest.java0100644 0000000 0000000 00000010054 13612062727 033527 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.commons.io.serialization; import static org.junit.jupiter.api.Assertions.assertEquals; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.util.ArrayList; import java.util.Random; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** This is more an example than a test - deserialize our {@link MoreComplexObject} * to verify which settings it requires, as the object uses a number of primitive * and java.* member objects. */ public class MoreComplexObjectTest extends AbstractCloseableListTest { private InputStream inputStream; private MoreComplexObject original; @BeforeEach public void setupMoreComplexObject() throws IOException { original = new MoreComplexObject(); final ByteArrayOutputStream bos = closeAfterEachTest(new ByteArrayOutputStream()); final ObjectOutputStream oos = closeAfterEachTest(new ObjectOutputStream(bos)); oos.writeObject(original); inputStream = closeAfterEachTest(new ByteArrayInputStream(bos.toByteArray())); } private void assertSerialization(final ObjectInputStream ois) throws ClassNotFoundException, IOException { final MoreComplexObject copy = (MoreComplexObject) (ois.readObject()); assertEquals(original.toString(), copy.toString(), "Expecting same data after deserializing"); } /** Trusting java.lang.* and the array variants of that means we have * to define a number of accept classes explicitly. Quite safe but * might become a bit verbose. */ @Test public void trustJavaLang() throws IOException, ClassNotFoundException { assertSerialization(closeAfterEachTest( new ValidatingObjectInputStream(inputStream) .accept(MoreComplexObject.class, ArrayList.class, Random.class) .accept("java.lang.*","[Ljava.lang.*") )); } /** Trusting java.* is probably reasonable and avoids having to be too * detailed in the accepts. */ @Test public void trustJavaIncludingArrays() throws IOException, ClassNotFoundException { assertSerialization(closeAfterEachTest( new ValidatingObjectInputStream(inputStream) .accept(MoreComplexObject.class) .accept("java.*","[Ljava.*") )); } /** Here we accept everything but reject specific classes, using a pure * blacklist mode. * * That's not as safe as it's hard to get an exhaustive blacklist, but * might be ok in controlled environments. */ @Test public void useBlacklist() throws IOException, ClassNotFoundException { final String [] blacklist = { "org.apache.commons.collections.functors.InvokerTransformer", "org.codehaus.groovy.runtime.ConvertedClosure", "org.codehaus.groovy.runtime.MethodClosure", "org.springframework.beans.factory.ObjectFactory" }; assertSerialization(closeAfterEachTest( new ValidatingObjectInputStream(inputStream) .accept("*") .reject(blacklist) )); } }././@LongLink0100644 0000000 0000000 00000000150 13612062727 011635 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/java/org/apache/commons/io/serialization/RegexpClassNameMatcherTest.javacommons-io-2.11.0-src/src/test/java/org/apache/commons/io/serialization/RegexpClassNameMatcherTest.j0100644 0000000 0000000 00000004336 13612062727 034011 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.commons.io.serialization; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.regex.Pattern; import org.junit.jupiter.api.Test; public class RegexpClassNameMatcherTest { @Test public void testSimplePatternFromString() { final ClassNameMatcher ca = new RegexpClassNameMatcher("foo.*"); assertTrue(ca.matches("foo.should.match")); assertFalse(ca.matches("bar.should.not.match")); } @Test public void testSimplePatternFromPattern() { final ClassNameMatcher ca = new RegexpClassNameMatcher(Pattern.compile("foo.*")); assertTrue(ca.matches("foo.should.match")); assertFalse(ca.matches("bar.should.not.match")); } @Test public void testOrPattern() { final ClassNameMatcher ca = new RegexpClassNameMatcher("foo.*|bar.*"); assertTrue(ca.matches("foo.should.match")); assertTrue(ca.matches("bar.should.match")); assertFalse(ca.matches("zoo.should.not.match")); } @Test public void testNullStringPattern() { assertThrows(NullPointerException.class, () -> new RegexpClassNameMatcher((String)null)); } @Test public void testNullPatternPattern() { assertThrows(IllegalArgumentException.class, () -> new RegexpClassNameMatcher((Pattern)null)); } }././@LongLink0100644 0000000 0000000 00000000155 13612062727 011642 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/java/org/apache/commons/io/serialization/ValidatingObjectInputStreamTest.javacommons-io-2.11.0-src/src/test/java/org/apache/commons/io/serialization/ValidatingObjectInputStreamT0100644 0000000 0000000 00000017540 13612062727 034126 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.commons.io.serialization; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InvalidClassException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.util.UUID; import java.util.regex.Pattern; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; public class ValidatingObjectInputStreamTest extends AbstractCloseableListTest { private MockSerializedClass testObject; private InputStream testStream; private static final ClassNameMatcher ALWAYS_TRUE = className -> true; @BeforeEach public void setupMockSerializedClass() throws IOException { testObject = new MockSerializedClass(UUID.randomUUID().toString()); final ByteArrayOutputStream bos = closeAfterEachTest(new ByteArrayOutputStream()); final ObjectOutputStream oos = closeAfterEachTest(new ObjectOutputStream(bos)); oos.writeObject(testObject); testStream = closeAfterEachTest(new ByteArrayInputStream(bos.toByteArray())); } private void assertSerialization(final ObjectInputStream ois) throws ClassNotFoundException, IOException { final MockSerializedClass result = (MockSerializedClass) (ois.readObject()); assertEquals(testObject, result); } @Test public void noAccept() { assertThrows(InvalidClassException.class, () -> assertSerialization( closeAfterEachTest(new ValidatingObjectInputStream(testStream)))); } @Test public void exceptionIncludesClassName() throws Exception { try { assertSerialization( closeAfterEachTest(new ValidatingObjectInputStream(testStream))); fail("Expected an InvalidClassException"); } catch(final InvalidClassException ice) { final String name = MockSerializedClass.class.getName(); assertTrue(ice.getMessage().contains(name), "Expecting message to contain " + name); } } @Test public void acceptCustomMatcher() throws Exception { assertSerialization( closeAfterEachTest(new ValidatingObjectInputStream(testStream)) .accept(ALWAYS_TRUE) ); } @Test public void rejectCustomMatcher() { assertThrows(InvalidClassException.class, () -> assertSerialization( closeAfterEachTest(new ValidatingObjectInputStream(testStream)) .accept(MockSerializedClass.class) .reject(ALWAYS_TRUE) )); } @Test public void acceptPattern() throws Exception { assertSerialization( closeAfterEachTest(new ValidatingObjectInputStream(testStream)) .accept(Pattern.compile(".*MockSerializedClass.*")) ); } @Test public void rejectPattern() { assertThrows(InvalidClassException.class, () -> assertSerialization( closeAfterEachTest(new ValidatingObjectInputStream(testStream)) .accept(MockSerializedClass.class) .reject(Pattern.compile("org.*")) )); } @Test public void acceptWildcard() throws Exception { assertSerialization( closeAfterEachTest(new ValidatingObjectInputStream(testStream)) .accept("org.apache.commons.io.*") ); } @Test public void rejectWildcard() { assertThrows(InvalidClassException.class, () -> assertSerialization( closeAfterEachTest(new ValidatingObjectInputStream(testStream)) .accept(MockSerializedClass.class) .reject("org.*") )); } @Test public void ourTestClassNotAccepted() { assertThrows(InvalidClassException.class, () -> assertSerialization( closeAfterEachTest(new ValidatingObjectInputStream(testStream)) .accept(Integer.class) )); } @Test public void ourTestClassOnlyAccepted() throws Exception { assertSerialization( closeAfterEachTest(new ValidatingObjectInputStream(testStream)) .accept(MockSerializedClass.class) ); } @Test public void ourTestClassAcceptedFirst() throws Exception { assertSerialization( closeAfterEachTest(new ValidatingObjectInputStream(testStream)) .accept(MockSerializedClass.class, Integer.class) ); } @Test public void ourTestClassAcceptedSecond() throws Exception { assertSerialization( closeAfterEachTest(new ValidatingObjectInputStream(testStream)) .accept(Integer.class, MockSerializedClass.class) ); } @Test public void ourTestClassAcceptedFirstWildcard() throws Exception { assertSerialization( closeAfterEachTest(new ValidatingObjectInputStream(testStream)) .accept("*MockSerializedClass","*Integer") ); } @Test public void ourTestClassAcceptedSecondWildcard() throws Exception { assertSerialization( closeAfterEachTest(new ValidatingObjectInputStream(testStream)) .accept("*Integer","*MockSerializedClass") ); } @Test public void reject() { assertThrows(InvalidClassException.class, () -> assertSerialization( closeAfterEachTest(new ValidatingObjectInputStream(testStream)) .accept(Long.class) .reject(MockSerializedClass.class, Integer.class) )); } @Test public void rejectPrecedence() { assertThrows(InvalidClassException.class, () -> assertSerialization( closeAfterEachTest(new ValidatingObjectInputStream(testStream)) .accept(MockSerializedClass.class) .reject(MockSerializedClass.class, Integer.class) )); } @Test public void rejectOnly() { assertThrows(InvalidClassException.class, () -> assertSerialization( closeAfterEachTest(new ValidatingObjectInputStream(testStream)) .reject(Integer.class) )); } @Test public void customInvalidMethod() { class CustomVOIS extends ValidatingObjectInputStream { CustomVOIS(final InputStream is) throws IOException { super(is); } @Override protected void invalidClassNameFound(final String className) throws InvalidClassException { throw new RuntimeException("Custom exception"); } } assertThrows(RuntimeException.class, () -> assertSerialization( closeAfterEachTest(new CustomVOIS(testStream)) .reject(Integer.class) )); } }././@LongLink0100644 0000000 0000000 00000000152 13612062727 011637 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/java/org/apache/commons/io/serialization/WildcardClassNameMatcherTest.javacommons-io-2.11.0-src/src/test/java/org/apache/commons/io/serialization/WildcardClassNameMatcherTest0100644 0000000 0000000 00000003435 13612062727 034057 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.commons.io.serialization; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; public class WildcardClassNameMatcherTest { @Test public void noPattern() { final ClassNameMatcher ca = new WildcardClassNameMatcher("org.foo"); assertTrue(ca.matches("org.foo")); assertFalse(ca.matches("org.foo.and.more")); assertFalse(ca.matches("org_foo")); } @Test public void star() { final ClassNameMatcher ca = new WildcardClassNameMatcher("org*"); assertTrue(ca.matches("org.foo.should.match")); assertFalse(ca.matches("bar.should.not.match")); } @Test public void starAndQuestionMark() { final ClassNameMatcher ca = new WildcardClassNameMatcher("org?apache?something*"); assertTrue(ca.matches("org.apache_something.more")); assertFalse(ca.matches("org..apache_something.more")); } }commons-io-2.11.0-src/src/test/java/org/apache/commons/io/test/TestUtils.java0100644 0000000 0000000 00000022022 13612062727 027346 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.test; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.io.Reader; import java.io.Writer; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.util.Arrays; import org.apache.commons.io.FileUtils; import org.apache.commons.io.output.ByteArrayOutputStream; /** * Base class for testcases doing tests with files. */ public abstract class TestUtils { /** * Assert that the content of a file is equal to that in a byte[]. * * @param b0 the expected contents * @param file the file to check * @throws IOException If an I/O error occurs while reading the file contents */ public static void assertEqualContent(final byte[] b0, final File file) throws IOException { int count = 0, numRead = 0; final byte[] b1 = new byte[b0.length]; try (InputStream is = Files.newInputStream(file.toPath())) { while (count < b0.length && numRead >= 0) { numRead = is.read(b1, count, b0.length); count += numRead; } assertEquals(b0.length, count, "Different number of bytes: "); for (int i = 0; i < count; i++) { assertEquals(b0[i], b1[i], "byte " + i + " differs"); } } } /** * Assert that the content of a file is equal to that in a char[]. * * @param c0 the expected contents * @param file the file to check * @throws IOException If an I/O error occurs while reading the file contents */ public static void assertEqualContent(final char[] c0, final File file) throws IOException { int count = 0, numRead = 0; final char[] c1 = new char[c0.length]; try (Reader ir = Files.newBufferedReader(file.toPath())) { while (count < c0.length && numRead >= 0) { numRead = ir.read(c1, count, c0.length); count += numRead; } assertEquals(c0.length, count, "Different number of chars: "); for (int i = 0; i < count; i++) { assertEquals(c0[i], c1[i], "char " + i + " differs"); } } } /** * Assert that the content of two files is the same. */ private static void assertEqualContent(final File f0, final File f1) throws IOException { /* This doesn't work because the filesize isn't updated until the file * is closed. assertTrue( "The files " + f0 + " and " + f1 + " have differing file sizes (" + f0.length() + " vs " + f1.length() + ")", ( f0.length() == f1.length() ) ); */ try (InputStream is0 = Files.newInputStream(f0.toPath())) { try (InputStream is1 = Files.newInputStream(f1.toPath())) { final byte[] buf0 = new byte[1024]; final byte[] buf1 = new byte[1024]; int n0 = 0; int n1; while (-1 != n0) { n0 = is0.read(buf0); n1 = is1.read(buf1); assertTrue((n0 == n1), "The files " + f0 + " and " + f1 + " have differing number of bytes available (" + n0 + " vs " + n1 + ")"); assertArrayEquals(buf0, buf1, "The files " + f0 + " and " + f1 + " have different content"); } } } } public static void checkFile(final File file, final File referenceFile) throws Exception { assertTrue(file.exists(), "Check existence of output file"); assertEqualContent(referenceFile, file); } public static void checkWrite(final OutputStream output) { try { new java.io.PrintStream(output).write(0); } catch (final Throwable t) { fail("The copy() method closed the stream when it shouldn't have. " + t.getMessage()); } } public static void checkWrite(final Writer output) { try { new java.io.PrintWriter(output).write('a'); } catch (final Throwable t) { fail("The copy() method closed the stream when it shouldn't have. " + t.getMessage()); } } public static void createFile(final File file, final long size) throws IOException { if (!file.getParentFile().exists()) { throw new IOException("Cannot create file " + file + " as the parent directory does not exist"); } try (final BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(file.toPath()))) { generateTestData(output, size); } } public static void createLineBasedFile(final File file, final String[] data) throws IOException { if (file.getParentFile() != null && !file.getParentFile().exists()) { throw new IOException("Cannot create file " + file + " as the parent directory does not exist"); } try (final PrintWriter output = new PrintWriter(new OutputStreamWriter(Files.newOutputStream(file.toPath()), StandardCharsets.UTF_8))) { for (final String element : data) { output.println(element); } } } public static void deleteFile(final File file) { if (file.exists()) { assertTrue(file.delete(), "Couldn't delete file: " + file); } } public static void generateTestData(final File file, final long size) throws IOException, FileNotFoundException { try (final BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(file.toPath()))) { generateTestData(output, size); } } public static byte[] generateTestData(final long size) { try { try (final ByteArrayOutputStream baout = new ByteArrayOutputStream()) { generateTestData(baout, size); return baout.toByteArray(); } } catch (final IOException ioe) { throw new IllegalStateException("This should never happen: " + ioe.getMessage(), ioe); } } public static void generateTestData(final OutputStream out, final long size) throws IOException { for (int i = 0; i < size; i++) { // output.write((byte)'X'); // nice varied byte pattern compatible with Readers and Writers out.write((byte) ((i % 127) + 1)); } } public static File newFile(final File testDirectory, final String filename) throws IOException { final File destination = new File(testDirectory, filename); /* assertTrue( filename + "Test output data file shouldn't previously exist", !destination.exists() ); */ if (destination.exists()) { FileUtils.forceDelete(destination); } return destination; } /** * Sleep for a guaranteed number of milliseconds unless interrupted. * * This method exists because Thread.sleep(100) can sleep for 0, 70, 100 or 200ms or anything else * it deems appropriate. Read the docs on Thread.sleep for further details. * * @param millis the number of milliseconds to sleep for * @throws InterruptedException if interrupted */ public static void sleep(final long millis) throws InterruptedException { final long finishAtMillis = System.currentTimeMillis() + millis; long remainingMillis = millis; do { Thread.sleep(remainingMillis); remainingMillis = finishAtMillis - System.currentTimeMillis(); } while (remainingMillis > 0); } public static void sleepQuietly(final long millis) { try { sleep(millis); } catch (final InterruptedException ignored){ // ignore InterruptedException. } } private TestUtils() { } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/test/ThrowOnCloseInputStream.java0100644 0000000 0000000 00000003137 13612062727 032176 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.test; import java.io.IOException; import java.io.InputStream; import org.apache.commons.io.input.NullInputStream; import org.apache.commons.io.input.ProxyInputStream; /** * Helper class for checking behavior of IO classes. */ public class ThrowOnCloseInputStream extends ProxyInputStream { /** * Default ctor. */ @SuppressWarnings("resource") public ThrowOnCloseInputStream() { super(new NullInputStream()); } /** * @param proxy InputStream to delegate to. */ public ThrowOnCloseInputStream(final InputStream proxy) { super(proxy); } /** @see java.io.InputStream#close() */ @Override public void close() throws IOException { throw new IOException(getClass().getSimpleName() + ".close() called."); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/test/ThrowOnCloseOutputStream.java0100644 0000000 0000000 00000003127 13612062727 032376 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.test; import java.io.IOException; import java.io.OutputStream; import org.apache.commons.io.output.NullOutputStream; import org.apache.commons.io.output.ProxyOutputStream; /** * Helper class for checking behavior of IO classes. */ public class ThrowOnCloseOutputStream extends ProxyOutputStream { /** * Default ctor. */ public ThrowOnCloseOutputStream() { super(NullOutputStream.NULL_OUTPUT_STREAM); } /** * @param proxy OutputStream to delegate to. */ public ThrowOnCloseOutputStream(final OutputStream proxy) { super(proxy); } /** @see java.io.OutputStream#close() */ @Override public void close() throws IOException { throw new IOException(getClass().getSimpleName() + ".close() called."); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/test/ThrowOnCloseReader.java0100644 0000000 0000000 00000003050 13612062727 031117 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.test; import java.io.IOException; import java.io.Reader; import org.apache.commons.io.input.NullReader; import org.apache.commons.io.input.ProxyReader; /** * Helper class for checking behavior of IO classes. */ public class ThrowOnCloseReader extends ProxyReader { /** * Default ctor. */ @SuppressWarnings("resource") public ThrowOnCloseReader() { super(new NullReader()); } /** * @param proxy Reader to delegate to. */ public ThrowOnCloseReader(final Reader proxy) { super(proxy); } /** @see java.io.Reader#close() */ @Override public void close() throws IOException { throw new IOException(getClass().getSimpleName() + ".close() called."); } } commons-io-2.11.0-src/src/test/java/org/apache/commons/io/test/ThrowOnCloseWriter.java0100644 0000000 0000000 00000003016 13612062727 031173 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.test; import java.io.IOException; import java.io.Writer; import org.apache.commons.io.output.NullWriter; import org.apache.commons.io.output.ProxyWriter; /** * Helper class for checking behavior of IO classes. */ public class ThrowOnCloseWriter extends ProxyWriter { /** * Default ctor. */ public ThrowOnCloseWriter() { super(NullWriter.NULL_WRITER); } /** * @param proxy Writer to delegate to. */ public ThrowOnCloseWriter(final Writer proxy) { super(proxy); } /** @see java.io.Writer#close() */ @Override public void close() throws IOException { throw new IOException(getClass().getSimpleName() + ".close() called."); } } ././@LongLink0100644 0000000 0000000 00000000145 13612062727 011641 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/java/org/apache/commons/io/test/ThrowOnFlushAndCloseOutputStream.javacommons-io-2.11.0-src/src/test/java/org/apache/commons/io/test/ThrowOnFlushAndCloseOutputStream.java0100644 0000000 0000000 00000004242 13612062727 034022 0ustar00rootroot0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.io.test; import static org.junit.jupiter.api.Assertions.fail; import java.io.IOException; import java.io.OutputStream; import org.apache.commons.io.output.ProxyOutputStream; /** * Helper class for checking behavior of IO classes. */ public class ThrowOnFlushAndCloseOutputStream extends ProxyOutputStream { private boolean throwOnFlush; private boolean throwOnClose; /** * @param proxy OutputStream to delegate to. * @param throwOnFlush True if flush() is forbidden * @param throwOnClose True if close() is forbidden */ public ThrowOnFlushAndCloseOutputStream(final OutputStream proxy, final boolean throwOnFlush, final boolean throwOnClose) { super(proxy); this.throwOnFlush = throwOnFlush; this.throwOnClose = throwOnClose; } /** @see java.io.OutputStream#flush() */ @Override public void flush() throws IOException { if (throwOnFlush) { fail(getClass().getSimpleName() + ".flush() called."); } super.flush(); } /** @see java.io.OutputStream#close() */ @Override public void close() throws IOException { if (throwOnClose) { fail(getClass().getSimpleName() + ".close() called."); } super.close(); } public void off() { throwOnFlush = false; throwOnClose = false; } } ././@LongLink0100644 0000000 0000000 00000000204 13612062727 011635 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files1/directory-files-only1/file1.txtcommons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files1/0100644 0000000 0000000 00000000001 13612062727 033513 0ustar00rootroot0000000 0000000 1././@LongLink0100644 0000000 0000000 00000000204 13612062727 011635 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files1/directory-files-only1/file2.txtcommons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files1/0100644 0000000 0000000 00000000001 13612062727 033513 0ustar00rootroot0000000 0000000 2././@LongLink0100644 0000000 0000000 00000000156 13612062727 011643 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files1/file1.txtcommons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files1/0100644 0000000 0000000 00000000001 13612062727 033513 0ustar00rootroot0000000 0000000 1././@LongLink0100644 0000000 0000000 00000000156 13612062727 011643 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files1/file2.txtcommons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files1/0100644 0000000 0000000 00000000001 13612062727 033513 0ustar00rootroot0000000 0000000 2././@LongLink0100644 0000000 0000000 00000000204 13612062727 011635 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files2/directory-files-only2/file1.txtcommons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files2/0100644 0000000 0000000 00000000001 13612062727 033514 0ustar00rootroot0000000 0000000 1././@LongLink0100644 0000000 0000000 00000000204 13612062727 011635 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files2/directory-files-only2/file2.txtcommons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files2/0100644 0000000 0000000 00000000001 13612062727 033514 0ustar00rootroot0000000 0000000 2././@LongLink0100644 0000000 0000000 00000000156 13612062727 011643 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files2/file1.txtcommons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files2/0100644 0000000 0000000 00000000001 13612062727 033514 0ustar00rootroot0000000 0000000 1././@LongLink0100644 0000000 0000000 00000000156 13612062727 011643 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files2/file2.txtcommons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-dirs-and-files/dirs-and-files2/0100644 0000000 0000000 00000000001 13612062727 033514 0ustar00rootroot0000000 0000000 2././@LongLink0100644 0000000 0000000 00000000172 13612062727 011641 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/dir1/directory-files-only1/file1.txtcommons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/dir1/directory-0100644 0000000 0000000 00000000001 13612062727 033666 0ustar00rootroot0000000 0000000 1././@LongLink0100644 0000000 0000000 00000000172 13612062727 011641 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/dir1/directory-files-only1/file2.txtcommons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/dir1/directory-0100644 0000000 0000000 00000000001 13612062727 033666 0ustar00rootroot0000000 0000000 2././@LongLink0100644 0000000 0000000 00000000172 13612062727 011641 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/dir2/directory-files-only1/file1.txtcommons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/dir2/directory-0100644 0000000 0000000 00000000001 13612062727 033667 0ustar00rootroot0000000 0000000 1././@LongLink0100644 0000000 0000000 00000000172 13612062727 011641 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/dir2/directory-files-only1/file2.txtcommons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/dir2/directory-0100644 0000000 0000000 00000000001 13612062727 033667 0ustar00rootroot0000000 0000000 2././@LongLink0100644 0000000 0000000 00000000165 13612062727 011643 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/directory-files-only1/file1.txtcommons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/directory-files0100644 0000000 0000000 00000000001 13612062727 034052 0ustar00rootroot0000000 0000000 1././@LongLink0100644 0000000 0000000 00000000165 13612062727 011643 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/directory-files-only1/file2.txtcommons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/directory-files0100644 0000000 0000000 00000000001 13612062727 034052 0ustar00rootroot0000000 0000000 2././@LongLink0100644 0000000 0000000 00000000165 13612062727 011643 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/directory-files-only2/file1.txtcommons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/directory-files0100644 0000000 0000000 00000000001 13612062727 034052 0ustar00rootroot0000000 0000000 1././@LongLink0100644 0000000 0000000 00000000165 13612062727 011643 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/directory-files-only2/file2.txtcommons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-dirs-then-files/directory-files0100644 0000000 0000000 00000000001 13612062727 034052 0ustar00rootroot0000000 0000000 2././@LongLink0100644 0000000 0000000 00000000160 13612062727 011636 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-files-only/directory-files-only1/file1.txtcommons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-files-only/directory-files-only0100644 0000000 0000000 00000000001 13612062727 034115 0ustar00rootroot0000000 0000000 1././@LongLink0100644 0000000 0000000 00000000160 13612062727 011636 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-files-only/directory-files-only1/file2.txtcommons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-files-only/directory-files-only0100644 0000000 0000000 00000000001 13612062727 034115 0ustar00rootroot0000000 0000000 2././@LongLink0100644 0000000 0000000 00000000160 13612062727 011636 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-files-only/directory-files-only2/file1.txtcommons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-files-only/directory-files-only0100644 0000000 0000000 00000000001 13612062727 034115 0ustar00rootroot0000000 0000000 1././@LongLink0100644 0000000 0000000 00000000160 13612062727 011636 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-files-only/directory-files-only2/file2.txtcommons-io-2.11.0-src/src/test/resources/dir-equals-tests/dir-equals-files-only/directory-files-only0100644 0000000 0000000 00000000001 13612062727 034115 0ustar00rootroot0000000 0000000 2commons-io-2.11.0-src/src/test/resources/org/apache/commons/io/CharSequenceReader.bin0100644 0000000 0000000 00000000213 13612062727 031036 0ustar00rootroot0000000 0000000 sr.org.apache.commons.io.input.CharSequenceReader3n:IidxImarkL charSequencetLjava/lang/CharSequence;xptFooBarcommons-io-2.11.0-src/src/test/resources/org/apache/commons/io/FileUtilsTestDataCR.dat0100644 0000000 0000000 00000000006 13612062727 031124 0ustar00rootroot0000000 0000000 1 2 3 commons-io-2.11.0-src/src/test/resources/org/apache/commons/io/FileUtilsTestDataCRLF.dat0100644 0000000 0000000 00000000011 13612062727 031342 0ustar00rootroot0000000 0000000 1 2 3 commons-io-2.11.0-src/src/test/resources/org/apache/commons/io/FileUtilsTestDataLF.dat0100644 0000000 0000000 00000000006 13612062727 031121 0ustar00rootroot0000000 0000000 1 2 3 commons-io-2.11.0-src/src/test/resources/org/apache/commons/io/abitmorethan16k.txt0100644 0000000 0000000 00000041770 13612062727 030430 0ustar00rootroot0000000 0000000 ## Licensed to the Apache Software Foundation (ASF) under one ## or more contributor license agreements. See the NOTICE file ## distributed with this work for additional information ## regarding copyright ownership. The ASF licenses this file ## to you under the Apache License, Version 2.0 (the ## "License"); you may not use this file except in compliance ## with the License. You may obtain a copy of the License at ## ## http://www.apache.org/licenses/LICENSE-2.0 ## ## Unless required by applicable law or agreed to in writing, ## software distributed under the License is distributed on an ## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY ## KIND, either express or implied. See the License for the ## specific language governing permissions and limitations ## under the License. a bit more than 16 K 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 commons-io-2.11.0-src/src/test/resources/org/apache/commons/io/abitmorethan16kcopy.txt0100644 0000000 0000000 00000041770 13612062727 031323 0ustar00rootroot0000000 0000000 ## Licensed to the Apache Software Foundation (ASF) under one ## or more contributor license agreements. See the NOTICE file ## distributed with this work for additional information ## regarding copyright ownership. The ASF licenses this file ## to you under the Apache License, Version 2.0 (the ## "License"); you may not use this file except in compliance ## with the License. You may obtain a copy of the License at ## ## http://www.apache.org/licenses/LICENSE-2.0 ## ## Unless required by applicable law or agreed to in writing, ## software distributed under the License is distributed on an ## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY ## KIND, either express or implied. See the License for the ## specific language governing permissions and limitations ## under the License. a bit more than 16 K 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 012345679 commons-io-2.11.0-src/src/test/resources/org/apache/commons/io/dirs-1-file-size-0/file-size-0.bin0100644 0000000 0000000 00000000000 13612062727 032504 0ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/test/resources/org/apache/commons/io/dirs-1-file-size-1/file-size-1.bin0100644 0000000 0000000 00000000001 13612062727 032507 0ustar00rootroot0000000 0000000 a././@LongLink0100644 0000000 0000000 00000000165 13612062727 011643 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/resources/org/apache/commons/io/dirs-2-file-size-2/dirs-a-file-size-1/file-size-1.bincommons-io-2.11.0-src/src/test/resources/org/apache/commons/io/dirs-2-file-size-2/dirs-a-file-size-10100644 0000000 0000000 00000000001 13612062727 033117 0ustar00rootroot0000000 0000000 a././@LongLink0100644 0000000 0000000 00000000165 13612062727 011643 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/resources/org/apache/commons/io/dirs-2-file-size-2/dirs-b-file-size-1/file-size-1.bincommons-io-2.11.0-src/src/test/resources/org/apache/commons/io/dirs-2-file-size-2/dirs-b-file-size-10100644 0000000 0000000 00000000001 13612062727 033120 0ustar00rootroot0000000 0000000 acommons-io-2.11.0-src/src/test/resources/org/apache/commons/io/io639-1.bin0100644 0000000 0000000 00000000011 13612062727 026350 0ustar00rootroot0000000 0000000 the test commons-io-2.11.0-src/src/test/resources/org/apache/commons/io/io639-2.bin0100644 0000000 0000000 00000000006 13612062727 026355 0ustar00rootroot0000000 0000000 test commons-io-2.11.0-src/src/test/resources/org/apache/commons/io/io639-3.bin0100644 0000000 0000000 00000000007 13612062727 026357 0ustar00rootroot0000000 0000000 test commons-io-2.11.0-src/src/test/resources/org/apache/commons/io/io639-4.bin0100644 0000000 0000000 00000000002 13612062727 026353 0ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/test/resources/org/apache/commons/io/io639-5.bin0100644 0000000 0000000 00000000001 13612062727 026353 0ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/test/resources/org/apache/commons/io/test-file-20byteslength.bin0100644 0000000 0000000 00000000024 13612062727 031731 0ustar00rootroot0000000 0000000 123456789 987654321 commons-io-2.11.0-src/src/test/resources/org/apache/commons/io/test-file-empty.bin0100644 0000000 0000000 00000000000 13612062727 030367 0ustar00rootroot0000000 0000000 commons-io-2.11.0-src/src/test/resources/org/apache/commons/io/test-file-gbk.bin0100644 0000000 0000000 00000000024 13612062727 030002 0ustar00rootroot0000000 0000000 ݔӾ ././@LongLink0100644 0000000 0000000 00000000155 13612062727 011642 Lustar 0000000 0000000 commons-io-2.11.0-src/src/test/resources/org/apache/commons/io/test-file-iso8859-1-shortlines-win-linebr.bincommons-io-2.11.0-src/src/test/resources/org/apache/commons/io/test-file-iso8859-1-shortlines-win-li0100644 0000000 0000000 00000000033 13612062727 033343 0ustar00rootroot0000000 0000000 1 2 3 commons-io-2.11.0-src/src/test/resources/org/apache/commons/io/test-file-iso8859-1.bin0100644 0000000 0000000 00000002626 13612062727 030537 0ustar00rootroot0000000 0000000 A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars A Test Line. Special char A Test Line. Special cha A Test Line. Special ch A Test Line. Special c A Test Line. Special A Test Line. Special A Test Line. Specia A Test Line. Speci A Test Line. Spec A Test Line. Spe A Test Line. Sp A Test Line. S A Test Line. A Test Line. A Test Line A Test Lin A Test Li A Test L A Test A Test A Tes A Te A T A A commons-io-2.11.0-src/src/test/resources/org/apache/commons/io/test-file-shiftjis.bin0100644 0000000 0000000 00000000065 13612062727 031067 0ustar00rootroot0000000 0000000 Hiragana letters: Kanji letters: Aq commons-io-2.11.0-src/src/test/resources/org/apache/commons/io/test-file-simple-utf8.bin0100644 0000000 0000000 00000000005 13612062727 031413 0ustar00rootroot0000000 0000000 ABC commons-io-2.11.0-src/src/test/resources/org/apache/commons/io/test-file-utf16be.bin0100644 0000000 0000000 00000005454 13612062727 030527 0ustar00rootroot0000000 0000000 A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars A Test Line. Special char A Test Line. Special cha A Test Line. Special ch A Test Line. Special c A Test Line. Special A Test Line. Special A Test Line. Specia A Test Line. Speci A Test Line. Spec A Test Line. Spe A Test Line. Sp A Test Line. S A Test Line. A Test Line. A Test Line A Test Lin A Test Li A Test L A Test A Test A Tes A Te A T A A commons-io-2.11.0-src/src/test/resources/org/apache/commons/io/test-file-utf16le.bin0100644 0000000 0000000 00000005454 13612062727 030541 0ustar00rootroot0000000 0000000 A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars A Test Line. Special char A Test Line. Special cha A Test Line. Special ch A Test Line. Special c A Test Line. Special A Test Line. Special A Test Line. Specia A Test Line. Speci A Test Line. Spec A Test Line. Spe A Test Line. Sp A Test Line. S A Test Line. A Test Line. A Test Line A Test Lin A Test Li A Test L A Test A Test A Tes A Te A T A A commons-io-2.11.0-src/src/test/resources/org/apache/commons/io/test-file-utf8-cr-only.bin0100644 0000000 0000000 00000003251 13612062727 031513 0ustar00rootroot0000000 0000000 A Test Line. Special chars: ÄäÜüÖöß Ãáéíïçñ ©µ¥£±²® A Test Line. Special chars: ÄäÜüÖöß Ãáéíïçñ ©µ¥£±² A Test Line. Special chars: ÄäÜüÖöß Ãáéíïçñ ©µ¥£± A Test Line. Special chars: ÄäÜüÖöß Ãáéíïçñ ©µ¥£ A Test Line. Special chars: ÄäÜüÖöß Ãáéíïçñ ©µ¥ A Test Line. Special chars: ÄäÜüÖöß Ãáéíïçñ ©µ A Test Line. Special chars: ÄäÜüÖöß Ãáéíïçñ © A Test Line. Special chars: ÄäÜüÖöß Ãáéíïçñ A Test Line. Special chars: ÄäÜüÖöß Ãáéíïçñ A Test Line. Special chars: ÄäÜüÖöß Ãáéíïçñ A Test Line. Special chars: ÄäÜüÖöß Ãáéíïç A Test Line. Special chars: ÄäÜüÖöß Ãáéíï A Test Line. Special chars: ÄäÜüÖöß Ãáéí A Test Line. Special chars: ÄäÜüÖöß Ãáé A Test Line. Special chars: ÄäÜüÖöß Ãá A Test Line. Special chars: ÄäÜüÖöß Ã A Test Line. Special chars: ÄäÜüÖöß A Test Line. Special chars: ÄäÜüÖöß A Test Line. Special chars: ÄäÜüÖö A Test Line. Special chars: ÄäÜüÖ A Test Line. Special chars: ÄäÜü A Test Line. Special chars: ÄäÜ A Test Line. Special chars: Ää A Test Line. Special chars: Ä A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars A Test Line. Special char A Test Line. Special cha A Test Line. Special ch A Test Line. Special c A Test Line. Special A Test Line. Special A Test Line. Specia A Test Line. Speci A Test Line. Spec A Test Line. Spe A Test Line. Sp A Test Line. S A Test Line. A Test Line. A Test Line A Test Lin A Test Li A Test L A Test A Test A Tes A Te A T A A commons-io-2.11.0-src/src/test/resources/org/apache/commons/io/test-file-utf8-win-linebr.bin0100644 0000000 0000000 00000003335 13612062727 032201 0ustar00rootroot0000000 0000000 A Test Line. Special chars: ÄäÜüÖöß Ãáéíïçñ ©µ¥£±²® A Test Line. Special chars: ÄäÜüÖöß Ãáéíïçñ ©µ¥£±² A Test Line. Special chars: ÄäÜüÖöß Ãáéíïçñ ©µ¥£± A Test Line. Special chars: ÄäÜüÖöß Ãáéíïçñ ©µ¥£ A Test Line. Special chars: ÄäÜüÖöß Ãáéíïçñ ©µ¥ A Test Line. Special chars: ÄäÜüÖöß Ãáéíïçñ ©µ A Test Line. Special chars: ÄäÜüÖöß Ãáéíïçñ © A Test Line. Special chars: ÄäÜüÖöß Ãáéíïçñ A Test Line. Special chars: ÄäÜüÖöß Ãáéíïçñ A Test Line. Special chars: ÄäÜüÖöß Ãáéíïçñ A Test Line. Special chars: ÄäÜüÖöß Ãáéíïç A Test Line. Special chars: ÄäÜüÖöß Ãáéíï A Test Line. Special chars: ÄäÜüÖöß Ãáéí A Test Line. Special chars: ÄäÜüÖöß Ãáé A Test Line. Special chars: ÄäÜüÖöß Ãá A Test Line. Special chars: ÄäÜüÖöß Ã A Test Line. Special chars: ÄäÜüÖöß A Test Line. Special chars: ÄäÜüÖöß A Test Line. Special chars: ÄäÜüÖö A Test Line. Special chars: ÄäÜüÖ A Test Line. Special chars: ÄäÜü A Test Line. Special chars: ÄäÜ A Test Line. Special chars: Ää A Test Line. Special chars: Ä A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars A Test Line. Special char A Test Line. Special cha A Test Line. Special ch A Test Line. Special c A Test Line. Special A Test Line. Special A Test Line. Specia A Test Line. Speci A Test Line. Spec A Test Line. Spe A Test Line. Sp A Test Line. S A Test Line. A Test Line. A Test Line A Test Lin A Test Li A Test L A Test A Test A Tes A Te A T A A commons-io-2.11.0-src/src/test/resources/org/apache/commons/io/test-file-utf8.bin0100644 0000000 0000000 00000003251 13612062727 030132 0ustar00rootroot0000000 0000000 A Test Line. Special chars: ÄäÜüÖöß Ãáéíïçñ ©µ¥£±²® A Test Line. Special chars: ÄäÜüÖöß Ãáéíïçñ ©µ¥£±² A Test Line. Special chars: ÄäÜüÖöß Ãáéíïçñ ©µ¥£± A Test Line. Special chars: ÄäÜüÖöß Ãáéíïçñ ©µ¥£ A Test Line. Special chars: ÄäÜüÖöß Ãáéíïçñ ©µ¥ A Test Line. Special chars: ÄäÜüÖöß Ãáéíïçñ ©µ A Test Line. Special chars: ÄäÜüÖöß Ãáéíïçñ © A Test Line. Special chars: ÄäÜüÖöß Ãáéíïçñ A Test Line. Special chars: ÄäÜüÖöß Ãáéíïçñ A Test Line. Special chars: ÄäÜüÖöß Ãáéíïçñ A Test Line. Special chars: ÄäÜüÖöß Ãáéíïç A Test Line. Special chars: ÄäÜüÖöß Ãáéíï A Test Line. Special chars: ÄäÜüÖöß Ãáéí A Test Line. Special chars: ÄäÜüÖöß Ãáé A Test Line. Special chars: ÄäÜüÖöß Ãá A Test Line. Special chars: ÄäÜüÖöß Ã A Test Line. Special chars: ÄäÜüÖöß A Test Line. Special chars: ÄäÜüÖöß A Test Line. Special chars: ÄäÜüÖö A Test Line. Special chars: ÄäÜüÖ A Test Line. Special chars: ÄäÜü A Test Line. Special chars: ÄäÜ A Test Line. Special chars: Ää A Test Line. Special chars: Ä A Test Line. Special chars: A Test Line. Special chars: A Test Line. Special chars A Test Line. Special char A Test Line. Special cha A Test Line. Special ch A Test Line. Special c A Test Line. Special A Test Line. Special A Test Line. Specia A Test Line. Speci A Test Line. Spec A Test Line. Spe A Test Line. Sp A Test Line. S A Test Line. A Test Line. A Test Line A Test Lin A Test Li A Test L A Test A Test A Tes A Te A T A A commons-io-2.11.0-src/src/test/resources/org/apache/commons/io/test-file-windows-31j.bin0100644 0000000 0000000 00000000026 13612062727 031326 0ustar00rootroot0000000 0000000 Aq commons-io-2.11.0-src/src/test/resources/org/apache/commons/io/test-file-x-windows-949.bin0100644 0000000 0000000 00000000022 13612062727 031517 0ustar00rootroot0000000 0000000 ѱ ѹα commons-io-2.11.0-src/src/test/resources/org/apache/commons/io/test-file-x-windows-950.bin0100644 0000000 0000000 00000000024 13612062727 031511 0ustar00rootroot0000000 0000000 l c餤 commons-io-2.11.0-src/src/test/resources/org/apache/commons/io/test.jar0100644 0000000 0000000 00000002115 13612062727 026333 0ustar00rootroot0000000 0000000 PKݤHR META-INF/PKPKݤHRMETA-INF/MANIFEST.MFMLK-. K-*ϳR03r.JM,IMu E,45yxPKm6w23PK HRdir1/PK HRdir1/f1PKnHR file1.txtHWTIM,NQ(I-.QMPK*cPK HRnext/PK HR next/dir/PKHRnext/dir/test.log34.*,H/,/7))460KO,NK)K,*044PKo)'PKvHRout.log34261534PK PKݤHR META-INF/PKݤHRm6w23=META-INF/MANIFEST.MFPK HRdir1/PK HRdir1/f1PKnHR*c file1.txtPK HRInext/PK HR lnext/dir/PKHRo)'next/dir/test.logPKvHR out.logPK =commons-io-2.11.0-src/src/test/resources/org/apache/commons/io/testfileBOM.xml0100644 0000000 0000000 00000015363 13612062727 027566 0ustar00rootroot0000000 0000000  Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo commons-io-2.11.0-src/src/test/resources/org/apache/commons/io/testfileNoBOM.xml0100644 0000000 0000000 00000015360 13612062727 030060 0ustar00rootroot0000000 0000000 Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo